Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
36c771518d | ||
|
|
dd7a3700dc | ||
|
|
f0736015a7 | ||
|
|
aae603d798 | ||
|
|
d9bc6309fb | ||
|
|
c14361919c | ||
|
|
b26c39cf21 | ||
|
|
ca2d17bd25 | ||
|
|
a243209c90 | ||
|
|
90435c07b4 | ||
|
|
46d09c7bd9 | ||
|
|
05036877ed | ||
|
|
98e8c7a10c | ||
|
|
19cabe816e | ||
|
|
706aa657b1 | ||
|
|
fd3f988a4f | ||
|
|
981282d809 | ||
|
|
fcce8b0a4b | ||
|
|
461a398965 | ||
|
|
eef0893d1a | ||
|
|
c50f1287b5 | ||
|
|
acd40f3154 | ||
|
|
764f9f81c8 | ||
|
|
70e8cd74a2 | ||
|
|
e96f4e01bd | ||
|
|
c44c2d7c96 | ||
|
|
e2ee73bc4e | ||
|
|
3f19886342 | ||
|
|
9a5afc918e | ||
|
|
2ac35ef5d1 | ||
|
|
33c6b35601 | ||
|
|
82f870db05 | ||
|
|
878efab321 | ||
|
|
659ddbd0a4 | ||
|
|
22b9e11021 | ||
|
|
02ec8880fc | ||
|
|
521cf50b7b | ||
|
|
1cc6fab3a9 | ||
|
|
7baccbabb9 | ||
|
|
d9b24b0f97 | ||
|
|
d504a0e131 | ||
|
|
09ca86a7fd | ||
|
|
5b68837023 | ||
|
|
7452c54c04 | ||
|
|
af1976b9d8 | ||
|
|
9fe45ce99f | ||
|
|
852964e77b | ||
|
|
b87dea1661 | ||
|
|
d2835c7472 | ||
|
|
f3c58424e5 | ||
|
|
c600eb3965 | ||
|
|
4a7848cb04 | ||
|
|
0d62b60e38 | ||
|
|
9b91850731 | ||
|
|
05c7a91f93 | ||
|
|
f83fdb3b8f | ||
|
|
020ff4b014 | ||
|
|
b3c7453823 | ||
|
|
18d003aa5d | ||
|
|
0b90badb5e | ||
|
|
290b5029d1 | ||
|
|
a7e4aea52d | ||
|
|
755d15509e | ||
|
|
02cea84ebb | ||
|
|
c47fc4f5b6 | ||
|
|
147e49f2cb | ||
|
|
7f4f942d50 | ||
|
|
8f4df1af56 | ||
|
|
77f2de2c5f | ||
|
|
e5e271e424 | ||
|
|
43ecca8be1 | ||
|
|
e21f7e398a | ||
|
|
e16f89743a | ||
|
|
a6c593c100 | ||
|
|
cd8e190082 | ||
|
|
f2106763c1 | ||
|
|
5da5cb0314 | ||
|
|
6d7f66569a | ||
|
|
3e8963b20b | ||
|
|
2cf5b06da8 | ||
|
|
68c01fc930 | ||
|
|
3bc1c4871b | ||
|
|
3d732e9a8a | ||
|
|
35f226af5c |
@@ -6,71 +6,70 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: localhost
|
||||
steps:
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
|
||||
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
|
||||
|
||||
#- uses: actions/checkout@v3
|
||||
- uses: RouxAntoine/checkout@v3.5.4
|
||||
with:
|
||||
ref: 'v13'
|
||||
- name: Add NODE/NPM bin directory to PATH
|
||||
shell: bash
|
||||
run: echo "/opt/alt/alt-nodejs20/root/usr/bin/" >> $GITHUB_PATH
|
||||
|
||||
# get part of the tag after the `v`
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
- uses: RouxAntoine/checkout@v3.5.4
|
||||
with:
|
||||
ref: "v13"
|
||||
|
||||
# Substitute the Manifest and Download URLs in the module.json
|
||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: 'system.json'
|
||||
env:
|
||||
version: ${{steps.get_version.outputs.version-without-v}}
|
||||
url: https://www.uberwald.me/gitea/${{gitea.repository}}
|
||||
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
|
||||
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
|
||||
# get part of the tag after the `v`
|
||||
- name: Extract tag version number
|
||||
id: get_version
|
||||
uses: battila7/get-version-action@v2
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '18' # Use the node version your project requires
|
||||
# Substitute the Manifest and Download URLs in the module.json
|
||||
- name: Substitute Manifest and Download Links For Versioned Ones
|
||||
id: sub_manifest_link_version
|
||||
uses: microsoft/variable-substitution@v1
|
||||
with:
|
||||
files: "system.json"
|
||||
env:
|
||||
version: ${{steps.get_version.outputs.version-without-v}}
|
||||
url: https://gitea.scriptarium.org/${{gitea.repository}}
|
||||
manifest: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
|
||||
download: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "18" # Use the node version your project requires
|
||||
|
||||
- name: Build the compendiums
|
||||
run: node ./tools/packCompendiumsToDist.mjs
|
||||
- name: Install dependencies
|
||||
run: npm install
|
||||
|
||||
# Create a zip file with all files required by the module to add to the release
|
||||
- run: |
|
||||
apt update -y
|
||||
apt install -y zip
|
||||
- name: Build the compendiums
|
||||
run: node ./tools/packCompendiumsToDist.mjs
|
||||
|
||||
- run: zip -r ./rddsystem.zip system.json template.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/
|
||||
- name: Create ZIP file
|
||||
run: zip -r ./rddsystem.zip system.json template.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/
|
||||
|
||||
- name: setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '>=1.20.1'
|
||||
- name: setup go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: ">=1.20.1"
|
||||
|
||||
- name: Use Go Action
|
||||
id: use-go-action
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: |-
|
||||
./rddsystem.zip
|
||||
system.json
|
||||
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'
|
||||
- name: Use Go Action
|
||||
id: use-go-action
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
files: |-
|
||||
./rddsystem.zip
|
||||
system.json
|
||||
api_key: "${{secrets.RDD_PUBLISH_RELEASE}}"
|
||||
|
||||
- name: Publish to Foundry server
|
||||
uses: djlechuck/foundryvtt-publish-package-action@v1
|
||||
with:
|
||||
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
|
||||
id: 'foundryvtt-reve-de-dragon'
|
||||
version: ${{github.event.release.tag_name}}
|
||||
manifest: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json'
|
||||
notes: 'https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v13/changelog.md'
|
||||
compatibility-minimum: '13'
|
||||
compatibility-verified: '13'
|
||||
- name: Publish to Foundry server
|
||||
uses: djlechuck/foundryvtt-publish-package-action@v1
|
||||
with:
|
||||
token: ${{ secrets.RDD_PUBLISH_RELEASE_FOUNDRY }}
|
||||
id: "foundryvtt-reve-de-dragon"
|
||||
version: ${{github.event.release.tag_name}}
|
||||
manifest: "https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json"
|
||||
notes: "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/raw/branch/v13/changelog.md"
|
||||
compatibility-minimum: "13"
|
||||
compatibility-verified: "13"
|
||||
|
||||
@@ -25,4 +25,7 @@ Merci à eux !!
|
||||
|
||||
Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT.
|
||||
|
||||
L'ensemble du code est sous licence Creative Commons.
|
||||
L'ensemble du code est sous licence Creative Commons.
|
||||
|
||||
# Licences
|
||||
- L'export pdf utilise la librairie [pdf-lib](https://pdf-lib.js.org/) sous licence [MIT](pdf-lib-LICENSE.md)
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><linearGradient x1="0" x2="1" y1="1" y2="0" id="lorc-shattered-sword-gradient-4"><stop offset="0%" stop-color="#4a4a4a" stop-opacity="1"></stop><stop offset="100%" stop-color="#c9c9c9" stop-opacity="1"></stop></linearGradient><radialGradient id="lorc-shattered-sword-gradient-5"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient><radialGradient id="lorc-shattered-sword-gradient-7"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient></defs><g class="" transform="translate(1,-2)" style=""><path d="m496.223 16.818-48.475 44.205 48.475 4.575v-48.78zm-41.55 1.22-68.91 11.28-7.04 65.547 75.95-76.828zM352.26 77.907l-87.887 50.3 15.447 41.026 82.662-16.87-10.222-74.456zm64.34 25.022-32.967 67.443 24.842 70.684 54.314-134.19-46.19-3.937zm-271.362 72.808c-10.02.155-20.714 3.165-30.79 9.057 4.143 8.863 3.382 18.708-2.776 24.873-6.158 6.165-15.993 6.927-24.846 2.78-12.923 22.167-11.88 47.34 2.485 61.73l29.84-29.87c58.655 42.87 109.37 92.94 150.57 151.24l-36.19 36.23 6.61-6.604c14.283 14.298 39.192 15.42 61.23 2.732-4.88-9.197-4.366-19.74 2.107-26.22 6.47-6.478 17-6.993 26.185-2.112 12.66-22.062 11.54-47-2.732-61.3l-28.248 28.28c-57.035-42.41-107.91-92.665-151.426-150.386l35.455-35.492-6.61 6.603c-7.834-7.843-18.863-11.726-30.862-11.542zm108.45 4.512c-17.61 17.41-39.674 39.21-62.22 61.375a728.952 728.952 0 0 0 27.407 30.094l59.063-59.126-24.25-32.344zm78.28 32.688L297 219.968l-65 65.063a728.12 728.12 0 0 0 35 32.376c22.02-23.134 43.764-46.41 64.97-69.406v-35.063zM173.47 313.25c-31.146 40.858-67.877 74.323-108.905 101.875 4.13 13.708 16.394 26.374 30.624 30.563 29.466-41.26 61.113-79.902 100.97-109.97a637.777 637.777 0 0 0-22.688-22.468zM44.5 410.28l-20.844 20.845c7.133 24.65 27.843 44.912 53.72 53.438l19.28-19.313c-26.948-4.28-48.314-26.91-51.875-52.938l-.28-2.03z" fill="#fff" fill-opacity="1" transform="translate(51.2, 51.2) scale(0.8, 0.8) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
@@ -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="m329.5 29.12-8.1 11.4L359 67.16l8.1-11.44zm-88 5.04 24.2 45.36 1.8 1.29 14.8-40.36zm57.6 12.63-16.4 44.8 40.7 28.81 35.3-31.54c-.9-.58-1.9-1.19-2.8-1.84zM59.83 48.56l10.84 45.83 29.63 2.6 2.7-29.63zM470.9 75.41c-5.6 4.71-12.2 8.59-19.5 11.74 5 46.45-14.7 83.45-45.2 109.75-26.5 22.9-60.9 38.4-95 47.9-2.5 4.8-5 9.2-7.4 13.1 41.5 5.4 93.2-21.2 129.2-60 19.8-21.3 34.8-45.9 41.1-69.2 5.2-19.4 4.7-37.42-3.2-53.29zm-351.3 8.71-3 32.48-32.35-2.9 226.55 271 20-16.7 15.3-12.8zM434 93.09c-4.2 1-8.5 2-12.8 2.7-14.9 2.5-30.1 3.1-43.5.3l-41 36.61c4 7 5 15.7 4.5 24.5-.6 12.6-4.3 26.7-9.3 40.9-3 8.3-6.3 16.6-9.9 24.6 26.9-9.2 52.6-22.3 72.5-39.4 26.2-22.8 42.5-51.6 39.5-90.21zM274 107.4l-51.2 72.2 30.6 36.5 58.2-82.1zM173.8 248.8 34.53 445.2l37.53 26.6L204.3 285.3zm233 79.2L273.3 439.5l19.2 23.1L426 351zm-18.3 77.9-35.3 29.4 39.7 47.6 35.3-29.4z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -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="M243.512 23.29c-27.105 18.337-53.533 32.92-82.274 45.337-2.843 17.364-3.948 34.497-4.05 51.584 28.913 15.41 56.096 32.85 83.33 49.634l7.045 4.344-3.432 7.482c-12.12 26.572-24.33 47.087-46.245 70.3l-5.184 5.512-6.46-3.904c-32.974-19.974-74.472-38.724-113.373-53.95l6.826-17.374c36.79 14.4 75.11 32.32 108.153 51.504 15.396-17.198 25.326-33.354 34.713-52.89-43.44-26.91-86.13-53.51-134.69-70.632-23.012 20.357-37.705 45.243-51.942 70.74 8.324 25.495 6.596 53.376-6.596 77.46 48.58-.593 97.994 2.23 150.666 10.26l5.658.837 1.787 5.44c8.85 26.46 11.79 54.41 8.325 83.588l-.987 8.432-8.466-.187c-40.508-.864-80.175-2.138-118.17.234 1.634 15.94-2.31 30.972-7.724 45.025 13.427 28.54 27.38 55.8 48.29 79.39 41.27-19.05 73.564-31.288 115.93-42.85-3.407-13.72-6.918-26.36-11.097-33.62-5.122-8.9-10.207-13.057-17.85-15.256-15.284-4.4-44.533 2.293-92.894 19.454l-6.243-17.594c48.907-17.354 79.702-26.894 104.283-19.82 9.133 2.628 16.884 8.004 23.066 15.46 14.487-7.627 28.415-16.79 42.053-26.996 12.34-45.92 37.29-81.42 66.626-112.107-7.226-13.52-13.208-27.204-20.563-40.613l-3.394-6.168 5-4.965c23.275-23.13 47.34-40.157 71.87-52.487l8.395 16.716c-20.952 10.53-41.503 25.913-61.795 45.152 12.41 23.91 22.263 45.5 39.457 64.826 37.488-27.124 74.943-51.39 116.84-74.938-13.96-30.473-31.345-58.357-56.286-79.462-32.2 13.38-62.527 17.39-92.61 12.29-14.223 13.25-30.094 22.23-48.756 23.337-29.017 1.722-60.74-15.74-99.174-57.672l6.858-6.295.017-.028.006.006 6.88-6.314c36.702 40.043 63.74 52.87 84.32 51.65 18.514-1.1 35.03-14.95 51.684-35.406-28.827-31.81-64.174-59.94-97.822-84.465zM39.324 277.884c-6.06.022-12.104.098-18.142.223 1.673 26.288 5.512 51.288 14.052 73.732 45.88-5.82 93.308-4.96 141.15-3.87 1.518-21.27-.253-41.69-6.058-61.212-45.528-6.565-88.59-9.03-131.002-8.873z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><linearGradient x1="0" x2="1" y1="1" y2="0" id="delapouite-sparkles-gradient-4"><stop offset="0%" stop-color="#4a4a4a" stop-opacity="1"></stop><stop offset="100%" stop-color="#c9c9c9" stop-opacity="1"></stop></linearGradient><radialGradient id="delapouite-sparkles-gradient-5"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient><radialGradient id="delapouite-sparkles-gradient-7"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient></defs><g class="" transform="translate(1,-2)" style=""><path d="M237.4 20.73c-6.1 42.1-26.8 64.2-63.9 64 31.6 4.5 63.8 8 63.9 64.07-.6-46.1 24.5-63.07 64.1-64.07-38-1.5-64.9-16.3-64.1-64zm127.8 11.58c-9.1 14.25-20.8 21.29-38.9 10.28 14.9 11.79 18.6 24.76 10.2 38.97 8.9-11.18 17.5-22.73 39-10.27-17.8-10.06-18.8-23.57-10.3-38.98zM59.68 41.69c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.52-.3-20.5 10.9-28.12 28.5-28.52-16.9-.7-28.9-7.3-28.5-28.5zM431 66.28c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.52-.3-20.5 10.9-28.12 28.5-28.52-16.9-.7-28.9-7.3-28.5-28.5zM120.3 116.4c-15.8 53.7-47.76 48-79.35 43.4C76.6 170 90.3 197.1 84.28 239.2c12.66-46 42.62-52.6 79.42-43.4-37.6-12.1-56.9-35.4-43.4-79.4zm187 5c-8.8 61.6-39.3 94-93.6 93.7 46.2 6.5 93.6 11.7 93.6 93.7-.8-67.3 35.9-92.2 93.8-93.7-55.5-2.2-94.9-23.9-93.8-93.7zm136.8 38.3c-13.1 21.6-29.5 28.8-49.7 20.1 16.3 9.7 33 19.1 20.1 49.6 10.3-25.2 27.9-28.7 49.7-20-20.3-9.7-31.6-23.9-20.1-49.7zM50.7 243.2c9.16 16.7 7.63 30.1-5.61 40 12.46-6.9 24.85-14.3 39.91 5.6-12.57-16.2-8.2-29 5.61-40-13.92 9.7-27.47 11.6-39.91-5.6zm137.2.3c11.4 26.8-.5 41.3-21.7 50.9 22.7-8.5 40.8-4.5 50.9 21.7-12.7-31.8 4.8-41.2 21.7-50.9-21 8.5-37.8.9-50.9-21.7zm228 12.6c-26.6 64.7-68.7 91.7-127.8 76.4 48.6 19.8 98.8 38.5 76.4 127.9 17.5-73.7 64.4-90.7 127.9-76.5-59.9-17.5-96.9-52-76.5-127.8zM99.94 295.5c15.66 57.8.86 98.1-47.32 118.5 43.46-11.8 87.38-25.2 118.68 47.4-26.4-59.3-3.4-95.4 47.3-118.8-50 19.2-93.1 15-118.66-47.1zm169.36 61c-21.8 20.6-43 23.6-63.2 7.3 15.5 16.3 31.6 32.4 7.2 63.3 19.8-25.6 41.2-24.1 63.3-7.3-20.2-17.4-28.6-37.5-7.3-63.3zM443.2 404c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.5-.3-20.5 10.9-28.1 28.5-28.5-16.9-.7-28.9-7.3-28.5-28.5zm-169.7 36c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.5-.3-20.5 10.9-28.1 28.5-28.5-16.9-.7-28.9-7.3-28.5-28.5z" fill="#fff" transform="translate(51.2, 51.2) scale(0.8, 0.8) rotate(0, 256, 256) skewX(0) skewY(0)" fill-opacity="1"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 2.6 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M256.25 20.313c-108.64 0-196.78 90.592-196.78 202.937 0 84.615 49.994 156.904 121.093 187.438v-16.375c0-25.638-6.2-40.132-13.875-48.47-7.675-8.336-17.567-11.4-27.72-11.937-18.252-.97-32.4-12.266-40.905-27-6.47-11.205-5.975-24.767-.532-36.97 5.444-12.2 15.49-23.71 29.19-33.905 27.394-20.39 69.79-35.56 122.436-35.56 52.702 0 98.475 15.648 129.344 36.218 15.435 10.284 27.24 21.746 34.22 33.968 6.976 12.222 8.93 26.41 2.186 38.094-4.19 7.257-11.026 11.988-18.687 15.938-7.663 3.95-16.085 6.78-24.595 6.78-11.865 0-20.63 2.214-27.438 10.157s-12.437 23.63-12.437 52.688v16.437c71.195-30.488 121.28-102.814 121.28-187.5 0-112.347-88.14-202.938-196.78-202.938zm-76.656 86.718c1.53.02 3.05.078 4.562.157 14.525.766 28.29 4.3 41.063 9.97l17.31 7.687-16.624 9.062-84.062 45.875-8.938-16.405 65.156-35.563c-24.195-5.513-50.92-1.877-82.062 17.532l-9.875-15.844c25.778-16.066 50.528-22.75 73.47-22.47zm150.312 0c22.944-.28 47.722 6.404 73.5 22.47l-9.875 15.844c-31.14-19.41-57.865-23.045-82.06-17.53l65.155 35.56-8.938 16.407-84.062-45.874L267 124.844l17.313-7.688c12.772-5.67 26.506-9.203 41.03-9.97 1.514-.078 3.034-.136 4.563-.155zm-73.594 170.282c-68.947 0-113.104 15.367-116.843 37.907l.5.03c13.487.714 28.843 5.31 40.468 17.938 11.624 12.627 18.812 32.418 18.812 61.125v100.312h113.813V394.312c0-31.4 5.766-51.81 16.937-64.843 11.17-13.034 27.003-16.69 41.625-16.69.352 0 .76-.03 1.156-.06-6.417-22.614-49.872-35.408-116.467-35.408z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><polygon points="256,512,0,256,256,0,512,256" fill="#000" fill-opacity="1"></polygon><g class="" transform="translate(8,-12)" style=""><path d="M282.83 18.877c21.567 6.146 36.328 15.205 40.572 28.77a71.007 71.007 0 0 0-4.066 2.363c-25.655 5.807-53.084 18.634-81.047 34.363 20.225-4.69 36.705-4.42 47.544 3.324-5.712 10.3-10.797 22.294-15.123 36.06-21.343 67.922-125.678-80.577-189.065-5.255C41.47 166.24 92.702 212.342 26.5 294.29c35.583-4.14 45.11-9.47 62.416-36.21 10.44-16.13 28.52-22.1 44.668-21.45-12.718 11.206-25.786 30.354-38.21 59.895 19.832-18.528 44.927-38.68 71.603-40.005.912 6.354-2.408 13.74-12.008 21.418C93.21 327.327 15.58 364.185 19.83 476.504c5.558-11.267 11.646-20.31 17.574-28.617 5.98 29.582 28.2 53.8 92.99 40.482-46.928-6.407-76.268-59.586-45.355-82.528 62.716-46.544 128.82 1.436 269.9-75.342a79.832 79.832 0 0 1 7.164-3.46c-2.246 19.6-12.367 39.84-22.362 57.14 14.26-10.38 25.415-20.147 33.928-29.262 2.14 26.14-11.748 54.65-25.393 78.268 43.26-31.49 61.19-57.976 63.207-78.422 9.334 36.678-1.895 95.547-25.03 123.492 77.553-39.433 106.608-77.127 109.76-190.664 1.662-59.824-66.23-60.536-56.435-101.344 11.945-49.756 6.768-84.69-7.565-107.947-19.6-49.73-79.99-59.74-149.385-59.423zM89.8 47.684C54.69 47.534 45.233 83.056 55.724 117c17.146-51.504 70.414-44.24 111.17-34.367-33.282-25.005-58.707-34.87-77.096-34.95zm254.595 30.742c18.643 21.37 29.373 43.02 10.105 65.732-26.562-16.677-26.985-39.252-10.105-65.732zm74.494 48.6c3.655-.013 7.78.35 12.473 1.09-1.706 30.506-14.4 33-46.634 32.154 8.335-22.146 14.416-33.176 34.16-33.245zm-84.677 40.316c9.652.1 20.258 2.84 30.598 8.918 44.65 26.246 21.934 73.314-4.1 74.78-15.174.855 1.443-23.842-16.17-38.476-15.258-12.678-38.596 12.53-45.204-5.78-8.218-22.693 10.21-39.696 34.877-39.442zm60.18 246.168c-24.195 27.825-58.89 60.1-99.444 31.41 16.625 45.643 68.87 70.465 99.443-31.41z" fill="#fff" fill-opacity="1" transform="translate(102.4, 102.4) scale(0.6, 0.6) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -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"
|
||||
viewBox="0 0 448 434"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="surenc.svg"
|
||||
width="448"
|
||||
height="434"
|
||||
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="3840"
|
||||
inkscape:window-height="2054"
|
||||
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="224"
|
||||
inkscape:cy="210"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg6" />
|
||||
<g
|
||||
class=""
|
||||
id="g4"
|
||||
transform="translate(-32,-46)">
|
||||
<path
|
||||
d="m 256,46 c -45.074,0 -82,36.926 -82,82 0,25.812 12.123,48.936 30.938,64 H 128 L 32,480 H 480 L 384,192 H 307.062 C 325.877,176.936 338,153.812 338,128 338,82.926 301.074,46 256,46 Z m 0,36 c 25.618,0 46,20.382 46,46 0,25.618 -20.382,46 -46,46 -25.618,0 -46,-20.382 -46,-46 0,-25.618 20.382,-46 46,-46 z m -82.215,202.95 h 23.5 v 33.263 l 33.873,-33.264 h 27.283 l -43.883,43.15 48.4,47.974 H 233.54 l -36.255,-35.888 v 35.888 h -23.5 z m 119.934,21.24 c 4.76,0 8.952,0.934 12.573,2.806 3.62,1.872 6.938,4.82 9.95,8.85 v -10.13 h 21.972 v 61.462 c 0,10.986 -3.48,19.368 -10.438,25.146 -6.917,5.82 -16.968,8.727 -30.152,8.727 -4.272,0 -8.4,-0.325 -12.39,-0.976 a 77.367,77.367 0 0 1 -12.024,-2.99 v -17.03 c 3.826,2.198 7.57,3.826 11.23,4.884 3.664,1.098 7.347,1.648 11.05,1.648 7.162,0 12.41,-1.566 15.746,-4.7 3.337,-3.132 5.006,-8.035 5.006,-14.708 v -4.7 c -3.01,3.986 -6.328,6.916 -9.95,8.788 -3.62,1.87 -7.813,2.808 -12.573,2.808 -8.343,0 -15.238,-3.275 -20.69,-9.826 -5.453,-6.592 -8.18,-14.974 -8.18,-25.146 0,-10.214 2.727,-18.576 8.18,-25.086 5.452,-6.55 12.347,-9.827 20.69,-9.827 z m 8.118,15.746 c -4.517,0 -8.038,1.67 -10.56,5.005 -2.523,3.338 -3.784,8.058 -3.784,14.162 0,6.266 1.22,11.026 3.662,14.28 2.442,3.215 6.003,4.823 10.682,4.823 4.557,0 8.096,-1.67 10.62,-5.006 2.522,-3.337 3.784,-8.036 3.784,-14.098 0,-6.104 -1.262,-10.824 -3.785,-14.16 -2.523,-3.337 -6.062,-5.006 -10.62,-5.006 z"
|
||||
fill="#ffffff"
|
||||
fill-opacity="1"
|
||||
id="path2" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
@@ -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="M221.313 16a23.682 23.695 0 0 0-23.688 23.688v106.406a23.682 23.695 0 0 0 2.156 9.72 23.682 23.695 0 0 0 3.157 13.81l41.75 71.626-79 55.438 6.094-48.625a23.682 23.695 0 0 0-8.186-20.97l-66.28-81.937a23.682 23.695 0 0 0-33.314-3.5l-9.188 7.438a23.682 23.695 0 0 0-3.53 33.344l59.78 73.906-11.25 89.937a23.682 23.695 0 0 0 12.47 23.876l37.468 53.47a23.695 23.682 1.57 0 0 2.344 2.812 23.682 23.695 0 0 0 13.594 20.062L262 491.53a23.682 23.695 0 0 0 9.97 2.22 23.682 23.695 0 0 0 23.53-2.063l87.156-60.937a23.682 23.695 0 0 0 5.844-33l-6.78-9.688a23.682 23.695 0 0 0-32.97-5.875l-72.406 50.657-59.063-27.625 120.595-84.626a23.695 23.682 1.57 0 0 5.53-5.5 23.682 23.695 0 0 0 14.626-13.594l37.22-91.53 87.813-44.845a23.694 23.682 1.18 0 0 10.312-31.875L488 122.687a23.694 23.682 1.18 0 0-31.875-10.343l-94.688 48.375a23.694 23.682 1.18 0 0-9.843 9.436 23.682 23.695 0 0 0-8.344 10.47l-27.375 67.31-5.22-7.436a23.682 23.695 0 0 0-3-8.844l-50.81-87.094V39.688A23.682 23.695 0 0 0 233.154 16h-11.843zM77.75 376A59.994 60 0 0 0 16 436a59.994 60 0 1 0 120 0 59.994 60 0 0 0-58.25-60z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 7.2 KiB |
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
viewBox="0 0 378.00079 384.97681"
|
||||
version="1.1"
|
||||
id="svg23"
|
||||
sodipodi:docname="resistance.svg"
|
||||
width="378.00079"
|
||||
height="384.97681"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata27">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1875"
|
||||
inkscape:window-height="1352"
|
||||
id="namedview25"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1.4355469"
|
||||
inkscape:cx="186.7504"
|
||||
inkscape:cy="196.1768"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg23" />
|
||||
<defs
|
||||
id="defs17">
|
||||
<linearGradient
|
||||
x1="0"
|
||||
x2="1"
|
||||
y1="1"
|
||||
y2="0"
|
||||
id="lorc-aura-gradient-4">
|
||||
<stop
|
||||
offset="0%"
|
||||
stop-color="#4a4a4a"
|
||||
stop-opacity="1"
|
||||
id="stop2" />
|
||||
<stop
|
||||
offset="100%"
|
||||
stop-color="#c9c9c9"
|
||||
stop-opacity="1"
|
||||
id="stop4" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="lorc-aura-gradient-5">
|
||||
<stop
|
||||
offset="0%"
|
||||
stop-color="#9013fe"
|
||||
stop-opacity="1"
|
||||
id="stop7" />
|
||||
<stop
|
||||
offset="100%"
|
||||
stop-color="#85562c"
|
||||
stop-opacity="1"
|
||||
id="stop9" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
id="lorc-aura-gradient-7">
|
||||
<stop
|
||||
offset="0%"
|
||||
stop-color="#9013fe"
|
||||
stop-opacity="1"
|
||||
id="stop12" />
|
||||
<stop
|
||||
offset="100%"
|
||||
stop-color="#85562c"
|
||||
stop-opacity="1"
|
||||
id="stop14" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<g
|
||||
class=""
|
||||
transform="translate(-68.2496,-61.8232)"
|
||||
id="g21">
|
||||
<path
|
||||
d="m 320.938,13.28 c -16.646,34.584 -38.466,60.157 -63.094,60.157 -24.522,0 -47.035,-25.275 -63.656,-59.593 0.366,39.358 -9.71,90.884 -30.938,105.125 -21.228,14.24 -49.64,-12.002 -78.844,-32.126 17.455,34.04 42.095,67.5 29.78,92.28 -12.21,24.576 -59.172,35.96 -92.874,35.626 29.338,19.29 78.842,45.803 78.844,74.188 0.002,28.384 -49.504,53.71 -78.844,73 33.702,-0.333 80.663,11.612 92.876,36.187 12.227,24.61 -9.03,56.31 -33.75,85.563 44.826,-15.413 65.142,-5.735 85.374,10.812 h 31.75 C 154.822,459.086 125.5,386.671 125.5,302.936 125.498,184.316 184.42,88.03 256.906,88.03 c 72.488,0 131.406,96.29 131.406,214.907 0,83.74 -29.317,156.153 -72.062,191.563 h 27.313 c 19.847,-14.62 39.796,-25.65 89.687,-9.28 -26.233,-30.264 -42.2,-62.484 -29.97,-87.095 12.257,-24.665 56.658,-36.612 90.533,-36.188 -29.4,-19.297 -75.344,-44.584 -75.344,-73 0,-28.415 45.943,-54.89 75.342,-74.187 -33.874,0.424 -78.273,-10.962 -90.53,-35.625 -12.315,-24.78 9.982,-58.24 27.437,-92.28 -29.202,20.12 -57.583,46.385 -78.845,32.124 -21.262,-14.263 -31.382,-66.13 -30.938,-105.69 z m -68.97,93.75 c -19.56,2.543 -37.343,25.564 -37.343,55.407 0,16.447 5.67,30.986 14,41.032 l 10.156,12.218 -15.593,2.937 c -10.815,2.035 -18.743,7.737 -25.53,17.063 -6.79,9.325 -11.984,22.344 -15.626,37.343 -6.585,27.128 -8.078,60.24 -8.31,89.47 h 36.093 l 0.656,8.656 9.124,122.563 h 76.187 l 8.095,-122.5 0.563,-8.72 h 34.375 c -0.026,-29.592 -0.44,-63.166 -6.407,-90.5 -3.295,-15.095 -8.287,-28.096 -15.156,-37.313 -6.87,-9.216 -15.133,-14.897 -27.28,-16.78 l -15.94,-2.47 10.064,-12.593 c 7.97,-9.996 13.375,-24.36 13.375,-40.406 -0.002,-31.817 -19.884,-55.313 -41.44,-55.313 -2.54,0 -3.96,-0.103 -4.03,-0.094 h -0.03 z"
|
||||
fill="#ffffff"
|
||||
fill-opacity="1"
|
||||
transform="matrix(0.8,0,0,0.8,51.2,51.2)"
|
||||
id="path19" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.4 KiB |
@@ -1,5 +1,131 @@
|
||||
# 13.0
|
||||
|
||||
## 13.0.21 - La folie d'Illysis
|
||||
|
||||
- Jets d'appréciation et de moral
|
||||
- concerne la danse, musique, chant, jeu, les oeuvres, la nourriture, les services
|
||||
- gestion des compétences d'appréciation pour les oeuvres
|
||||
- pas de jet de moral si la qualité n'est pas suffisante (inférieure au moral,
|
||||
à la compétence, moral déjà gagné pour la même raison)
|
||||
- jet d'appréciation avec en option la compétence et la qualité
|
||||
- jet de moral très heureux (pour Spasme)
|
||||
- les jets de moral sont liés à des "bon moments"
|
||||
- la liste des bons moments passés par un acteur est remise à zéro à Château Dormant
|
||||
- Fenêtre de jet v2
|
||||
- les possessions sont maintenant gérées avec les fenêtres V2
|
||||
- on peut choisir sa voie de draconic pour contrer une possession ou conjurer
|
||||
- La zone de saisie dans les journaux est mieux adaptée
|
||||
- Correction des bonus de caractéristiques des cyans
|
||||
|
||||
|
||||
## 13.0.20 - L'immobilisme d'Illysis
|
||||
|
||||
- Centrage du logo de pause
|
||||
- Ajout d'un statut malade/empoisonné
|
||||
- Fenêtre de jet v2
|
||||
- correction du compteur empoignade
|
||||
- amélioration des messages liés à l'empoignade
|
||||
- amélioration des choix de perte d'endurance
|
||||
- correction de la dépense de rêve sur lancement de sort
|
||||
- ajustement astrologique sur rituels
|
||||
|
||||
|
||||
## 13.0.19 - L'introspection d'Illysis
|
||||
|
||||
- Ajout d'un bouton pour les jets de résistance sous rêve actuel
|
||||
- Fenêtre de jet v2
|
||||
- restrictions au propriétaire du personnage
|
||||
- ouverture de la fenêtre de jets
|
||||
- appel à la chance
|
||||
- appel à la destinée
|
||||
- fermeture par défaut selon le type de jets:
|
||||
- jets d'attaque
|
||||
- jets de défense
|
||||
- jets imposés par un choix d'action
|
||||
- lancer de sorts
|
||||
- jets suite à appel à la chance
|
||||
- gestion des écailles d'efficacité sur les armes
|
||||
- permettre de faire une attaque même si l'initiative n'est pas faite
|
||||
- les messages de défense s'affichent correctement avec plusieurs joueurs
|
||||
- les particulières en force/rapidité sont correctement affichées dans le tchat
|
||||
- l'expérience sur jet de résistance est limitée à 1 point
|
||||
|
||||
## 13.0.18 - Le reflet d'Illysis
|
||||
|
||||
- Mise à jour de la feuille de personnage pdf template (avec police correcte)
|
||||
- Ajout d'une icône "écurie" pour les services des commerces & auberges
|
||||
- Suppression de message d'erreur sur compétence
|
||||
manquante à l'ouverture des acteurs d'invocation
|
||||
|
||||
## 13.0.17 - Le chant d'Illysis
|
||||
|
||||
- Corrections CSS
|
||||
- Migration Uberwald -> Scriptarium
|
||||
|
||||
## 13.0.16 - La paix d'Illysis
|
||||
|
||||
- Export de personnages sous forme de feuille de personnage pdf
|
||||
- Correction d'un problème à l'ouverture de personnages saisis dans d'anciennes versions
|
||||
- Fenêtre de jet v2
|
||||
- on peut faire des jets en dehors des combats
|
||||
|
||||
## 13.0.15 - Les pièces d'Illysis
|
||||
|
||||
- On peut de nouveau acheter dans les commerces
|
||||
- Corrections V13
|
||||
- Les textes sur fond "parchemin" ne sont plus affichés en blanc
|
||||
|
||||
## 13.0.14 - Le familier d'Illysis
|
||||
|
||||
- Les réussites particulières en demi-surprise sont de simples réussites
|
||||
- Les images des scènes par défaut sont corrigées
|
||||
- Ajout d'une image de status "sur-encombré"
|
||||
- Correction V13
|
||||
- couleur lisible dans les sommaires des journaux et des compendiums
|
||||
- Amélioration des entités:
|
||||
- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
|
||||
- l'encaissement indique une blessure dans le tchat... même si ce n'est que de l'endurance
|
||||
- les blurettes suivent les règles des entités de cauchemar (p322)
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
- attaque/défense des créatures
|
||||
- les attaques/parades avec une arme trop lourde se font en demi-surprise
|
||||
- les demandes de défense disparaîssent une fois prises en compte
|
||||
- empoignade
|
||||
- l'empoignade est possible avec une initiative d'empoignade, ou en cours d'empoignade
|
||||
- seule la dague, le pugilat et la dague sont possibles en cours d'empoignade
|
||||
- jet de Dextérité/Dague pour utiliser la dague en cours d'empoignade (p136)
|
||||
- attaquer avec une arme un empoigneur donne un +4 si pas d'empoignade (p134)
|
||||
- la différence de taille donne un bonus/malus en cours d'empoignade (p135)
|
||||
- les dommages de l'empoignade ajoutent/enlèvent un point d'empoignade
|
||||
- le statut d'empoignade est affiché sur les tokens
|
||||
- les défenses contre une empoignade sont corrigées
|
||||
|
||||
## 13.0.13 - L'épanouissement d'Illysis
|
||||
|
||||
- Fix d'erreur au chargement de templates RollDialog
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
- Fix: affichage des points de tâche
|
||||
- Fix: affichage des ajustements cohérent
|
||||
- L'ouverture depuis les caractéristiques permet plusieurs types de jets
|
||||
- On peut créer ou modifier les tâches dans la fenêtre de jets de tâches
|
||||
- attaque/défense
|
||||
- les maladresses sont affichées dans le résultat du jet
|
||||
- le message au défenseur s'affiche correctement
|
||||
- la difficulté d'attaque s'applique à la défense
|
||||
- on peut choisir les particulières en rapidité
|
||||
|
||||
## 13.0.12 - La méditation d'Illysis
|
||||
|
||||
- les signes draconiques éphémères de 1 round sont supprimés à la descente des TMRs
|
||||
- Générateur de description
|
||||
- correction des termes pour les couleurs des yeux/cheveux
|
||||
- ajout de boutons pour forcer le sexe masculin/féminin
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
- les méditations proposent un bouton pour monter dans les TMRs
|
||||
- fenêtre de lancer de sorts
|
||||
- Correction: les compétences de jeux ne remplacent plus les compétences en dehors des jets de jeu
|
||||
- gestion des maladresses d'attaque et défense
|
||||
|
||||
## 13.0.11 - Le gambit d'Illysis
|
||||
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
@@ -35,7 +161,7 @@
|
||||
- ajout d'un status "Force insuffisante"
|
||||
- clarification des maladresses à l'attaque (en demi surprise, ou à cause d'un échec total)
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
- ajout du statut "Force insuffisante" aux acteurs si la
|
||||
- ajout du statut "Force insuffisante" aux acteurs si la
|
||||
force est insuffisante pour l'arme
|
||||
- avancement du mode attaque
|
||||
- choix de tactique
|
||||
|
||||
@@ -60,8 +60,7 @@
|
||||
/* Fonts */
|
||||
.sheet header.sheet-header h1 input,
|
||||
.window-app .window-header,
|
||||
#actors .directory-list,
|
||||
#navigation #scene-list .scene.nav-item {
|
||||
#sidebar {
|
||||
font-family: "GoudyAcc";
|
||||
}
|
||||
/* For title, sidebar character and scene */
|
||||
@@ -71,17 +70,16 @@
|
||||
.sheet header.sheet-header .flex-group-center.flex-fatigue,
|
||||
select,
|
||||
.item-checkbox,
|
||||
#sidebar,
|
||||
#players,
|
||||
#navigation #nav-toggle {
|
||||
#players {
|
||||
font-family: "CaslonAntique";
|
||||
/* For sheet parts; For nav and title */
|
||||
}
|
||||
:root {
|
||||
body {
|
||||
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
|
||||
/* =================== 3. some constants ============ */
|
||||
--fieldset-background: url(/ui/parchment.jpg);
|
||||
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--rdd-input-background: hsla(0, 0%, 0%, 0.1);
|
||||
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
|
||||
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
|
||||
@@ -99,7 +97,9 @@ select,
|
||||
--gradient-warning: linear-gradient(150deg, hsla(32, 100%, 50%, 0.3), hsla(52, 60%, 50%, 0.1), hsla(32, 60%, 50%, 0.1), hsla(32, 100%, 50%, 0.3));
|
||||
--gradient-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, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-color-button: hsl(25, 5%, 60%);
|
||||
--background-color-custom-button: hsla(208, 38%, 21%, 0.988);
|
||||
--background-custom-button: linear-gradient(to bottom, var(--background-color-custom-button) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, hsl(0, 100%, 25%) 5%, hsl(0, 97%, 12%) 100%);
|
||||
--background-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);
|
||||
@@ -593,6 +593,9 @@ select,
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section[name="resistance"] {
|
||||
align-items: flex-end;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -607,6 +610,12 @@ select,
|
||||
margin: 0 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section img.flag-resistance {
|
||||
max-width: 1.5rem;
|
||||
max-height: 1.5rem;
|
||||
text-align: right;
|
||||
filter: invert(0.6);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -648,15 +657,19 @@ select,
|
||||
.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;
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section img {
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.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;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
@@ -670,7 +683,7 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat {
|
||||
font-family: CaslonAntique;
|
||||
display: grid;
|
||||
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions";
|
||||
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "description description description" "actions actions actions";
|
||||
grid-template-columns: 3rem 1fr 1.4rem;
|
||||
grid-template-rows: max-content max-content max-content max-content;
|
||||
gap: 0 0.5rem;
|
||||
@@ -707,6 +720,10 @@ select,
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-details div,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-details div {
|
||||
display: block;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions {
|
||||
grid-area: actions;
|
||||
@@ -722,6 +739,17 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a img {
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description {
|
||||
grid-area: description;
|
||||
text-align: justify;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description div,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description div {
|
||||
display: block;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons,
|
||||
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons {
|
||||
grid-area: buttons;
|
||||
@@ -757,7 +785,19 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .window-header {
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry-content {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .journal-page-header h1,
|
||||
.system-foundryvtt-reve-de-dragon .journal-page-header h2 .journal-page-header h3,
|
||||
.system-foundryvtt-reve-de-dragon .journal-page-header h4 {
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content {
|
||||
margin: 0;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content {
|
||||
margin: 0.2rem;
|
||||
padding: 0;
|
||||
@@ -768,7 +808,7 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .strong-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon i:is(.fas, .far, .fa-solid, .fa-regular, .fa-sharp ) {
|
||||
.system-foundryvtt-reve-de-dragon i:is(.fas, .far, .fa-solid, .fa-regular, .fa-sharp) {
|
||||
font-size: smaller;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header h1.charname {
|
||||
@@ -807,7 +847,7 @@ select,
|
||||
margin-top: -8px;
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header :is(.header-compteurs,.header-etats,.profile-img, .profile-img-token) {
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header :is(.header-compteurs, .header-etats, .profile-img, .profile-img-token) {
|
||||
padding: 0 0.4rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header div.header-etats {
|
||||
@@ -844,11 +884,11 @@ select,
|
||||
object-fit: contain;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon img.equipement-inutilisable {
|
||||
vertical-align: bottom ;
|
||||
vertical-align: bottom;
|
||||
max-width: 1.4rem;
|
||||
max-height: 1.4rem;
|
||||
border: 1px;
|
||||
background: center / contain no-repeat url('../../assets/ui/icone_parchement_vierge.webp');
|
||||
background: center / contain no-repeat url("../../icons/templates/icone_parchement_vierge.webp");
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
|
||||
width: calc(60% - 110px - 1rem);
|
||||
@@ -916,7 +956,14 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon div.tmrdialog div.tmr-actions {
|
||||
vertical-align: top;
|
||||
flex-basis: inherit;
|
||||
flex: 'flex-shrink';
|
||||
flex: "flex-shrink";
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a {
|
||||
text-shadow: 1px 1px 2px var(--rdd-color-text-primary);
|
||||
color: var(--color-background-chat-message);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a:hover {
|
||||
text-shadow: 1px 0px 0px #ff6600;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .tabs .item.active,
|
||||
.system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover,
|
||||
@@ -924,6 +971,12 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon a:hover {
|
||||
text-shadow: 1px 0px 0px #ff6600;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .tabs .item.active img,
|
||||
.system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover img,
|
||||
.system-foundryvtt-reve-de-dragon i.moral-radio-checkmark-off:hover img,
|
||||
.system-foundryvtt-reve-de-dragon a:hover img {
|
||||
filter: drop-shadow(1px 0px 0px #ff6600);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .rollable:hover,
|
||||
.system-foundryvtt-reve-de-dragon .rollable:focus {
|
||||
color: #000;
|
||||
@@ -1037,7 +1090,7 @@ select,
|
||||
justify-content: space-between;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .flex-shrink {
|
||||
flex: 'flex-shrink';
|
||||
flex: "flex-shrink";
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .flex-grow,
|
||||
@@ -1255,7 +1308,7 @@ select,
|
||||
border: 0;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(.button-img,.button-effect-img,.tmr-move):hover {
|
||||
.system-foundryvtt-reve-de-dragon :is(.button-img, .button-effect-img, .tmr-move):hover {
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
text-shadow: 1px 0px 0px #ff6600;
|
||||
@@ -1347,12 +1400,22 @@ select,
|
||||
margin-inline: 0.1rem;
|
||||
margin-block: 0.1rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .prosemirror menu {
|
||||
background-color: var(--color-background-chat-message);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet fieldset :is(label, input) {
|
||||
font-family: CaslonAntique;
|
||||
text-align: justify;
|
||||
font-size: 1rem;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet input.attribute-value {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid var(--color-border-light-tertiary);
|
||||
padding: 1px 3px;
|
||||
height: var(--form-field-height);
|
||||
border-radius: 3px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet div.form-group {
|
||||
clear: both;
|
||||
display: flex;
|
||||
@@ -1363,14 +1426,20 @@ select,
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror {
|
||||
height: fit-content;
|
||||
min-height: 5rem;
|
||||
min-height: 6rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror .editor-container {
|
||||
min-height: 5rem;
|
||||
height: 8rem;
|
||||
min-height: 6rem;
|
||||
height: calc(100% - 3rem);
|
||||
margin: 0;
|
||||
flex: none;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror {
|
||||
height: 100%;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror .editor-container {
|
||||
height: calc(100% - 6rem);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .large-editor {
|
||||
border: 2;
|
||||
height: fit-content;
|
||||
@@ -1380,24 +1449,24 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .editor {
|
||||
border: 2;
|
||||
height: fit-content;
|
||||
min-height: 5rem;
|
||||
min-height: 6rem;
|
||||
padding: 0 3px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .medium-editor {
|
||||
border: 2;
|
||||
min-height: 8rem;
|
||||
min-height: 9rem;
|
||||
padding: 0 3px;
|
||||
align-items: top;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .small-editor {
|
||||
border: 2;
|
||||
min-height: 2rem;
|
||||
min-height: 4rem;
|
||||
padding: 0 3px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor,.editor,.medium-editor,.small-editor) {
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor, .editor, .medium-editor, .small-editor) {
|
||||
align-items: start;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor,.editor,.medium-editor,.small-editor) .editor.prosemirror {
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor, .editor, .medium-editor, .small-editor) .editor.prosemirror {
|
||||
align-items: normal;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tox .tox-editor-container {
|
||||
@@ -1412,8 +1481,8 @@ select,
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs {
|
||||
height: 40px;
|
||||
border-top: 1px solid #AAA;
|
||||
border-bottom: 1px solid #AAA;
|
||||
border-top: 1px solid #aaa;
|
||||
border-bottom: 1px solid #aaa;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs .item {
|
||||
line-height: 40px;
|
||||
@@ -1448,12 +1517,27 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls {
|
||||
display: none !important;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular),
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls,
|
||||
.system-foundryvtt-reve-de-dragon .item-controls {
|
||||
vertical-align: super;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls img,
|
||||
.system-foundryvtt-reve-de-dragon .item-controls img {
|
||||
display: inline;
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
margin: 0 0.1rem;
|
||||
border: none;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .fa, .fa-solid, .fa-regular),
|
||||
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .fa, .fa-solid, .fa-regular) {
|
||||
font-size: 0.8em;
|
||||
color: var(--color-controls-light);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular):hover,
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls img:hover,
|
||||
.system-foundryvtt-reve-de-dragon .item-controls img:hover,
|
||||
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover,
|
||||
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
@@ -1537,55 +1621,93 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .type-compendium {
|
||||
font-size: 0.6rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header {
|
||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||
color: #ffffff;
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header :is(
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
input[type="datetime-local"],
|
||||
input[type="date"],
|
||||
input[type="time"]) {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body label,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content label,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar label,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .hint,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content .hint,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .hint,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs {
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button .count,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content button .count,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button .count,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content button,
|
||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button {
|
||||
background-color: var(--background-color-button);
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
color: var(--rdd-color-text-primary);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header {
|
||||
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header label,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .hint,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .permissions-list,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button .count,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header div,
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header button {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input {
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
border: 0 none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input[type="checkbox"] {
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon input[type="number"] {
|
||||
text-align: right;
|
||||
padding-right: 0.5rem;
|
||||
max-width: 7rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon select:is(.number-x,.number-x2,.number-x3,.number-x4,.number-x5) {
|
||||
.system-foundryvtt-reve-de-dragon select:is(.number-x, .number-x2, .number-x3, .number-x4, .number-x5) {
|
||||
padding-right: 0.2rem;
|
||||
text-align: center;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon input:is(.number,.number-x,.number-x2,.number-x3,.number-x4,.number-x5) {
|
||||
.system-foundryvtt-reve-de-dragon input:is(.number, .number-x, .number-x2, .number-x3, .number-x4, .number-x5) {
|
||||
padding-right: 0.2rem;
|
||||
text-align: right;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(input,select).number-x {
|
||||
.system-foundryvtt-reve-de-dragon :is(input, select).number-x {
|
||||
max-width: 1.4rem;
|
||||
min-width: 1rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(input,select).number-x2 {
|
||||
.system-foundryvtt-reve-de-dragon :is(input, select).number-x2 {
|
||||
max-width: 2.4rem;
|
||||
min-width: 2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(input,select).number-x3 {
|
||||
.system-foundryvtt-reve-de-dragon :is(input, select).number-x3 {
|
||||
max-width: 3.4rem;
|
||||
min-width: 3rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(input,select).number-x4 {
|
||||
.system-foundryvtt-reve-de-dragon :is(input, select).number-x4 {
|
||||
max-width: 4.4rem;
|
||||
min-width: 4rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(input,select).number-x5 {
|
||||
.system-foundryvtt-reve-de-dragon :is(input, select).number-x5 {
|
||||
max-width: 4.4rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon form.rdddialogchrono input[type=datetime-local] {
|
||||
.system-foundryvtt-reve-de-dragon form.rdddialogchrono input[type="datetime-local"] {
|
||||
min-width: 20px;
|
||||
padding: 0;
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
@@ -1593,9 +1715,12 @@ select,
|
||||
width: calc(100% - 2px);
|
||||
height: var(--form-field-height);
|
||||
margin: 0;
|
||||
color: var(--color-text-dark-primary);
|
||||
color: var(--rdd-color-text-primary);
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
|
||||
min-width: 30rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral {
|
||||
width: 14rem;
|
||||
margin: 0.4rem;
|
||||
@@ -1616,8 +1741,9 @@ select,
|
||||
height: 2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-app .window-content,
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body {
|
||||
background: #f5f5f0 url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
|
||||
.system-foundryvtt-reve-de-dragon .application .window-content {
|
||||
background: url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon section.sheet-body {
|
||||
padding: 0.25rem 0.5rem;
|
||||
@@ -1673,7 +1799,7 @@ select,
|
||||
text-align: left;
|
||||
width: 2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .compteur a i:is(.fas,.far):hover {
|
||||
.system-foundryvtt-reve-de-dragon .compteur a i:is(.fas, .far):hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .select-diff {
|
||||
@@ -2095,7 +2221,7 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon #sidebar-tabs > .collapsed,
|
||||
.system-foundryvtt-reve-de-dragon #chat-controls .chat-control-icon {
|
||||
color: rgba(220, 220, 220, 0.75);
|
||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
|
||||
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sidebar-tab .directory-list .entity {
|
||||
border-top: 1px dashed rgba(0, 0, 0, 0.25);
|
||||
@@ -2151,19 +2277,19 @@ select,
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button:is(
|
||||
[data-tab="chat"],
|
||||
[data-tab="combat"],
|
||||
[data-tab="scenes"],
|
||||
[data-tab="actors"],
|
||||
[data-tab="items"],
|
||||
[data-tab="journal"],
|
||||
[data-tab="cards"],
|
||||
[data-tab="macros"],
|
||||
[data-tab="tables"],
|
||||
[data-tab="playlists"],
|
||||
[data-tab="compendium"],
|
||||
[data-tab="settings"]
|
||||
)::before {
|
||||
[data-tab="chat"],
|
||||
[data-tab="combat"],
|
||||
[data-tab="scenes"],
|
||||
[data-tab="actors"],
|
||||
[data-tab="items"],
|
||||
[data-tab="journal"],
|
||||
[data-tab="cards"],
|
||||
[data-tab="macros"],
|
||||
[data-tab="tables"],
|
||||
[data-tab="playlists"],
|
||||
[data-tab="compendium"],
|
||||
[data-tab="settings"]
|
||||
)::before {
|
||||
content: none;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button {
|
||||
@@ -2231,7 +2357,12 @@ select,
|
||||
max-height: calc(100vh - 156px);
|
||||
height: auto;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon #controls :is(.scene-control.active,.control-tool.active, .scene-control:hover, .control-tool:hover) {
|
||||
.system-foundryvtt-reve-de-dragon #controls :is(
|
||||
.scene-control.active,
|
||||
.control-tool.active,
|
||||
.scene-control:hover,
|
||||
.control-tool:hover
|
||||
) {
|
||||
background: #482e1c;
|
||||
background-origin: padding-box;
|
||||
border-image: url(../assets/ui/footer-button.webp) 10 repeat;
|
||||
@@ -2292,7 +2423,7 @@ select,
|
||||
pointer-events: all;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon div.horloge-roue div.horloge-cercle {
|
||||
background: hsl(60, 20%, 95%) url(../assets/ui/bg_left.webp) no-repeat left top;
|
||||
background: hsla(60, 20%, 90%, 0.8);
|
||||
top: 2%;
|
||||
left: 2%;
|
||||
width: 96%;
|
||||
@@ -2549,7 +2680,7 @@ select,
|
||||
top: calc(50% - 0.4rem + 0.5 * 28%);
|
||||
left: calc(50% - 0.4rem + -0.8660254 * 28%);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre,.calendar-vaisseau) img {
|
||||
.system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img {
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
border: none;
|
||||
vertical-align: bottom;
|
||||
@@ -2589,7 +2720,7 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon .calendar-vaisseau {
|
||||
grid-column: 9/10;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(.calendar-lyre,.calendar-vaisseau) {
|
||||
.system-foundryvtt-reve-de-dragon :is(.calendar-lyre, .calendar-vaisseau) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
@@ -2601,12 +2732,12 @@ select,
|
||||
visibility: hidden;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon div.horloge-digitale {
|
||||
color: #CCC;
|
||||
color: #ccc;
|
||||
background: hsl(0, 0%, 20%);
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon div.horloge-digitale :is(.calendar-heure-texte,.calendar-minute-texte) {
|
||||
.system-foundryvtt-reve-de-dragon div.horloge-digitale :is(.calendar-heure-texte, .calendar-minute-texte) {
|
||||
font-size: 1rem;
|
||||
pointer-events: all;
|
||||
margin: 0;
|
||||
@@ -2676,6 +2807,13 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div:nth-child(odd) {
|
||||
background: var(--background-tooltip-alt);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div img {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon aside#tooltip {
|
||||
max-width: 15rem;
|
||||
background: var(--background-tooltip);
|
||||
@@ -2692,8 +2830,23 @@ select,
|
||||
.system-foundryvtt-reve-de-dragon aside#tooltip .toolclip p.faint {
|
||||
color: var(--color-tooltip-faint);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-info {
|
||||
font-size: 1.1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-info img {
|
||||
margin: 0 0.5rem;
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .jet-astrologie {
|
||||
color: var(--major-button-color) !important;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button,
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed {
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-checked,
|
||||
.system-foundryvtt-reve-de-dragon select.chat-card-select {
|
||||
border-radius: 0.2rem;
|
||||
cursor: pointer;
|
||||
font-family: CaslonPro;
|
||||
@@ -2706,29 +2859,27 @@ select,
|
||||
display: inline-block;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button img,
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed img {
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-checked img,
|
||||
.system-foundryvtt-reve-de-dragon select.chat-card-select img {
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-info {
|
||||
font-size: 1.1rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.system-foundryvtt-reve-de-dragon select.chat-card-select {
|
||||
width: calc(100% - 0.6rem);
|
||||
color: var(--major-button-color);
|
||||
background-color: var(--background-color-custom-button);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-info img {
|
||||
margin: 0 0.5rem;
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
filter: invert(0.8);
|
||||
.system-foundryvtt-reve-de-dragon select.chat-card-select option {
|
||||
background-color: var(--background-color-custom-button);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button {
|
||||
text-shadow: 1px 1px #4d3534;
|
||||
box-shadow: inset 1x 1px #a6827e;
|
||||
color: var(--major-button-color);
|
||||
background: var(--background-custom-button);
|
||||
background-color: #7d5d3b00;
|
||||
background-color: var(--background-color-custom-button);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed {
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-checked {
|
||||
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
|
||||
box-shadow: inset -1px -1px #a6827e;
|
||||
color: hsla(202, 42%, 14%, 0.7);
|
||||
@@ -2737,14 +2888,12 @@ select,
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:hover {
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-checked:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button:active,
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:active {
|
||||
.system-foundryvtt-reve-de-dragon .chat-card-button-checked:active {
|
||||
position: relative;
|
||||
top: 1px;
|
||||
}
|
||||
@@ -2811,7 +2960,7 @@ select,
|
||||
background: none;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon #pause > h3 {
|
||||
color: #CCC;
|
||||
color: #ccc;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon #pause > img {
|
||||
content: url(../assets/ui/rdd_pause.webp);
|
||||
@@ -2826,7 +2975,7 @@ select,
|
||||
height: 68px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon div.vl {
|
||||
border: 1px solid ;
|
||||
border: 1px solid;
|
||||
border-color: hsla(0, 0%, 0%, 0.5);
|
||||
height: inherit;
|
||||
min-height: max-content;
|
||||
|
||||
|
After Width: | Height: | Size: 8.3 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"TYPES": {
|
||||
"Actor": {
|
||||
"Actor": {
|
||||
"personnage": "Personnage",
|
||||
"creature": "Créature",
|
||||
"entite": "Entité de cauchemar",
|
||||
@@ -63,10 +63,12 @@
|
||||
"StatusUnarmed": "Désarmé",
|
||||
"StatusGrappling": "Empoignade",
|
||||
"StatusGrappled": "Empoigné",
|
||||
"StatusMalade": "Malade",
|
||||
"StatusRestrained": "Immobilisé",
|
||||
"StatusComma": "Comma",
|
||||
"StatusDead": "Mort",
|
||||
"StatusDemiReve": "Demi-rêve",
|
||||
"StatusSurEnc": "Sur-encombrement",
|
||||
"StatusForceWeak": "Force insuffisante"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:root {
|
||||
body {
|
||||
|
||||
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
|
||||
// --debug-background-color-red: #ff000054;
|
||||
@@ -13,6 +13,7 @@
|
||||
/* =================== 3. some constants ============ */
|
||||
--fieldset-background: url(/ui/parchment.jpg);
|
||||
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--rdd-input-background:hsla(0, 0%, 0%, 0.1);
|
||||
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
|
||||
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
|
||||
@@ -44,7 +45,9 @@
|
||||
hsla(50, 100%, 80%, 0.7)
|
||||
);
|
||||
|
||||
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-color-button: hsl(25, 5%, 60%);
|
||||
--background-color-custom-button: hsla(208, 38%, 21%, 0.988);
|
||||
--background-custom-button: linear-gradient(to bottom, var(--background-color-custom-button) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, hsla(0, 100%, 25%, 1) 5%, hsla(0, 97%, 12%, 1) 100%);
|
||||
--background-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);
|
||||
|
||||
@@ -70,8 +70,7 @@
|
||||
/* Fonts */
|
||||
.sheet header.sheet-header h1 input,
|
||||
.window-app .window-header,
|
||||
#actors .directory-list,
|
||||
#navigation #scene-list .scene.nav-item {
|
||||
#sidebar {
|
||||
font-family: "GoudyAcc"
|
||||
}
|
||||
|
||||
@@ -80,6 +79,6 @@
|
||||
.window-app input,
|
||||
.sheet header.sheet-header .header-compteurs,
|
||||
.sheet header.sheet-header .flex-group-center.flex-fatigue,
|
||||
select, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
|
||||
select, .item-checkbox, #players {
|
||||
font-family: "CaslonAntique"; /* For sheet parts; For nav and title */
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
"img header buttons"
|
||||
"img resume buttons"
|
||||
"details details details"
|
||||
"actions actions actions";
|
||||
"description description description"
|
||||
"actions actions actions"
|
||||
;
|
||||
grid-template-columns: 3rem 1fr 1.4rem;
|
||||
grid-template-rows: max-content max-content max-content max-content;
|
||||
gap: 0 0.5rem;
|
||||
@@ -37,6 +39,9 @@
|
||||
text-align: justify;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
div.chat-actions {
|
||||
grid-area: actions;
|
||||
@@ -50,6 +55,15 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
div.chat-description {
|
||||
grid-area: description;
|
||||
text-align: justify;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
div.chat-buttons {
|
||||
grid-area: buttons;
|
||||
|
||||
@@ -160,6 +160,9 @@
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
|
||||
roll-section[name="resistance"] {
|
||||
align-items: flex-end;
|
||||
}
|
||||
roll-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -174,6 +177,12 @@
|
||||
margin: 0 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
img.flag-resistance {
|
||||
max-width: 1.5rem;
|
||||
max-height: 1.5rem;
|
||||
text-align: right;
|
||||
filter: invert(0.6);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,15 +233,19 @@
|
||||
max-width: 4rem;
|
||||
}
|
||||
|
||||
roll-conditions roll-section[name="tricher"] img {
|
||||
/* image de d100 */
|
||||
max-width: 2.5rem;
|
||||
max-height: 2.5rem;
|
||||
roll-conditions roll-section img {
|
||||
max-width: 1rem;
|
||||
max-height: 1rem;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
roll-conditions roll-section[name="tricher"] img {
|
||||
/* image de d100 */
|
||||
max-width: 2.5rem;
|
||||
max-height: 2.5rem;
|
||||
}
|
||||
|
||||
roll-buttons {
|
||||
display: flex;
|
||||
|
||||
@@ -18,6 +18,7 @@ import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
|
||||
import { RdDCoeur } from "./coeur/rdd-coeur.js";
|
||||
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
|
||||
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
|
||||
import { MORAL } from "./moral/apprecier.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
@@ -208,7 +209,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
}
|
||||
|
||||
// Points de reve actuel
|
||||
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollCarac(CARACS.REVE_ACTUEL, { resistance: true }))
|
||||
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false }))
|
||||
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveActuel({ diff: -8, resistance: true }))
|
||||
this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
|
||||
|
||||
this.html.find('.roll-arme').click(async event => {
|
||||
@@ -274,9 +276,9 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value))
|
||||
|
||||
this.html.find('.stress-test').click(async event => await this.actor.transformerStress())
|
||||
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral('malheureuse'))
|
||||
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral('neutre'))
|
||||
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral('heureuse'))
|
||||
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX))
|
||||
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral(MORAL.NEUTRE))
|
||||
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral(MORAL.HEUREUX))
|
||||
this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme())
|
||||
|
||||
this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1))
|
||||
@@ -342,7 +344,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async createEmptyTache() {
|
||||
await this.actor.createItem('tache', 'Nouvelle tache');
|
||||
await this.actor.createItem(ITEM_TYPES.tache, 'Nouvelle tache')
|
||||
}
|
||||
|
||||
_getActionCombat(event) {
|
||||
@@ -375,14 +377,6 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.actor.update(formData);
|
||||
}
|
||||
|
||||
async splitItem(item) {
|
||||
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
|
||||
dialog.render(true);
|
||||
|
||||
@@ -41,17 +41,19 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||
import { RdDRencontre } from "./item/rencontre.js";
|
||||
import { DialogSelect } from "./dialog-select.js";
|
||||
import { PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js";
|
||||
import { CATEGORIES_COMPETENCES, PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js";
|
||||
|
||||
import { RdDRollResult } from "./rdd-roll-result.js";
|
||||
import { RdDInitiative } from "./initiative.mjs";
|
||||
import RollDialog from "./roll/roll-dialog.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
|
||||
import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION } from "./roll/roll-constants.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
||||
import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs";
|
||||
import { PART_TACHE } from "./roll/roll-part-tache.mjs";
|
||||
import { PART_COMP } from "./roll/roll-part-comp.mjs";
|
||||
import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
|
||||
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
|
||||
import { RdDPossessionV2 } from "./rdd-possession-v2.mjs";
|
||||
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
|
||||
|
||||
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
|
||||
|
||||
@@ -130,11 +132,6 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
return etatGeneral
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getActivePoisons() {
|
||||
return foundry.utils.duplicate(this.items.filter(item => item.type == 'poison' && item.system.active))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getMalusArmure() {
|
||||
return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
|
||||
@@ -165,12 +162,15 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getDemiReve() { return this.system.reve.tmrpos.coord }
|
||||
getDraconics() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') }
|
||||
getDraconics() {
|
||||
return this.isHautRevant()
|
||||
? this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == CATEGORIES_COMPETENCES.draconic.key)
|
||||
: []
|
||||
}
|
||||
getBestDraconic() { return foundry.utils.duplicate([...this.getDraconics(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
|
||||
getDraconicOuPossession() {
|
||||
return [...this.getDraconics().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC]
|
||||
.sort(Misc.descending(it => it.system.niveau))
|
||||
.find(it => true)
|
||||
|
||||
getConjurationNaturelle() {
|
||||
return new RdDItemCompetence(POSSESSION_SANS_DRACONIC)
|
||||
}
|
||||
|
||||
isForceInsuffisante(forceRequise) {
|
||||
@@ -184,13 +184,16 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
const actions = []
|
||||
const uniques = []
|
||||
|
||||
const addAttaque = (arme, main = undefined, action = 'attaque') => {
|
||||
const dommagesArme = RdDItemArme.valeurMain(arme.system.dommages, main)
|
||||
const addAttaque = (arme, main = undefined) => {
|
||||
const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
|
||||
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
||||
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
|
||||
|
||||
const comp = this.getCompetence(RdDActor.$getCompetenceAction(arme, main))
|
||||
const unique = [comp.id, arme.name, dommagesArme, forceRequise, ecaillesEfficacite].join('|');
|
||||
const comp = this.getCompetence(arme.getCompetenceAction(main), { onMessage: message => { console.info(message) } })
|
||||
if (!comp) {
|
||||
return
|
||||
}
|
||||
const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|');
|
||||
if (uniques.includes(unique)) {
|
||||
return
|
||||
}
|
||||
@@ -211,24 +214,20 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
main: main,
|
||||
carac: { key: caracCode, value: caracValue },
|
||||
equipe: arme.system.equipe,
|
||||
dommagesArme: dommagesArme,
|
||||
dommages: dommages,
|
||||
forceRequise: forceRequise,
|
||||
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
|
||||
})
|
||||
}
|
||||
|
||||
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
|
||||
|
||||
this.itemTypes[ITEM_TYPES.arme]
|
||||
.filter(it => it.isAttaque())
|
||||
.sort(Misc.ascending(it => it.name))
|
||||
.forEach(arme => {
|
||||
if (arme.system.unemain && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
|
||||
if (arme.system.deuxmains && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
|
||||
if (arme.system.lancer && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
|
||||
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
|
||||
})
|
||||
.forEach(arme => arme.getTypeAttaques().forEach(t => addAttaque(arme, t)))
|
||||
|
||||
addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS)
|
||||
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS, 'empoignade')
|
||||
|
||||
return actions
|
||||
}
|
||||
@@ -244,16 +243,6 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
}
|
||||
|
||||
static $getCompetenceAction(arme, main) {
|
||||
switch (main) {
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
|
||||
case ATTAQUE_TYPE.LANCER: return arme.system.lancer
|
||||
case ATTAQUE_TYPE.TIR: return arme.system.tir
|
||||
default: return arme.system.competence
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async $perteReveEnchantementsChateauDormants() {
|
||||
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
|
||||
@@ -343,10 +332,6 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
await this._recupererVie(message, isMaladeEmpoisonne);
|
||||
}
|
||||
|
||||
getMaladiesPoisons() {
|
||||
return this.items.filter(item => item.type == 'maladie' || (item.type == 'poison' && item.system.active));
|
||||
}
|
||||
|
||||
_messageRecuperationMaladiePoisons(maladiesPoisons, message) {
|
||||
if (maladiesPoisons.length > 0) {
|
||||
const identifies = maladiesPoisons.filter(it => it.system.identifie);
|
||||
@@ -378,15 +363,15 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
content: ""
|
||||
};
|
||||
|
||||
await this._recuperationSante(message);
|
||||
await this._recupereMoralChateauDormant(message);
|
||||
await this._recupereChance();
|
||||
await this.transformerStress();
|
||||
await this.retourSeuilDeReve(message);
|
||||
await this.setBonusPotionSoin(0);
|
||||
await this.retourSust(message);
|
||||
await this.$perteReveEnchantementsChateauDormants();
|
||||
await this.$suppressionLancementsSort();
|
||||
await this._recuperationSante(message)
|
||||
await this._recupereMoralChateauDormant(message)
|
||||
await this._recupereChance()
|
||||
await this.transformerStress()
|
||||
await this.retourSeuilDeReve(message)
|
||||
await this.setBonusPotionSoin(0)
|
||||
await this.retourSust(message)
|
||||
await this.$perteReveEnchantementsChateauDormants()
|
||||
await this.$suppressionLancementsSort()
|
||||
await RdDCoeur.applyCoeurChateauDormant(this, message);
|
||||
if (message.content != "") {
|
||||
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
|
||||
@@ -430,11 +415,13 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
|
||||
async _recupereMoralChateauDormant(message) {
|
||||
await this.update({ 'system.compteurs.bonmoments': [] }, { render: false })
|
||||
|
||||
if (!ReglesOptionnelles.isUsing("recuperation-moral")) { return }
|
||||
|
||||
const etatMoral = this.system.sommeil?.moral ?? 'neutre';
|
||||
const jetMoral = await this._jetDeMoral(etatMoral);
|
||||
message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement);
|
||||
const etatMoral = this.system.sommeil?.moral ?? MORAL.NEUTRE
|
||||
const jetMoral = await this._jetDeMoral(etatMoral)
|
||||
message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement)
|
||||
}
|
||||
|
||||
_messageAjustementMoral(ajustement) {
|
||||
@@ -708,7 +695,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
const rencontre = await game.system.rdd.rencontresTMR.getReveDeDragon(force);
|
||||
let rollData = {
|
||||
actor: this,
|
||||
competence: this.getDraconicOuPossession(),
|
||||
competence: this.getDraconicOuPossession().find(it => true),
|
||||
canClose: false,
|
||||
rencontre: rencontre,
|
||||
tmr: true,
|
||||
@@ -741,12 +728,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async sortMisEnReserve(sort, draconic, coord, ptreve) {
|
||||
await this.createEmbeddedDocuments("Item", [{
|
||||
type: ITEM_TYPES.sortreserve,
|
||||
name: sort.name,
|
||||
img: sort.img,
|
||||
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
|
||||
}],
|
||||
await this.createEmbeddedDocuments("Item", [RdDItemSort.prepareSortEnReserve(sort, draconic, ptreve, coord)],
|
||||
{ renderSheet: false });
|
||||
this.tmrApp.updateTokens();
|
||||
}
|
||||
@@ -760,20 +742,18 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
let updates = {};
|
||||
if (caracName == LIST_CARAC_PERSONNAGE.reve.code) {
|
||||
if (to > Misc.toInt(this.system.reve.seuil.value)) {
|
||||
updates[`system.reve.seuil.value`] = to; // SFA : Direct and packed changes
|
||||
//this.setPointsDeSeuil(to);
|
||||
updates[`system.reve.seuil.value`] = to
|
||||
}
|
||||
}
|
||||
if (caracName == LIST_CARAC_PERSONNAGE.chance.code) {
|
||||
if (to > Misc.toInt(this.system.compteurs.chance.value)) {
|
||||
updates[`system.compteurs.chance.value`] = to; // SFA : Direct and packed changes
|
||||
//this.setPointsDeChance(to);
|
||||
updates[`system.compteurs.chance.value`] = to
|
||||
}
|
||||
}
|
||||
let selectedCarac = this.findCaracByName(caracName);
|
||||
const from = selectedCarac.value
|
||||
updates[`system.carac.${caracName}.value`] = to;
|
||||
await this.update(updates);
|
||||
await this.update(updates, { noHook: true });
|
||||
await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName);
|
||||
}
|
||||
|
||||
@@ -1218,17 +1198,21 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async jetDeMoral(situation, messageReussi = undefined, messageManque = undefined) {
|
||||
const jetMoral = await this._jetDeMoral(situation);
|
||||
const finMessage = (jetMoral.succes ? messageReussi : messageManque) ?? (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral");
|
||||
async jetDeMoral(situation, bonmoment = "") {
|
||||
if (bonmoment != "" && bonmoment != undefined && this.system.compteurs.bonmoments.includes(bonmoment)) {
|
||||
ui.notifications.info(`${this.name} a déjà gagné du moral après avoir passé un bon moment (${bonmoment}) pendant la journée, pas de gain de moral`)
|
||||
return
|
||||
}
|
||||
const jetMoral = await this._jetDeMoral(situation, bonmoment)
|
||||
const finMessage = (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral");
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getOwners(this),
|
||||
content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${situation} (${jetMoral.jet}/${jetMoral.difficulte}).`
|
||||
});
|
||||
return jetMoral.ajustement;
|
||||
content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${SITUATION_MORAL[situation] ?? situation} (${jetMoral.jet}/${jetMoral.difficulte}).`
|
||||
})
|
||||
return jetMoral.ajustement
|
||||
}
|
||||
|
||||
async _jetDeMoral(situation) {
|
||||
async _jetDeMoral(situation, bonmoment = "") {
|
||||
const moralActuel = Misc.toInt(this.system.compteurs.moral.value);
|
||||
const jet = await RdDDice.rollTotal("1d20");
|
||||
const difficulte = 10 + moralActuel;
|
||||
@@ -1240,14 +1224,18 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
difficulte: difficulte,
|
||||
succes: succes,
|
||||
ajustement: this._calculAjustementMoral(succes, moralActuel, situation)
|
||||
};
|
||||
await this.moralIncDec(jetMoral.ajustement);
|
||||
}
|
||||
await this.moralIncDec(jetMoral.ajustement, bonmoment);
|
||||
return jetMoral;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async moralIncDec(ajustementMoral) {
|
||||
async moralIncDec(ajustementMoral, bonmoment = "") {
|
||||
if (ajustementMoral != 0) {
|
||||
if (ajustementMoral > 0 && bonmoment != "" && bonmoment != undefined) {
|
||||
const bonmoments = [...this.system.compteurs.bonmoments, bonmoment]
|
||||
await this.update({ 'system.compteurs.bonmoments': bonmoments }, { render: false })
|
||||
}
|
||||
const startMoral = parseInt(this.system.compteurs.moral.value)
|
||||
const moralTheorique = startMoral + ajustementMoral
|
||||
if (moralTheorique > 3) { // exaltation
|
||||
@@ -1268,13 +1256,14 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
/* -------------------------------------------- */
|
||||
_calculAjustementMoral(succes, moral, situation) {
|
||||
switch (situation) {
|
||||
case 'heureux': case 'heureuse': return succes ? 1 : 0;
|
||||
case 'malheureuse': case 'malheureux': return succes ? 0 : -1;
|
||||
case 'neutre':
|
||||
if (succes && moral < 0) return 1;
|
||||
if (!succes && moral > 0) return -1;
|
||||
case MORAL.TRESHEUREUX: return succes ? 2 : 1
|
||||
case MORAL.HEUREUX: case 'heureuse': return succes ? 1 : 0
|
||||
case MORAL.MALHEUREUX: case 'malheureuse': return succes ? 0 : -1
|
||||
case MORAL.NEUTRE:
|
||||
if (succes && moral < 0) return 1
|
||||
if (!succes && moral > 0) return -1
|
||||
}
|
||||
return 0;
|
||||
return 0
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -1333,33 +1322,31 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
const item = this.getItem(itemId)
|
||||
if (!item.getUtilisationCuisine()) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (choix.doses > item.system.quantite) {
|
||||
ui.notifications.warn(`Il n'y a pas assez de ${item.name} pour manger ${choix.doses}`)
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (!this._apprecierCuisine(item, choix.seForcer)) {
|
||||
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
|
||||
return;
|
||||
}
|
||||
await this.manger(item, choix.doses, { diminuerQuantite: false });
|
||||
await this.boire(item, choix.doses, { diminuerQuantite: false });
|
||||
await item.diminuerQuantite(choix.doses, choix);
|
||||
}
|
||||
|
||||
async _apprecierCuisine(item, seForcer) {
|
||||
const surmonteExotisme = await this._surmonterExotisme(item, seForcer);
|
||||
if (surmonteExotisme) {
|
||||
await this.apprecier(CARACS.ODORATGOUT, 'cuisine', item.system.qualite, item.system.boisson ? "apprécie la boisson" : "apprécie le plat");
|
||||
const onManger = [
|
||||
async () => await this.manger(item, choix.doses, { diminuerQuantite: false }),
|
||||
async () => await this.boire(item, choix.doses, { diminuerQuantite: false }),
|
||||
async () => await item.diminuerQuantite(choix.doses, choix)
|
||||
]
|
||||
|
||||
if (await this._surmonterExotisme(item)) {
|
||||
const appreciation = item.system.appreciation;
|
||||
new Apprecier(this, appreciation, item.system.qualite)
|
||||
.apprecier(onManger)
|
||||
}
|
||||
else if (seForcer) {
|
||||
await this.jetDeMoral('malheureux');
|
||||
else if (choix.seForcer) {
|
||||
await this.jetDeMoral(MORAL.MALHEUREUX)
|
||||
await Promise.all(onManger.map(async callback => await callback()))
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -1385,7 +1372,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
const rolled = await this.doRollCaracCompetence(carac, undefined, 0, { title });
|
||||
if (rolled?.isSuccess) {
|
||||
await this.jetDeMoral('heureux');
|
||||
await this.jetDeMoral(MORAL.HEUREUX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1452,7 +1439,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
ethylismeData.perteEndurance = await this.santeIncDec("endurance", -perte);
|
||||
|
||||
if (!ethylisme.jet_moral) {
|
||||
ethylismeData.jetMoral = await this._jetDeMoral('heureuse');
|
||||
ethylismeData.jetMoral = await this._jetDeMoral(MORAL.HEUREUX, "Ethylisme");
|
||||
if (ethylismeData.jetMoral.ajustement == 1) {
|
||||
ethylismeData.moralAlcool = 'heureux';
|
||||
ethylisme.jet_moral = true;
|
||||
@@ -1460,7 +1447,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
ethylismeData.jetMoral.ajustement = -1;
|
||||
ethylismeData.moralAlcool = 'triste';
|
||||
ethylisme.jet_moral = true;
|
||||
await this.moralIncDec(-1);
|
||||
await this.moralIncDec(-1, "Ethylisme");
|
||||
}
|
||||
}
|
||||
if (ethylisme.value < 0) {
|
||||
@@ -1654,7 +1641,8 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
return
|
||||
}
|
||||
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
|
||||
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance);
|
||||
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence,
|
||||
rollData.v2 ? rollData.type.resistance : rollData.jetResistance);
|
||||
if (xpData.length) {
|
||||
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.hbs`, {
|
||||
actor: this,
|
||||
@@ -1712,15 +1700,18 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!")
|
||||
return
|
||||
}
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
return await this.rollUnSortV2();
|
||||
}
|
||||
// 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;
|
||||
return
|
||||
}
|
||||
|
||||
const draconicList = this.computeDraconicAndSortIndex(sorts);
|
||||
const reve = foundry.utils.duplicate(this.system.carac.reve);
|
||||
const draconicList = this.computeDraconicAndSortIndex(sorts)
|
||||
const reve = foundry.utils.duplicate(this.system.carac.reve)
|
||||
|
||||
const dialog = await this.openRollDialog({
|
||||
name: 'lancer-un-sort',
|
||||
@@ -1743,6 +1734,27 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
this.tmrApp?.setTMRPendingAction(dialog);
|
||||
}
|
||||
|
||||
async rollUnSortV2() {
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT }
|
||||
};
|
||||
const dialog = await RollDialog.create(rollData, {
|
||||
callbacks: [async roll => {
|
||||
await this.tmrApp?.restoreTMRAfterAction();
|
||||
if (roll.closeTMR) {
|
||||
await this.tmrApp?.close();
|
||||
this.tmrApp = undefined;
|
||||
}
|
||||
}],
|
||||
onRollDone: RollDialog.onRollDoneClose,
|
||||
onClose: async () => {
|
||||
await this.tmrApp?.restoreTMRAfterAction();
|
||||
}
|
||||
});
|
||||
this.tmrApp?.setTMRPendingAction(dialog);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
|
||||
let addMsg = "";
|
||||
@@ -1814,11 +1826,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
else {
|
||||
console.log('lancement de sort', rollData.selectedSort)
|
||||
const precedents = rollData.selectedSort.system.lancements ?? []
|
||||
const lancements = [...precedents, {
|
||||
timestamp: game.system.rdd.calendrier.getTimestamp(),
|
||||
reve: rollData.selectedSort.system.ptreve_reel
|
||||
}]
|
||||
const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel)
|
||||
await this.updateEmbeddedDocuments('Item',
|
||||
[{ _id: rollData.selectedSort._id, 'system.lancements': lancements }]
|
||||
)
|
||||
@@ -1942,8 +1950,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
diff: { value: diff ?? 0 }
|
||||
}
|
||||
}
|
||||
RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose }))
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
@@ -1977,8 +1984,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
selected: { tache: { key: tache.id, forced: options.forced } },
|
||||
type: { allowed: [PART_TACHE], current: PART_TACHE }
|
||||
}
|
||||
RollDialog.create(rollData, options)
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
const compData = this.getCompetence(tache.system.competence)
|
||||
@@ -2037,8 +2043,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
selected: { jeu: { key: jeu.id } },
|
||||
type: { allowed: [ROLL_TYPE_JEU], current: ROLL_TYPE_JEU }
|
||||
}
|
||||
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
const listCarac = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim());
|
||||
@@ -2066,8 +2071,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
selected: { meditation: { key: id } },
|
||||
type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION }
|
||||
}
|
||||
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
|
||||
@@ -2109,7 +2113,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
/* -------------------------------------------- */
|
||||
_getSignesDraconiques(coord) {
|
||||
const type = TMRUtility.getTMRType(coord);
|
||||
return this.itemTypes["signedraconique"].filter(it => it.system.typesTMR.includes(type));
|
||||
return this.itemTypes[ITEM_TYPES.signedraconique].filter(it => it.system.typesTMR.includes(type));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -2121,18 +2125,19 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
async rollLireSigneDraconique(coord) {
|
||||
if (!this.isHautRevant()) {
|
||||
ui.notifications.info("Seul un haut rêvant peut lire un signe draconique!");
|
||||
return;
|
||||
return
|
||||
}
|
||||
let signes = this._getSignesDraconiques(coord);
|
||||
let signes = this._getSignesDraconiques(coord)
|
||||
if (signes.length == 0) {
|
||||
ui.notifications.info(`Aucun signe draconiques en ${coord} !`);
|
||||
return;
|
||||
ui.notifications.info(`Aucun signe draconiques en ${coord} !`)
|
||||
return
|
||||
}
|
||||
|
||||
let draconicList = this.getDraconics()
|
||||
.map(draconic => {
|
||||
let draconicLecture = foundry.utils.duplicate(draconic);
|
||||
draconicLecture.system.defaut_carac = "intellect";
|
||||
return draconicLecture;
|
||||
let draconicLecture = foundry.utils.duplicate(draconic)
|
||||
draconicLecture.system.defaut_carac = "intellect"
|
||||
return draconicLecture
|
||||
});
|
||||
|
||||
const intellect = this.system.carac.intellect;
|
||||
@@ -2265,7 +2270,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
const xpCompetence = competence ? xp - xpCarac : 0;
|
||||
if (jetResistance) {
|
||||
const message = `Jet de résistance ${jetResistance}, l'expérience est limitée à 1`;
|
||||
const message = `Jet de résistance, l'expérience est limitée à 1`;
|
||||
ui.notifications.info(message);
|
||||
console.log(message)
|
||||
// max 1 xp sur jets de résistance
|
||||
@@ -2406,7 +2411,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
if (this.tmrApp) {
|
||||
ui.notifications.warn("Vous êtes déja dans les TMR....")
|
||||
this.tmrApp.forceTMRDisplay()
|
||||
return
|
||||
return false
|
||||
}
|
||||
if (mode != 'visu' && this.isDemiReve()) {
|
||||
ui.notifications.warn("Le personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
|
||||
@@ -2414,6 +2419,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
if (mode == 'visu') {
|
||||
await this._doDisplayTMR(mode)
|
||||
return false
|
||||
}
|
||||
else {
|
||||
const rencontre = this.getRencontreTMREnAttente();
|
||||
@@ -2426,6 +2432,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
buttonLabel: 'Monter dans les TMR',
|
||||
onAction: async () => await this._doDisplayTMR(mode)
|
||||
})
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2463,6 +2470,29 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
await this.tmrApp.onDeplacement()
|
||||
}
|
||||
|
||||
async quitterTMR(message, viewOnly, cumulFatigue) {
|
||||
if (this.tmrApp) {
|
||||
this.tmrApp = undefined
|
||||
const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
|
||||
await this.santeIncDec(
|
||||
appliquerFatigue ? "fatigue" : "endurance",
|
||||
(appliquerFatigue ? 1 : -1) * cumulFatigue)
|
||||
if (!viewOnly) {
|
||||
await this.supprimerSignesDraconiques(it => it.system.ephemere && it.system.duree == '1 round', { render: false })
|
||||
await this.setEffect(STATUSES.StatusDemiReve, false)
|
||||
ChatUtility.tellToUserAndGM(message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async supprimerSignesDraconiques(filter = it => true, options = { render: true }) {
|
||||
const signes = this.itemTypes[ITEM_TYPES.signedraconique].filter(filter)
|
||||
if (signes.length > 0) {
|
||||
this.deleteEmbeddedDocuments("Item", signes.map(item => item.id), options)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollSoins(blesse, blessureId) {
|
||||
const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
|
||||
@@ -2548,7 +2578,12 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
conjurerPossession(possession) {
|
||||
RdDPossession.onConjurerPossession(this, possession)
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
RdDPossessionV2.rollConjurerPossession(this, possession)
|
||||
}
|
||||
else {
|
||||
RdDPossession.onConjurerPossession(this, possession)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -2566,7 +2601,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
if (item?.isEquipable()) {
|
||||
const isEquipe = !item.system.equipe;
|
||||
await item.update({ "system.equipe": isEquipe });
|
||||
this.computeEncTotal();
|
||||
this.computeEncTotal()
|
||||
if (isEquipe)
|
||||
this.verifierForceMin(item);
|
||||
}
|
||||
@@ -2957,6 +2992,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
if (updatedEndurance && options.diff) {
|
||||
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
|
||||
}
|
||||
await super.onUpdateActor(update, options, actorId)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -2999,9 +3035,12 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
break
|
||||
case ITEM_TYPES.empoignade:
|
||||
await RdDEmpoignade.deleteLinkedEmpoignade(this.id, item)
|
||||
// TODO: check remaining emp.
|
||||
await this.setEffect(STATUSES.StatusGrappled, false)
|
||||
await this.setEffect(STATUSES.StatusGrappling, false)
|
||||
break
|
||||
}
|
||||
super.onDeleteItem(item, options, id)
|
||||
await super.onDeleteItem(item, options, id)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -3116,7 +3155,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
selected: { oeuvre: { key: oeuvre.id } },
|
||||
type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, },
|
||||
}
|
||||
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -3221,8 +3260,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
cuisine: { key: recette.id }
|
||||
}
|
||||
}
|
||||
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
const artData = {
|
||||
@@ -3272,8 +3310,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
cuisine: { key: item.id }
|
||||
}
|
||||
}
|
||||
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
if (item.getUtilisationCuisine() == 'brut') {
|
||||
|
||||
@@ -56,13 +56,15 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
|
||||
if (this.options.vueDetaillee) {
|
||||
// On carac change
|
||||
this.html.find('.carac-value').change(async event => {
|
||||
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "")
|
||||
await this.actor.updateCarac(caracName, parseInt(event.target.value))
|
||||
});
|
||||
if (event.currentTarget.name.includes("carac.")) {
|
||||
let caracName = event.currentTarget.name.replace("carac.", "")
|
||||
await this.actor.updateCarac(caracName, parseInt(event.currentTarget.value))
|
||||
}
|
||||
})
|
||||
// On competence change
|
||||
this.html.find('.competence-value').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value
|
||||
await this.actor.updateCompetence(compName, parseInt(event.target.value))
|
||||
await this.actor.updateCompetence(compName, parseInt(event.currentTarget.value))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ENTITE_INCARNE, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
|
||||
import { RDD_CONFIG, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDResolutionTable } from "../rdd-resolution-table.js";
|
||||
@@ -22,13 +22,16 @@ import { DialogValidationEncaissement } from "../dialog-validation-encaissement.
|
||||
import { RdDCombat } from "../rdd-combat.js";
|
||||
import { RdDEmpoignade } from "../rdd-empoignade.js";
|
||||
import { RdDPossession } from "../rdd-possession.js";
|
||||
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js";
|
||||
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js";
|
||||
import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
|
||||
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
|
||||
import RollDialog from "../roll/roll-dialog.mjs";
|
||||
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE } from "../roll/roll-constants.mjs";
|
||||
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE} from "../roll/roll-constants.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
|
||||
import { PART_COMP } from "../roll/roll-part-comp.mjs";
|
||||
import { RdDInitiative } from "../initiative.mjs";
|
||||
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
|
||||
|
||||
/**
|
||||
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
||||
@@ -89,7 +92,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
getSConst() { return 0 }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isSurenc() { return false }
|
||||
computeMalusSurEncombrement() { return 0 }
|
||||
|
||||
ajustementAstrologique() { return 0 }
|
||||
@@ -115,27 +117,73 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return this.system.carac[competence.system.defaut_carac].value;
|
||||
}
|
||||
|
||||
getDraconics() { return [] }
|
||||
getDraconicOuPossession() {
|
||||
return [
|
||||
...this.getDraconics(),
|
||||
...this.itemTypes[ITEM_TYPES.competencecreature].filter(it => it.isCompetencePossession()),
|
||||
this.getConjurationNaturelle()
|
||||
].sort(Misc.descending(it => it.system.niveau));
|
||||
}
|
||||
|
||||
getConjurations() {
|
||||
return this.getDraconicOuPossession()
|
||||
.map(it => this.toActionConjuration(it))
|
||||
}
|
||||
|
||||
getConjurationNaturelle() {
|
||||
return new RdDItemCompetenceCreature({
|
||||
name: 'Sans compétence',
|
||||
type: ITEM_TYPES.competencecreature,
|
||||
img: RDD_CONFIG.icons.possession,
|
||||
system: {
|
||||
carac_value: this.getReveActuel(),
|
||||
niveau: 0,
|
||||
default_diffLibre: 0,
|
||||
categorie: CATEGORIES_COMPETENCES_CREATURES.possession.key,
|
||||
ispossession: true,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
toActionConjuration(comp) {
|
||||
const caracCode = this.isPersonnage() ? CARACS.REVE_ACTUEL : CARACS.REVE
|
||||
const caracValue = this.getReveActuel()
|
||||
const ajustement = this.getEtatGeneral()
|
||||
return {
|
||||
label: `Conjuration (${comp.name})`,
|
||||
action: 'possession',
|
||||
initOnly: false,
|
||||
comp: comp,
|
||||
carac: { key: caracCode, value: caracValue },
|
||||
initiative: RdDInitiative.getRollInitiative(caracValue, comp.system.niveau, ajustement)
|
||||
}
|
||||
}
|
||||
|
||||
listActions({ isAttaque = false, isEquipe = false }) {
|
||||
return this.itemTypes[ITEM_TYPES.competencecreature]
|
||||
.filter(it => it.isAttaque())
|
||||
.map(it => it.attaqueCreature())
|
||||
.filter(it => it != undefined);
|
||||
.filter(it => it != undefined)
|
||||
}
|
||||
|
||||
async computeArmure(dmg) { return this.getProtectionNaturelle() }
|
||||
async remiseANeuf() { }
|
||||
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
|
||||
|
||||
computeResumeBlessure() { }
|
||||
countBlessures(filter = it => !it.isContusion()) { return 0 }
|
||||
async santeIncDec(name, inc, isCritique = false) { }
|
||||
|
||||
async finDeRound(options = { terminer: false }) {
|
||||
await this.$finDeRoundSuppressionEffetsTermines(options);
|
||||
await this.finDeRoundBlessures();
|
||||
await this.$finDeRoundSupprimerObsoletes();
|
||||
await this.$finDeRoundEmpoignade();
|
||||
await this.finDeRoundSuppressionEffetsTermines(options)
|
||||
await this.finDeRoundBlessures()
|
||||
await this.finDeRoundSupprimerObsoletes()
|
||||
await this.finDeRoundEmpoignade()
|
||||
await this.finDeRoundPossession()
|
||||
}
|
||||
|
||||
async $finDeRoundSuppressionEffetsTermines(options) {
|
||||
async finDeRoundSuppressionEffetsTermines(options) {
|
||||
for (let effect of this.getEffects()) {
|
||||
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
|
||||
await effect.delete();
|
||||
@@ -147,20 +195,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
async finDeRoundBlessures() {
|
||||
}
|
||||
|
||||
async $finDeRoundSupprimerObsoletes() {
|
||||
async finDeRoundSupprimerObsoletes() {
|
||||
const obsoletes = []
|
||||
.concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
|
||||
.concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
|
||||
.map(it => it.id);
|
||||
.map(it => it.id)
|
||||
await this.deleteEmbeddedDocuments('Item', obsoletes);
|
||||
}
|
||||
|
||||
async $finDeRoundEmpoignade() {
|
||||
const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
|
||||
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
|
||||
game.actors.get(emp.system.empoigneid),
|
||||
emp
|
||||
))
|
||||
async finDeRoundEmpoignade() {
|
||||
await Promise.all(this.itemTypes[ITEM_TYPES.empoignade]
|
||||
.filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id)
|
||||
.map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
|
||||
}
|
||||
|
||||
async finDeRoundPossession(){
|
||||
await Promise.all(this.itemTypes[ITEM_TYPES.possession]
|
||||
.map(async it => await RdDPossessionV2.onPossession(this, it)))
|
||||
}
|
||||
|
||||
async setSonne(sonne = true) { }
|
||||
@@ -176,10 +226,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
}
|
||||
|
||||
getCompetences(name = undefined, options = { onMessage: message => { } }) {
|
||||
const all = [...this.itemTypes[ITEM_TYPES.competence], ...this.itemTypes[ITEM_TYPES.competencecreature]]
|
||||
if (name == undefined) {
|
||||
return this.itemTypes[ITEM_TYPES.competence]
|
||||
return all
|
||||
}
|
||||
return RdDItemCompetence.findCompetences(this.itemTypes[ITEM_TYPES.competence], name, options)
|
||||
return RdDItemCompetence.findCompetences(all, name, options)
|
||||
}
|
||||
|
||||
getCompetenceCorpsACorps(options = { onMessage: message => { } }) {
|
||||
@@ -198,11 +249,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return false
|
||||
}
|
||||
|
||||
getDraconicOuPossession() { return POSSESSION_SANS_DRACONIC }
|
||||
|
||||
getPossession(possessionId) {
|
||||
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
|
||||
}
|
||||
|
||||
getEmpoignades() {
|
||||
return this.itemTypes[ITEM_TYPES.empoignade];
|
||||
}
|
||||
@@ -226,53 +276,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isEffectAllowed(effectId) { return false }
|
||||
|
||||
getEffects(filter = e => true, forceRequise = undefined) {
|
||||
const effects = this.getEmbeddedCollection("ActiveEffect")
|
||||
const selected = effects.filter(filter)
|
||||
if (forceRequise && this.isForceInsuffisante(forceRequise)) {
|
||||
selected.push(StatusEffects.prepareActiveEffect(STATUSES.StatusForceWeak))
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
||||
getEffectByStatus(statusId) {
|
||||
return this.getEffects().find(it => it.statuses.has(statusId));
|
||||
}
|
||||
|
||||
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(statusId)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async removeEffect(id) {
|
||||
this.removeEffects(it => it.id == id)
|
||||
}
|
||||
|
||||
async removeEffects(filter = e => true) {
|
||||
if (game.user.isGM) {
|
||||
const effectsToRemove = this.getEffects(filter);
|
||||
const ids = effectsToRemove.map(it => it.id);
|
||||
await this.deleteEmbeddedDocuments('ActiveEffect', ids);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isDemiReve() {
|
||||
return this.getEffectByStatus(STATUSES.StatusDemiReve) != undefined
|
||||
return this.getEffectsByStatus(STATUSES.StatusDemiReve).length > 0
|
||||
}
|
||||
|
||||
getSurprise(isCombat = undefined) {
|
||||
return StatusEffects.getSurprise(this.getEffects(), isCombat)
|
||||
getSurprise(isCombat = undefined, forceRequise = undefined) {
|
||||
return StatusEffects.getSurprise(this.getEffects(e => true, isCombat, forceRequise), isCombat)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -309,6 +319,21 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
|
||||
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
const competence = this.getCompetence(compName);
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
|
||||
selected: {
|
||||
carac: { key: caracName },
|
||||
comp: { key: competence.name },
|
||||
diff: { value: diff }
|
||||
}
|
||||
}
|
||||
return await RollDialog.create(rollData, options)
|
||||
}
|
||||
|
||||
const competence = this.getCompetence(compName);
|
||||
await this.openRollDialog({
|
||||
name: 'jet-competence',
|
||||
@@ -380,6 +405,26 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
})
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async rollReveActuel({ diff = 0, resistance = false }) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: {
|
||||
allowed: [PART_COMP],
|
||||
current: PART_COMP,
|
||||
resistance: resistance
|
||||
},
|
||||
selected: {
|
||||
carac: { key: CARACS.REVE_ACTUEL, forced: true },
|
||||
comp: resistance ? { key: undefined, forced: true } : undefined,
|
||||
diff: { type: DIFF.DEFAUT, value: diff }
|
||||
}
|
||||
}
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
return this.rollCarac(CARACS.REVE_ACTUEL, { diff, resistance })
|
||||
}
|
||||
|
||||
async rollCarac(caracName, options = {}) {
|
||||
if (Grammar.equalsInsensitive(caracName, CARACS.TAILLE)) {
|
||||
return
|
||||
@@ -387,14 +432,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: { allowed: [PART_COMP], current: PART_COMP },
|
||||
type: {
|
||||
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES,
|
||||
current: PART_COMP,
|
||||
resistance: options.resistance
|
||||
},
|
||||
selected: {
|
||||
carac: { key: caracName },
|
||||
comp: options.resistance ? { key: undefined, forced: true } : undefined
|
||||
comp: options.resistance ? { key: undefined, forced: true } : undefined,
|
||||
diff: { type: DIFF.DEFAUT, value: options.diff ?? 0 }
|
||||
}
|
||||
}
|
||||
RollDialog.create(rollData, options)
|
||||
return
|
||||
return await RollDialog.create(rollData, options)
|
||||
}
|
||||
|
||||
foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false })
|
||||
@@ -423,32 +472,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-general.hbs');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollCompetenceV2(rollData) {
|
||||
rollData.ids = rollData?.ids ?? {}
|
||||
rollData.type = rollData.type ?? { allowed: DEFAULT_ROLL_TYPES }
|
||||
rollData.ids.actorId = this.id
|
||||
await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||
|
||||
const competence = this.getCompetence(idOrName);
|
||||
if (competence.type != ITEM_TYPES.competencecreature && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
const rollData = {
|
||||
ids: { actorId: this.id },
|
||||
type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES },
|
||||
selected: {
|
||||
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
|
||||
comp: { key: competence.name },
|
||||
diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 }
|
||||
diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
|
||||
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
|
||||
}
|
||||
}
|
||||
if (options.arme) {
|
||||
rollData.selected.attaque = { arme: { id: options.arme.id }, comp: { id: competence.id } }
|
||||
rollData.type = { allowed: ATTAQUE_ROLL_TYPES }
|
||||
}
|
||||
|
||||
await this.rollCompetenceV2(rollData)
|
||||
return
|
||||
return await RollDialog.create(rollData)
|
||||
}
|
||||
|
||||
let rollData = {
|
||||
@@ -512,19 +551,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
title: 'Ne pas utiliser les automatisation de combat',
|
||||
buttonLabel: "Pas d'automatisation",
|
||||
onAction: async () => {
|
||||
this.rollCompetenceV2({
|
||||
ids: {
|
||||
actorId: this.id,
|
||||
actorTokenId: token?.id,
|
||||
},
|
||||
selected: {
|
||||
conditions: { value: 0 }
|
||||
},
|
||||
const rollData = {
|
||||
ids: { actorId: this.id, actorTokenId: token?.id, },
|
||||
type: {
|
||||
allowed: [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE, ROLL_TYPE_JEU],
|
||||
current: ROLL_TYPE_COMP
|
||||
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
|
||||
}
|
||||
})
|
||||
};
|
||||
return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -571,6 +604,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
})
|
||||
}
|
||||
|
||||
rollPossession() {
|
||||
RdDPossessionV2.rollAttaquePossession(this)
|
||||
}
|
||||
|
||||
verifierForceMin(item) { }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -669,7 +706,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
async accorder(entite, when = 'avant-encaissement') {
|
||||
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|
||||
|| entite == undefined
|
||||
|| !entite.isEntite([ENTITE_INCARNE])
|
||||
|| !entite.isEntiteIncarnee()
|
||||
|| entite.isEntiteAccordee(this)) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -116,6 +116,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
blessure: blessure
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async santeIncDec(name, inc, isCritique = false) {
|
||||
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
@@ -129,7 +130,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
let result = {
|
||||
sonne: false,
|
||||
};
|
||||
|
||||
let perteEndurance = 0
|
||||
let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
|
||||
|
||||
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
|
||||
@@ -144,16 +145,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
|
||||
result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
|
||||
}
|
||||
const perte = compteur.value - result.newValue;
|
||||
result.perte = perte;
|
||||
if (perte > 1) {
|
||||
// Peut-être sonné si 2 points d'endurance perdus d'un coup
|
||||
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
|
||||
} else if (inc > 0) {
|
||||
await this.setSonne(false);
|
||||
}
|
||||
perteEndurance = compteur.value - result.newValue;
|
||||
result.perte = perteEndurance
|
||||
if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost
|
||||
fatigue = perte;
|
||||
fatigue = perteEndurance;
|
||||
}
|
||||
}
|
||||
compteur.value = result.newValue;
|
||||
@@ -162,6 +157,14 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
|
||||
}
|
||||
await this.update({ "system.sante": sante }, { render: true })
|
||||
|
||||
if (perteEndurance > 1) {
|
||||
// Peut-être sonné si 2 points d'endurance perdus d'un coup
|
||||
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
|
||||
} else if (name == "endurance" && inc > 0) {
|
||||
await this.setSonne(false);
|
||||
}
|
||||
|
||||
if (this.isDead()) {
|
||||
await this.setEffect(STATUSES.StatusComma, true);
|
||||
}
|
||||
@@ -179,6 +182,46 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
|
||||
}
|
||||
|
||||
async onCreateItem(item, options, id) {
|
||||
await this.changeItemEffects(item)
|
||||
await super.onCreateItem(item, options, id)
|
||||
}
|
||||
|
||||
async onUpdateItem(item, options, id) {
|
||||
await this.changeItemEffects(item);
|
||||
await super.onUpdateItem(item, options, id)
|
||||
}
|
||||
|
||||
async onDeleteItem(item, options, id) {
|
||||
await this.changeItemEffects(item);
|
||||
await super.onDeleteItem(item, options, id)
|
||||
}
|
||||
|
||||
async changeItemEffects(item) {
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.blessure:
|
||||
await this.changeStateBleeding();
|
||||
break;
|
||||
case ITEM_TYPES.maladie:
|
||||
case ITEM_TYPES.poison:
|
||||
await this.changeStateMalade();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
async changeStateBleeding() {
|
||||
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
|
||||
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
|
||||
}
|
||||
|
||||
async changeStateMalade() {
|
||||
const maladiePoisons = this.getMaladiesPoisons()
|
||||
await this.setEffect(STATUSES.StatusMalade, maladiePoisons.length > 0)
|
||||
}
|
||||
|
||||
getMaladiesPoisons() {
|
||||
return this.items.filter(it => [ITEM_TYPES.maladie, ITEM_TYPES.poison].includes(it.type))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async ajouterBlessure(encaissement, attackerToken = undefined) {
|
||||
@@ -292,7 +335,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
}
|
||||
|
||||
isSonne() {
|
||||
return this.getEffectByStatus(STATUSES.StatusStunned)
|
||||
return this.getEffectsByStatus(STATUSES.StatusStunned).length > 0
|
||||
}
|
||||
|
||||
isEffectAllowed(effectId) { return true }
|
||||
|
||||
@@ -49,15 +49,14 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
formData.calc = {
|
||||
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
|
||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||
encTotal: await this.actor.computeEncTotal(),
|
||||
encTotal: this.actor.getEncTotal(),
|
||||
}
|
||||
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
||||
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
|
||||
.forEach(it => it.isdommages = it.isDommages()
|
||||
)
|
||||
.forEach(it => it.isdommages = it.isDommages())
|
||||
|
||||
return formData;
|
||||
}
|
||||
@@ -230,14 +229,6 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.actor.update(formData);
|
||||
}
|
||||
|
||||
async splitItem(item) {
|
||||
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
|
||||
dialog.render(true);
|
||||
|
||||
@@ -10,7 +10,8 @@ import { RdDConfirm } from "../rdd-confirm.js";
|
||||
import { RdDUtility } from "../rdd-utility.js";
|
||||
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
||||
import { RdDItem } from "../item.js";
|
||||
import { STATUSES } from "../settings/status-effects.js";
|
||||
import { StatusEffects, STATUSES } from "../settings/status-effects.js";
|
||||
import { Apprecier } from "../moral/apprecier.mjs";
|
||||
|
||||
export class RdDBaseActor extends Actor {
|
||||
|
||||
@@ -215,9 +216,12 @@ export class RdDBaseActor extends Actor {
|
||||
return game.users.players.find(player => player.active && player.character?.id == this.id);
|
||||
}
|
||||
|
||||
isCreatureEntite() { return this.isCreature() || this.isEntite() }
|
||||
isCreatureOuEntite() { return this.isCreature() || this.isEntite() }
|
||||
isCreature() { return false }
|
||||
isEntite(typeentite = []) { return false }
|
||||
isEntite() { return false }
|
||||
isEntiteIncarnee() { return false }
|
||||
isEntiteNonIncarnee() { return false }
|
||||
isEntiteBlurette() { return false }
|
||||
isHautRevant() { return false }
|
||||
isVehicule() { return false }
|
||||
isPersonnage() { return false }
|
||||
@@ -241,41 +245,89 @@ export class RdDBaseActor extends Actor {
|
||||
|
||||
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
||||
getEncombrementMax() { return 0 }
|
||||
isSurenc() { return false }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isEffectAllowed(effectId) { return false }
|
||||
|
||||
getEffects(filter = e => true, forceRequise = undefined) {
|
||||
const effects = this.getEmbeddedCollection("ActiveEffect")
|
||||
const selected = effects.filter(filter)
|
||||
if (forceRequise && this.isForceInsuffisante(forceRequise)) {
|
||||
selected.push(StatusEffects.prepareActiveEffect(STATUSES.StatusForceWeak))
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
||||
getEffectsByStatus(effectId) {
|
||||
return this.getEffects().filter(it => it.statuses.has(effectId))
|
||||
}
|
||||
|
||||
async setEffect(effectId, status) {
|
||||
if (this.isEffectAllowed(effectId)) {
|
||||
const effects = this.getEffectsByStatus(effectId)
|
||||
if (!status && effects.length > 0) {
|
||||
await this.deleteEmbeddedDocuments('ActiveEffect', effects.map(it => it.id), { render: true })
|
||||
}
|
||||
if (status && effects.length == 0) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], { render: true })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async removeEffect(id) {
|
||||
this.removeEffects(it => it.id == id)
|
||||
}
|
||||
|
||||
async removeEffects(filter = e => true) {
|
||||
if (game.user.isGM) {
|
||||
const ids = this.getEffects(filter)
|
||||
.filter(it => this.canRemoveEffects(it))
|
||||
.map(it => it.id)
|
||||
if (ids.length > 0) {
|
||||
await this.deleteEmbeddedDocuments('ActiveEffect', ids)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
canRemoveEffects(effect) {
|
||||
if (effect.statuses.has(STATUSES.StatusSurEnc)) {
|
||||
return !this.isSurenc()
|
||||
}
|
||||
if (effect.statuses.has(STATUSES.StatusDemiReve)) {
|
||||
return !this.tmrApp
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async updateCarac(caracName, to) {
|
||||
}
|
||||
|
||||
async onUpdateActor(change, options, actorId) {
|
||||
const updatedCarac = change?.system?.carac
|
||||
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
|
||||
console.log(' onUpdateActor', change, options, actorId)
|
||||
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onPreUpdateItem(item, change, options, id) { }
|
||||
|
||||
async onCreateItem(item, options, id) {
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.blessure:
|
||||
await this.changeBleedingState()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async onUpdateItem(item, options, id) {
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.blessure:
|
||||
await this.changeBleedingState()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async changeBleedingState() {
|
||||
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
|
||||
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
|
||||
}
|
||||
|
||||
async onUpdateActor(update, options, actorId) { }
|
||||
async onDeleteItem(item, options, id) {
|
||||
if (item.isInventaire()) {
|
||||
await this._removeItemFromConteneur(item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async _removeItemFromConteneur(item) {
|
||||
const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
|
||||
.map(conteneur => {
|
||||
@@ -466,10 +518,13 @@ export class RdDBaseActor extends Actor {
|
||||
async acheter(item, quantite, cout, achat) {
|
||||
await this.depenserSols(cout)
|
||||
const createdItemId = await this.creerQuantiteItem(item, quantite)
|
||||
if (achat.choix.consommer && item.type == 'nourritureboisson' && createdItemId != undefined) {
|
||||
if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) {
|
||||
achat.choix.doses = achat.choix.nombreLots;
|
||||
await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId);
|
||||
}
|
||||
if (item.type == ITEM_TYPES.service) {
|
||||
new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
|
||||
}
|
||||
}
|
||||
|
||||
verifierFortune(cout) {
|
||||
@@ -524,16 +579,22 @@ export class RdDBaseActor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeEncTotal() {
|
||||
if (!this.pack) {
|
||||
if (this.pack) {
|
||||
this.encTotal = 0
|
||||
}
|
||||
else {
|
||||
const wasSurenc = this.isSurenc()
|
||||
this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type))
|
||||
.map(it => it.getEncTotal()).reduce(Misc.sum(), 0)
|
||||
return this.encTotal;
|
||||
const isSurenc = this.isSurenc()
|
||||
if (isSurenc != wasSurenc) {
|
||||
await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
getEncTotal() {
|
||||
return Math.floor(this.encTotal ?? 0);
|
||||
return Math.floor(this.encTotal ?? 0)
|
||||
}
|
||||
|
||||
async createItem(type, name = undefined) {
|
||||
@@ -584,7 +645,7 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
}
|
||||
}
|
||||
await this.computeEncTotal();
|
||||
await this.computeEncTotal()
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -792,6 +853,7 @@ export class RdDBaseActor extends Actor {
|
||||
|
||||
listActionsPossessions() {
|
||||
return this.itemTypes[ITEM_TYPES.possession]
|
||||
.filter(it => !it.system.possede)
|
||||
.map(p => {
|
||||
return {
|
||||
label: p.name,
|
||||
@@ -800,9 +862,4 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
})
|
||||
}
|
||||
listActionsCombat() {
|
||||
const possessions = this.listActionsPossessions()
|
||||
return possessions.length > 0 ? possessions : this.listActions({})
|
||||
|
||||
}
|
||||
}
|
||||
@@ -43,7 +43,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
|
||||
this.html.find('.resonance-add').click(async event =>
|
||||
await DialogSelect.select({
|
||||
label: "Choisir un acteur à accorder",
|
||||
list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink)
|
||||
list: game.actors.filter(it => true)
|
||||
},
|
||||
it => this.resonanceAdd(it.id))
|
||||
)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
|
||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
|
||||
import { ITEM_TYPES } from "../constants.js";
|
||||
import { RdDItemBlessure } from "../item/blessure.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDCarac } from "../rdd-carac.js";
|
||||
import { RdDEncaisser } from "../rdd-roll-encaisser.js";
|
||||
@@ -16,11 +17,10 @@ export class RdDEntite extends RdDBaseActorReve {
|
||||
return item.type == ITEM_TYPES.competencecreature
|
||||
}
|
||||
|
||||
isEntite(typeentite = []) {
|
||||
return (typeentite.length == 0 || typeentite.includes(this.system.definition.typeentite));
|
||||
}
|
||||
|
||||
isNonIncarnee() { return this.isEntite([ENTITE_NONINCARNE]) }
|
||||
isEntite() { return true }
|
||||
isEntiteNonIncarnee() { return this.system.definition.typeentite == ENTITE_NONINCARNE }
|
||||
isEntiteIncarnee() { return !this.isEntiteNonIncarnee() }
|
||||
isEntiteBlurette() { return this.system.definition.typeentite == ENTITE_BLURETTE }
|
||||
|
||||
getReveActuel() {
|
||||
return Misc.toInt(this.system.carac.reve?.value)
|
||||
@@ -41,28 +41,21 @@ export class RdDEntite extends RdDBaseActorReve {
|
||||
getChance() { return this.getReve() }
|
||||
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getReve()) }
|
||||
|
||||
getDraconicOuPossession() {
|
||||
return this.itemTypes[ITEM_TYPES.competencecreature]
|
||||
.filter(it => it.system.categorie == 'possession')
|
||||
.sort(Misc.descending(it => it.system.niveau))
|
||||
.find(it => true);
|
||||
}
|
||||
|
||||
async remiseANeuf() {
|
||||
await this.removeEffects(e => true);
|
||||
if (!this.isNonIncarnee()) {
|
||||
if (!this.isEntiteNonIncarnee()) {
|
||||
await this.update({
|
||||
'system.sante.endurance.value': this.system.sante.endurance.max
|
||||
});
|
||||
}
|
||||
await this.removeEffects(e => true)
|
||||
}
|
||||
|
||||
isDead() {
|
||||
return this.isNonIncarnee() ? false : this.system.sante.endurance.value <= 0
|
||||
return this.isEntiteNonIncarnee() ? false : this.system.sante.endurance.value <= 0
|
||||
}
|
||||
|
||||
async santeIncDec(name, inc, isCritique = false) {
|
||||
if (name == 'endurance' && !this.isNonIncarnee()) {
|
||||
if (name == 'endurance' && !this.isEntiteNonIncarnee()) {
|
||||
const oldValue = this.system.sante.endurance.value;
|
||||
const endurance = Math.max(0,
|
||||
Math.min(oldValue + inc,
|
||||
@@ -78,7 +71,7 @@ export class RdDEntite extends RdDBaseActorReve {
|
||||
}
|
||||
|
||||
async encaisser() {
|
||||
if (this.isNonIncarnee()) {
|
||||
if (this.isEntiteNonIncarnee()) {
|
||||
return
|
||||
}
|
||||
await RdDEncaisser.encaisser(this)
|
||||
@@ -89,24 +82,37 @@ export class RdDEntite extends RdDBaseActorReve {
|
||||
}
|
||||
|
||||
async onAppliquerJetEncaissement(encaissement, attackerToken) {
|
||||
if (this.isEntiteNonIncarnee()) {
|
||||
return
|
||||
}
|
||||
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
|
||||
foundry.utils.mergeObject(encaissement, {
|
||||
resteEndurance: perteEndurance.newValue,
|
||||
endurance: perteEndurance.perte
|
||||
});
|
||||
endurance: perteEndurance.perte,
|
||||
blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
|
||||
})
|
||||
}
|
||||
|
||||
isEntiteAccordee(attacker) {
|
||||
if (this.isEntite([ENTITE_INCARNE])) {
|
||||
if (this.isEntiteIncarnee()) {
|
||||
let resonnance = this.system.sante.resonnance
|
||||
return (resonnance.actors.find(it => it == attacker.id))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
listActionsPossessions() {
|
||||
if (this.isEntiteNonIncarnee()) {
|
||||
return this.itemTypes[ITEM_TYPES.competencecreature]
|
||||
.filter(it => it.system.ispossession)
|
||||
.map(it => it.attaqueCreature())
|
||||
.filter(it => it != undefined)
|
||||
}
|
||||
return super.listActionsPossessions()
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async setEntiteReveAccordee(actor) {
|
||||
if (this.isEntite([ENTITE_INCARNE])) {
|
||||
if (this.isEntiteIncarnee()) {
|
||||
if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
|
||||
// déjà accordé
|
||||
return
|
||||
|
||||
@@ -29,7 +29,7 @@ export class ExperienceLog {
|
||||
};
|
||||
console.log('ExperienceLog.add', newXpLog)
|
||||
const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]);
|
||||
await actor.update({ [`system.experiencelog`]: newExperienceLog });
|
||||
await actor.update({ [`system.experiencelog`]: newExperienceLog }, { noHook: true });
|
||||
}
|
||||
|
||||
static labelTopic(topic) {
|
||||
|
||||
@@ -0,0 +1,288 @@
|
||||
import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js"
|
||||
import { Grammar } from "../../grammar.js"
|
||||
import { RdDItemArme } from "../../item/arme.js"
|
||||
import { CATEGORIES_COMPETENCE_COMBAT } from "../../item/base-items.js"
|
||||
import { Misc } from "../../misc.js"
|
||||
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
|
||||
import { PDFDocument } from "./pdf-lib/pdf-lib.esm.js"
|
||||
|
||||
|
||||
|
||||
const copyProperty = (actor, path) => foundry.utils.getProperty(actor, path)
|
||||
|
||||
// const findItem = (actor, itemType, itemName) => actor.itemTypes[itemType].find(it => Grammar.equalsInsensitive(formCompName(it.name), formCompName(itemName)))
|
||||
// const findItemPos = (actor, itemType, pos) => actor.itemTypes[itemType].length <= pos ? actor.itemTypes[itemType][pos] : length
|
||||
// const findProperty = (it, path) => it ? foundry.utils.getProperty(it, path) : undefined
|
||||
|
||||
// const findItemProperty = (actor, itemType, itemName, path) => findProperty(findItem(actor, itemType, itemName), path)
|
||||
// const findItemPosProperty = (actor, itemType, pos, path) => findProperty(findItemPos(actor, itemType, pos), path)
|
||||
|
||||
// const findArmeProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.arme, pos), path)
|
||||
// const findSortProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.sort, pos), path)
|
||||
|
||||
// const itemFormPath = (type, pos, property) => `${type}s.${pos}.${property}`
|
||||
|
||||
|
||||
const ACTOR_TO_FORM_MAPPING = [
|
||||
{ path: 'name' },
|
||||
{ path: 'system.carac.taille.value' },
|
||||
{ path: 'system.carac.apparence.value' },
|
||||
{ path: 'system.carac.apparence.xp' },
|
||||
{ path: 'system.carac.constitution.value' },
|
||||
{ path: 'system.carac.constitution.xp' },
|
||||
{ path: 'system.carac.force.value' },
|
||||
{ path: 'system.carac.force.value' },
|
||||
{ path: 'system.carac.force.xp' },
|
||||
{ path: 'system.carac.agilite.value' },
|
||||
{ path: 'system.carac.agilite.xp' },
|
||||
{ path: 'system.carac.dexterite.value' },
|
||||
{ path: 'system.carac.dexterite.xp' },
|
||||
{ path: 'system.carac.vue.value' },
|
||||
{ path: 'system.carac.vue.xp' },
|
||||
{ path: 'system.carac.ouie.value' },
|
||||
{ path: 'system.carac.ouie.xp' },
|
||||
{ path: 'system.carac.odoratgout.value' },
|
||||
{ path: 'system.carac.odoratgout.xp' },
|
||||
{ path: 'system.carac.volonte.value' },
|
||||
{ path: 'system.carac.volonte.xp' },
|
||||
{ path: 'system.carac.empathie.value' },
|
||||
{ path: 'system.carac.empathie.xp' },
|
||||
{ path: 'system.carac.intellect.value' },
|
||||
{ path: 'system.carac.intellect.xp' },
|
||||
{ path: 'system.carac.reve.value' },
|
||||
{ path: 'system.carac.reve.xp' },
|
||||
{ path: 'system.carac.chance.value' },
|
||||
{ path: 'system.carac.chance.xp' },
|
||||
|
||||
{ path: 'system.age' },
|
||||
{ path: 'system.sexe' },
|
||||
{ path: 'system.taille' },
|
||||
{ path: 'system.poids' },
|
||||
{ path: 'system.cheveux' },
|
||||
{ path: 'system.yeux' },
|
||||
{ path: 'system.beaute' },
|
||||
{ path: 'system.main' },
|
||||
{ path: 'system.heure' },
|
||||
{ path: 'computed.hn.heure', getter: actor => (RdDTimestamp.definition(actor.system.heure)?.heure ?? 0) + 1 },
|
||||
{ path: 'computed.hn.label', getter: actor => RdDTimestamp.definition(actor.system.heure)?.avecArticle },
|
||||
|
||||
{ path: 'system.carac.melee.value' },
|
||||
{ path: 'system.carac.tir.value' },
|
||||
{ path: 'system.carac.lancer.value' },
|
||||
{ path: 'system.carac.derobee.value' },
|
||||
{ path: 'system.sante.vie.value' },
|
||||
{ path: 'system.sante.endurance.value' },
|
||||
|
||||
{ path: 'system.attributs.sust.value' },
|
||||
{ path: 'system.attributs.sconst.value' },
|
||||
{ path: 'system.attributs.encombrement.value' },
|
||||
{ path: 'system.attributs.plusdom.value', getter: actor => Misc.toSignedString(actor.system.attributs.plusdom.value) },
|
||||
|
||||
// , getter: actor => actor.get
|
||||
]
|
||||
|
||||
export default class ExportPdf {
|
||||
|
||||
static init() {
|
||||
Hooks.on("getActorContextOptions", (actorDirectory, menus) => { ExportPdf.onActorDirectoryMenu(actorDirectory, menus) })
|
||||
}
|
||||
|
||||
static onActorDirectoryMenu(actorDirectory, menus) {
|
||||
menus.push({
|
||||
name: 'Export PDF',
|
||||
icon: '<i class="fa-regular fa-file-pdf"></i>',
|
||||
condition: target => actorDirectory.id == 'actors' && ExportPdf.$isActorPersonnage(this.$getActor(target)),
|
||||
callback: async target => await ExportPdf.exportActor(target)
|
||||
})
|
||||
}
|
||||
|
||||
static $getActor(target) {
|
||||
const entryId = $(target).closest(".directory-item")?.data("entryId")
|
||||
return game.actors.get(entryId)
|
||||
}
|
||||
|
||||
static $isActorPersonnage(actor) {
|
||||
return actor?.type == ACTOR_TYPES.personnage
|
||||
}
|
||||
|
||||
static async exportActor(target) {
|
||||
const actor = ExportPdf.$getActor(target)
|
||||
if (!ExportPdf.$isActorPersonnage(actor)) {
|
||||
ui.notifications.error("Pas de personnage sélectionné")
|
||||
return
|
||||
}
|
||||
const templatePdf = '/systems/foundryvtt-reve-de-dragon/assets/feuille-personnage.pdf';
|
||||
|
||||
const pdfBytes = await fetch(templatePdf).then(res => res.arrayBuffer())
|
||||
const pdfDoc = await PDFDocument.load(pdfBytes)
|
||||
|
||||
const exporter = new ExportPdf(actor, pdfDoc)
|
||||
exporter.generateFeuillePersonnage()
|
||||
}
|
||||
|
||||
constructor(actor, pdfDoc) {
|
||||
this.pdfDoc = pdfDoc
|
||||
this.form = this.pdfDoc.getForm()
|
||||
this.actor = actor
|
||||
this.allComps = this.actor.itemTypes[ITEM_TYPES.competence]
|
||||
this.comps = this.allComps
|
||||
.filter(it => !it.isNiveauBase())
|
||||
.sort(Misc.ascending(it => it.name))
|
||||
|
||||
this.compsNonArmes = this.comps.filter(it => !ExportPdf.isCompCombat(it))
|
||||
this.compsArmes = this.comps.filter(it => ExportPdf.isCompCombat(it))
|
||||
this.addedComps = new Set([])
|
||||
}
|
||||
|
||||
static isCompCombat(comp) {
|
||||
return CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie) && !Grammar.includesLowerCaseNoAccent(comp.name, "corps à corps") && !Grammar.includesLowerCaseNoAccent(comp.name, "esquive")
|
||||
}
|
||||
|
||||
async generateFeuillePersonnage() {
|
||||
|
||||
this.$exportActorFields()
|
||||
this.$exportCompetences()
|
||||
this.$exportArchetype()
|
||||
this.$exportArmes()
|
||||
this.$exportSorts()
|
||||
|
||||
const pdfBytes = await this.pdfDoc.save();
|
||||
const filename = `rdd-${this.actor.name.slugify()}.pdf`;
|
||||
foundry.utils.saveDataToFile(pdfBytes, "application/pdf", filename);
|
||||
}
|
||||
|
||||
$exportActorFields() {
|
||||
ACTOR_TO_FORM_MAPPING.forEach(async (mapping) => {
|
||||
const path = mapping.path
|
||||
const value = mapping.getter ? mapping.getter(this.actor) : copyProperty(this.actor, path)
|
||||
this.$setFormValue(path, value)
|
||||
})
|
||||
}
|
||||
|
||||
$exportCompetences() {
|
||||
this.compsNonArmes
|
||||
.filter(it => !this.addedComps.has(it.id))
|
||||
.forEach(comp => {
|
||||
const formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
|
||||
this.$setFormCompetence(formCompName, comp)
|
||||
})
|
||||
const musique = this.compsNonArmes.filter(it => Grammar.includesLowerCaseNoAccent(it.name, 'musique'))
|
||||
.sort(Misc.descending(it => it.system.niveau))
|
||||
.filter(it => !this.addedComps.has(it.id))
|
||||
.find(it => true)
|
||||
if (musique) {
|
||||
this.$setFormCompetence('musique', musique)
|
||||
}
|
||||
}
|
||||
|
||||
$exportArchetype() {
|
||||
this.allComps.sort(Misc.ascending(it => it.system.niveau_archetype))
|
||||
.forEach(comp => {
|
||||
let formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
|
||||
if (formCompName.includes('musique')) {
|
||||
formCompName = 'musique'
|
||||
}
|
||||
this.$setFormValue(`competences.${formCompName}.niveau_archetype`, comp.system.niveau_archetype)
|
||||
})
|
||||
}
|
||||
|
||||
$setFormCompetenceArchetype(formCompName, comp, baseFormName = 'competences') {
|
||||
}
|
||||
|
||||
$exportArmes() {
|
||||
const uniques = new Set([])
|
||||
const armes = this.actor.itemTypes[ITEM_TYPES.arme].map(arme => arme.getTypeAttaques()
|
||||
.map(main => {
|
||||
const compName = arme.getCompetenceAction(main)
|
||||
const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
|
||||
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
||||
const comp = this.compsArmes.find(it => Grammar.equalsInsensitive(it.name, compName)) ?? this.actor.findItemLike(compName, ITEM_TYPES.competence)
|
||||
const unique = [comp.id, arme.name, dommages, forceRequise].join('|');
|
||||
if (uniques.has(unique)) {
|
||||
return undefined
|
||||
}
|
||||
uniques.add(unique)
|
||||
return { arme: arme, comp: comp, main: main }
|
||||
}))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.filter(it => it != undefined && !it.comp.isNiveauBase())
|
||||
.sort(Misc.descending(it => it.comp.niveau))
|
||||
|
||||
for (let pos = 0; pos < armes.length; pos++) {
|
||||
const it = armes[pos]
|
||||
this.$setFormArmeCompetence(pos, it.comp, it.arme, it.main, it.main)
|
||||
}
|
||||
|
||||
// TODO: list comps without weapons
|
||||
// TODO: list other comps not in the standard list -- use an instance of ExportPdf to hold state/built list
|
||||
const otherComps = this.comps.filter(it => !this.addedComps.has(it.id))
|
||||
for (let pos = 0; pos < otherComps.length; pos++) {
|
||||
const comp = otherComps[pos]
|
||||
this.$setFormCompetence(pos, comp, 'competences')
|
||||
this.$setFormValue(`competences.${pos}.name`, comp.name)
|
||||
}
|
||||
}
|
||||
|
||||
$setFormCompetence(formCompName, comp, baseFormName = 'competences') {
|
||||
|
||||
if (this.form.getFieldMaybe(`${baseFormName}.${formCompName}.niveau`)) {
|
||||
this.addedComps.add(comp.id)
|
||||
}
|
||||
if (comp.system.niveau != comp.system.base) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.niveau`, comp.system.niveau)
|
||||
}
|
||||
if (comp.system.xp > 0) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.xp`, comp.system.xp)
|
||||
}
|
||||
if (comp.system.xp_sort > 0) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.xp_sort`, comp.system.xp_sort)
|
||||
}
|
||||
if (CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie)) {
|
||||
this.$setFormValue(`${baseFormName}.${formCompName}.init`, comp.getBaseInit())
|
||||
}
|
||||
}
|
||||
|
||||
$setFormArmeCompetence(pos, comp, arme, main) {
|
||||
this.$setFormCompetence(pos, comp, 'armes')
|
||||
this.$setFormValue(`armes.${pos}.name`, arme.name)
|
||||
this.$setFormValue(`armes.${pos}.main`, main)
|
||||
this.$setFormValue(`armes.${pos}.plusdom`, RdDItemArme.valeurMain(arme.system.dommages, main))
|
||||
}
|
||||
|
||||
$exportSorts() {
|
||||
const sorts = this.actor.itemTypes[ITEM_TYPES.sort].sort(Misc.ascending(s => ExportPdf.$orderDraconic(s) + s.name))
|
||||
|
||||
for (let pos = 0; pos < sorts.length; pos++) {
|
||||
const sort = sorts[pos]
|
||||
this.$setFormSort(pos, sort)
|
||||
}
|
||||
}
|
||||
|
||||
$setFormSort(pos, sort) {
|
||||
this.$setFormValue(`sorts.${pos}.name`, sort.name)
|
||||
this.$setFormValue(`sorts.${pos}.voie`, sort.system.draconic)
|
||||
this.$setFormValue(`sorts.${pos}.tmr`, sort.system.caseTMRSpeciale ?? sort.system.caseTMR)
|
||||
this.$setFormValue(`sorts.${pos}.diff`, sort.system.difficulte)
|
||||
this.$setFormValue(`sorts.${pos}.reve`, sort.system.ptreve)
|
||||
this.$setFormValue(`sorts.${pos}.bonuscase`, sort.system.bonuscase)
|
||||
}
|
||||
|
||||
static $orderDraconic(s) {
|
||||
switch (s.system.draconic.substring(0, 1)) {
|
||||
case 'O': return 1
|
||||
case 'H': return 2
|
||||
case 'N': return 3
|
||||
case 'T': return 4
|
||||
}
|
||||
return 5
|
||||
}
|
||||
|
||||
$setFormValue(path, value) {
|
||||
const hasField = this.form.getFieldMaybe(path)
|
||||
if (hasField && value != undefined) {
|
||||
const field = this.form.getTextField(path)
|
||||
field.setText(value.toString())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js"
|
||||
import { EMPOIGNADE, RdDItemArme } from "../../item/arme.js"
|
||||
import { RdDItemCompetence } from "../../item-competence.js"
|
||||
import { RdDItemSort } from "../../item-sort.js"
|
||||
import { ITEM_TYPES } from "../../constants.js"
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "../../constants.js"
|
||||
import { Misc } from "../../misc.js"
|
||||
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
|
||||
import { RdDBonus } from "../../rdd-bonus.js"
|
||||
@@ -160,7 +160,7 @@ export class Mapping {
|
||||
return undefined
|
||||
}
|
||||
const categorie = Mapping.complementCategorie(arme, maniement)
|
||||
const dommages = Mapping.dommagesArme(actor, arme, maniement)
|
||||
const dommages = Mapping.dommages(actor, arme, maniement)
|
||||
return {
|
||||
name: arme.name + categorie,
|
||||
niveau: Misc.toSignedString(competence.system.niveau),
|
||||
@@ -170,12 +170,13 @@ export class Mapping {
|
||||
arme: arme
|
||||
}
|
||||
}
|
||||
static dommagesArme(actor, arme, maniement) {
|
||||
|
||||
static dommages(actor, arme, maniement) {
|
||||
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
|
||||
const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
|
||||
switch (arme.system.mortalite) {
|
||||
case 'non-mortel': return `(${dommages})`
|
||||
case EMPOIGNADE: return '-'
|
||||
case RDD_CONFIG.encaissement.nonmortel: return `(${dommages})`
|
||||
case RDD_CONFIG.encaissement.empoignade: return '-'
|
||||
}
|
||||
return dommages
|
||||
}
|
||||
|
||||
@@ -20,14 +20,15 @@ const PATHS = [
|
||||
const RANDOM_VALUES = {
|
||||
'system.sexe': { 'masculin': 1, 'féminin': 1 },
|
||||
'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 },
|
||||
'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains clair': 5, 'blonds': 4, 'blonds très clair': 1, 'roux carotte': 1, 'roux cuivré': 3 },
|
||||
'system.yeux': { 'noirs': 2, 'noisettes': 3, 'bruns vert': 4, 'verts': 3, 'bleus clair': 3, 'bleus gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
|
||||
'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains': 3, 'châtain clair': 5, 'blonds': 4, 'blond platine': 1, 'roux carotte': 1, 'roux cuivré': 3, 'chauve': 1 },
|
||||
'system.yeux': { 'noirs': 2, 'noisette': 3, 'brun-vert': 4, 'verts': 3, 'bleu clair': 3, 'bleu gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
|
||||
}
|
||||
|
||||
export class AppPersonnageAleatoire extends FormApplication {
|
||||
static preloadHandlebars() {
|
||||
foundry.applications.handlebars.loadTemplates([
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/random/sexe-aleatoire.hbs',
|
||||
])
|
||||
}
|
||||
|
||||
@@ -49,14 +50,14 @@ export class AppPersonnageAleatoire extends FormApplication {
|
||||
this.current = foundry.utils.duplicate(actor)
|
||||
this.checked = {
|
||||
'name': false,
|
||||
'system.sexe': true,
|
||||
'system.age': true,
|
||||
'system.taille': true,
|
||||
'system.poids': true,
|
||||
'system.main': true,
|
||||
'system.heure': true,
|
||||
'system.cheveux': true,
|
||||
'system.yeux': true
|
||||
'system.sexe': (this.actor.system.sexe ?? '') == '',
|
||||
'system.age': this.actor.system.age == 0,
|
||||
'system.taille': (this.actor.system.taille ?? '') == '',
|
||||
'system.poids': (this.actor.system.poids ?? '') == '',
|
||||
'system.main': (this.actor.system.main ?? '') == '',
|
||||
'system.heure': (this.actor.system.heure ?? '') == '',
|
||||
'system.cheveux': (this.actor.system.cheveux ?? '') == '',
|
||||
'system.yeux': (this.actor.system.yeux ?? '') == '',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +77,8 @@ export class AppPersonnageAleatoire extends FormApplication {
|
||||
this.html.find("button.button-apply").click(async event => await this.onApply())
|
||||
this.html.find("input.current-value").change(async event => await this.onChange(event))
|
||||
this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event))
|
||||
this.html.find('a[data-action="sexe-masculin"]').click(async event => await this.onSexe('masculin'))
|
||||
this.html.find('a[data-action="sexe-feminin"]').click(async event => await this.onSexe('féminin'))
|
||||
this.html.find("a.random").click(async event => await this.onRandom(event))
|
||||
this.html.find("a.reset").click(async event => await this.onReset(event))
|
||||
this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected())
|
||||
@@ -96,6 +99,10 @@ export class AppPersonnageAleatoire extends FormApplication {
|
||||
const fields = this.html.find(selector).parents("div.random-field:first")
|
||||
return fields[0].attributes['data-path'].value
|
||||
}
|
||||
async onSexe(sexe) {
|
||||
this.current['system.sexe'] = sexe
|
||||
this.render()
|
||||
}
|
||||
|
||||
async onChange(event) {
|
||||
const path = this.getPath(event.currentTarget)
|
||||
@@ -180,8 +187,9 @@ export class AppPersonnageAleatoire extends FormApplication {
|
||||
const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2)
|
||||
const total = await RdDDice.rollTotal(`2d${variation} + ${base}`)
|
||||
const cm = total % 100
|
||||
const dm = cm < 10 ? '0' : ''
|
||||
const m = (total - cm) / 100
|
||||
return `${m}m${cm}`
|
||||
return `${m}m${dm}${cm}`
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -76,6 +76,15 @@ export class ChatUtility {
|
||||
ChatUtility.removeMessages({ part: part });
|
||||
}
|
||||
|
||||
static remover(chatMessage) {
|
||||
const messageId = chatMessage.id;
|
||||
if (messageId) {
|
||||
return (..._) => ChatUtility.removeMessages({ messageId: messageId });
|
||||
|
||||
}
|
||||
return (..._) => { }
|
||||
}
|
||||
|
||||
static removeChatMessageId(messageId) {
|
||||
if (messageId) {
|
||||
ChatUtility.removeMessages({ messageId: messageId });
|
||||
@@ -106,6 +115,25 @@ export class ChatUtility {
|
||||
return await ChatMessage.create(messageData)
|
||||
}
|
||||
|
||||
static tellToUser(message) {
|
||||
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
|
||||
}
|
||||
|
||||
static tellToGM(message) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: message,
|
||||
whisper: ChatUtility.getGMs()
|
||||
});
|
||||
}
|
||||
|
||||
static tellToUserAndGM(message) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: message,
|
||||
whisper: ChatUtility.getUserAndGMs()
|
||||
})
|
||||
}
|
||||
static getOwners(document) {
|
||||
return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { RdDBaseActor } from "../actor/base-actor.js";
|
||||
import { ChatUtility } from "../chat-utility.js";
|
||||
import { renderTemplate } from "../constants.js";
|
||||
import { MORAL } from "../moral/apprecier.mjs";
|
||||
|
||||
const INFO_COEUR = 'info-coeur';
|
||||
|
||||
@@ -122,7 +123,7 @@ export class RdDCoeur {
|
||||
const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre)
|
||||
for (let amoureux of [infoCoeur.source, infoCoeur.target]) {
|
||||
const actorAmoureux = game.actors.get(amoureux.actor.id);
|
||||
amoureux.situation = diff <= amoureux.coeur ? 'heureux' : 'neutre'
|
||||
amoureux.situation = diff <= amoureux.coeur ? MORAL.HEUREUX : MORAL.NEUTRE
|
||||
amoureux.gainMoral = await actorAmoureux.jetDeMoral(amoureux.situation)
|
||||
}
|
||||
const chatHtml = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/coeur/chat-accepter-tendre-moment.hbs`, infoCoeur)
|
||||
|
||||
@@ -13,53 +13,69 @@ export const renderTemplate = foundry.applications.handlebars.renderTemplate
|
||||
|
||||
export const RDD_CONFIG = {
|
||||
niveauEthylisme: [
|
||||
{ value: "1", label: "Aucun" },
|
||||
{ value: "0", label: "Eméché (0)" },
|
||||
{ value: "-1", label: "Gris (-1)" },
|
||||
{ value: "-2", label: "Pinté (-2)" },
|
||||
{ value: "-3", label: "Pas Frais (-3)" },
|
||||
{ value: "-4", label: "Ivre (-4)" },
|
||||
{ value: "-5", label: "Bu (-5)" },
|
||||
{ value: "-6", label: "Complètement fait (-6)" },
|
||||
{ value: "-7", label: "Ivre mort (-7)" }
|
||||
{ value: '1', label: 'Aucun' },
|
||||
{ value: '0', label: 'Eméché (0)' },
|
||||
{ value: '-1', label: 'Gris (-1)' },
|
||||
{ value: '-2', label: 'Pinté (-2)' },
|
||||
{ value: '-3', label: 'Pas Frais (-3)' },
|
||||
{ value: '-4', label: 'Ivre (-4)' },
|
||||
{ value: '-5', label: 'Bu (-5)' },
|
||||
{ value: '-6', label: 'Complètement fait (-6)' },
|
||||
{ value: '-7', label: 'Ivre mort (-7)' }
|
||||
],
|
||||
categorieEntite: {
|
||||
"cauchemar": "Cauchemar",
|
||||
"reve": "Rêve"
|
||||
'cauchemar': 'Cauchemar',
|
||||
'reve': 'Rêve'
|
||||
},
|
||||
typeEntite: {
|
||||
"incarne": "Incarnée",
|
||||
"nonincarne": "Non Incarnée",
|
||||
"blurette": "Blurette"
|
||||
[ENTITE_INCARNE]: 'Incarnée',
|
||||
[ENTITE_NONINCARNE]: 'Non Incarnée',
|
||||
[ENTITE_BLURETTE]: 'Blurette'
|
||||
},
|
||||
heuresRdD: [
|
||||
{ value: "vaisseau", label: "Vaisseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp" },
|
||||
{ value: "sirene", label: "Sirène", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp" },
|
||||
{ value: "faucon", label: "Faucon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp" },
|
||||
{ value: "couronne", label: "Couronne", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp" },
|
||||
{ value: "dragon", label: "Dragon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp" },
|
||||
{ value: "epees", label: "Epées", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp" },
|
||||
{ value: "lyre", label: "Lyre", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp" },
|
||||
{ value: "serpent", label: "Serpent", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp" },
|
||||
{ value: "poissonacrobate", label: "Poisson Acrobate", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp" },
|
||||
{ value: "araignee", label: "Araignée", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp" },
|
||||
{ value: "roseau", label: "Roseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp" },
|
||||
{ value: "chateaudormant", label: "Chateau Dormant", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp" }
|
||||
{ value: 'vaisseau', label: 'Vaisseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp' },
|
||||
{ value: 'sirene', label: 'Sirène', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp' },
|
||||
{ value: 'faucon', label: 'Faucon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp' },
|
||||
{ value: 'couronne', label: 'Couronne', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp' },
|
||||
{ value: 'dragon', label: 'Dragon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp' },
|
||||
{ value: 'epees', label: 'Epées', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' },
|
||||
{ value: 'lyre', label: 'Lyre', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp' },
|
||||
{ value: 'serpent', label: 'Serpent', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp' },
|
||||
{ value: 'poissonacrobate', label: 'Poisson Acrobate', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp' },
|
||||
{ value: 'araignee', label: 'Araignée', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp' },
|
||||
{ value: 'roseau', label: 'Roseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp' },
|
||||
{ value: 'chateaudormant', label: 'Chateau Dormant', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp' }
|
||||
],
|
||||
raretes: [
|
||||
{ value: "Commune", label: "Commune" },
|
||||
{ value: "Frequente", label: "Fréquente" },
|
||||
{ value: "Rare", label: "Rare" },
|
||||
{ value: "Rarissime", label: "Rarissime" }
|
||||
{ value: 'Commune', label: 'Commune' },
|
||||
{ value: 'Frequente', label: 'Fréquente' },
|
||||
{ value: 'Rare', label: 'Rare' },
|
||||
{ value: 'Rarissime', label: 'Rarissime' }
|
||||
],
|
||||
particuliere: {
|
||||
force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg'},
|
||||
finesse: { key: 'finesse', descr: 'en finesse', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-finesse.svg'},
|
||||
rapidite: { key: 'finesse', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.svg'},
|
||||
force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg' },
|
||||
finesse: { key: 'finesse', descr: 'en finesse', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-finesse.svg' },
|
||||
rapidite: { key: 'rapidite', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.svg' },
|
||||
},
|
||||
icons: {
|
||||
armesDisparates: 'systems/foundryvtt-reve-de-dragon/assets/actions/armes-disparates.svg',
|
||||
demiReve: 'systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg',
|
||||
empoignade: 'systems/foundryvtt-reve-de-dragon/assets/actions/empoignade.svg',
|
||||
possession: 'systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg',
|
||||
forceWeak: 'systems/foundryvtt-reve-de-dragon/assets/actions/weak.svg',
|
||||
surenc: 'systems/foundryvtt-reve-de-dragon/assets/actions/surenc.svg',
|
||||
magique: 'systems/foundryvtt-reve-de-dragon/assets/actions/magique.svg',
|
||||
armebrisee: 'systems/foundryvtt-reve-de-dragon/assets/actions/arme-brisee.svg',
|
||||
malade: 'systems/foundryvtt-reve-de-dragon/assets/actions/malade.svg',
|
||||
},
|
||||
encaissement: {
|
||||
mortel: 'mortel',
|
||||
nonmortel: 'non-mortel',
|
||||
entiteincarnee: 'entiteincarnee',
|
||||
empoignade: 'empoignade'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const ACTOR_TYPES = {
|
||||
personnage: 'personnage',
|
||||
creature: 'creature',
|
||||
|
||||
@@ -3,6 +3,7 @@ import { renderTemplate } from "./constants.js"
|
||||
export class DialogSelect extends Dialog {
|
||||
static extractIdNameImg(it) { return { id: it.id, name: it.name, img: it.img } }
|
||||
|
||||
|
||||
static async select(selectionData, onSelectChoice) {
|
||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select.hbs", selectionData)
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ export class RdDInitiative {
|
||||
return "1d6" + (base >= 0 ? "+" : "") + base
|
||||
}
|
||||
|
||||
static ajustementInitiative(caracValue, niveau, bonus) {
|
||||
static ajustementInitiative(caracValue, niveau, bonus = 0) {
|
||||
return niveau + Math.floor(caracValue / 2) + bonus
|
||||
}
|
||||
|
||||
static formule(phase, carac, niveau, bonusMalus) {
|
||||
static formule(phase, carac, niveau, bonusMalus = 0) {
|
||||
const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus)
|
||||
return { phase, ajustement }
|
||||
}
|
||||
@@ -58,6 +58,7 @@ export class RdDInitiative {
|
||||
return {
|
||||
roll: roll,
|
||||
value: value,
|
||||
rang: formule.phase.rang,
|
||||
init: formule.phase.rang + value / 100,
|
||||
label: formule.phase.label
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDInitiative } from "./initiative.mjs";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
|
||||
import { CATEGORIES_COMPETENCE_COMBAT, CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
|
||||
@@ -46,6 +47,30 @@ export class RdDItemCompetence extends RdDItem {
|
||||
|
||||
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
|
||||
|
||||
isNiveauBase() {
|
||||
return this.system.niveau == this.system.base && this.system.xp == 0
|
||||
}
|
||||
|
||||
getBaseInit() {
|
||||
const carac = this.getInitCarac()
|
||||
if (carac == undefined) {
|
||||
return undefined
|
||||
}
|
||||
return RdDInitiative.ajustementInitiative(carac.value, this.system.niveau)
|
||||
}
|
||||
|
||||
getInitCarac() {
|
||||
if (!this.actor) {
|
||||
return undefined
|
||||
}
|
||||
switch (this.system.categorie) {
|
||||
case CATEGORIES_COMPETENCES.melee.key: return this.actor.system.carac.melee
|
||||
case CATEGORIES_COMPETENCES.tir.key: return this.actor.system.carac.tir
|
||||
case CATEGORIES_COMPETENCES.lancer.key: return this.actor.system.carac.lancer
|
||||
case CATEGORIES_COMPETENCES.draconic.key: return this.actor.system.carac.reve
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getLabelCategorie(category) {
|
||||
return CATEGORIES_COMPETENCES[category].label;
|
||||
|
||||
@@ -32,6 +32,7 @@ export class RdDItemCompetenceCreature extends RdDItem {
|
||||
initiative: initative,
|
||||
mortalite: this.system.mortalite,
|
||||
dommages: this.system.dommages,
|
||||
forceRequise: 0,
|
||||
equipe: true,
|
||||
resistance: 100,
|
||||
penetration: 0,
|
||||
@@ -43,7 +44,8 @@ export class RdDItemCompetenceCreature extends RdDItem {
|
||||
carac: { key: this.name, value: this.system.carac_value },
|
||||
equipe: true,
|
||||
mortalite: this.system.mortalite,
|
||||
dmg: this.system.dommages,
|
||||
dommages: this.system.dommages,
|
||||
//dmg: this.system.dommages,
|
||||
initiative: initative
|
||||
};
|
||||
return attaque
|
||||
|
||||
@@ -14,6 +14,8 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
|
||||
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
|
||||
import { ItemAction } from "./item/item-actions.js";
|
||||
import { SANS_COMPETENCE } from "./item/base-items.js";
|
||||
import { Apprecier } from "./moral/apprecier.mjs";
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet for RdD specific items
|
||||
@@ -89,6 +91,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const competences = (await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage))
|
||||
let formData = {
|
||||
title: this.item.name,
|
||||
id: this.item.id,
|
||||
@@ -101,8 +104,9 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
|
||||
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
|
||||
isComestible: this.item.getUtilisationCuisine(),
|
||||
options: RdDSheetUtility.mergeDocumentRights({}, this.item, this.isEditable),
|
||||
competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage),
|
||||
competences: [SANS_COMPETENCE, ...competences],
|
||||
categories: RdDItem.getCategories(this.item.type),
|
||||
isAppreciable: Apprecier.isAppreciable(this.item)
|
||||
}
|
||||
|
||||
if (this.item.type == ITEM_TYPES.competencecreature) {
|
||||
@@ -260,7 +264,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
async _updateObject(event, formData) {
|
||||
switch (this.item.type) {
|
||||
case ITEM_TYPES.sort:
|
||||
formData['system.bonuscase'] = RdDItemSort.bonuscasesToString(RdDItemSheetV1._listCaseTmr(
|
||||
@@ -273,8 +277,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
|
||||
formData['system.niveau'] = formData['system.niveau'] ?? formData['system.base']
|
||||
break
|
||||
}
|
||||
|
||||
return this.item.update(formData)
|
||||
return await super._updateObject(event, formData)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@@ -62,7 +62,7 @@ export class RdDItemSort extends Item {
|
||||
|
||||
|
||||
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
|
||||
static coutReve(sort) { return RdDItemSort.toVar((sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) }
|
||||
static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve || sort.system.ptreve.match(/(\d)+\+?/)) ? 'r' : 'r ') + sort.system.ptreve) }
|
||||
static getDraconicsSort(competencesDraconic, sort) {
|
||||
// se baser sur la voie du sort?
|
||||
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
|
||||
@@ -148,10 +148,17 @@ export class RdDItemSort extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static incrementBonusCase(actor, sort, coord) {
|
||||
let bonuscase = RdDItemSort.calculBonuscase(sort, coord)
|
||||
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
|
||||
}
|
||||
|
||||
|
||||
static calculBonuscase(sort, coord) {
|
||||
if (TMRUtility.isFleuve(coord)) {
|
||||
coord = FLEUVE_COORD;
|
||||
coord = FLEUVE_COORD
|
||||
}
|
||||
let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase);
|
||||
let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase)
|
||||
const existing = list.find(it => it.case == coord)
|
||||
const bonus = Number(existing?.bonus ?? 0) + 1
|
||||
if (existing) {
|
||||
@@ -160,11 +167,9 @@ export class RdDItemSort extends Item {
|
||||
else {
|
||||
list.push({ case: coord, bonus: 1 })
|
||||
}
|
||||
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': RdDItemSort.bonuscasesToString(list) }]);
|
||||
return RdDItemSort.bonuscasesToString(list)
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaseBonus(sort, coord) {
|
||||
const search = TMRUtility.isFleuve(coord)
|
||||
@@ -189,4 +194,22 @@ export class RdDItemSort extends Item {
|
||||
.map(it => it.split(':'))
|
||||
.map(it => { return { case: it[0], bonus: it[1] } });
|
||||
}
|
||||
|
||||
static prepareSortEnReserve(sort, draconic, ptreve, coord) {
|
||||
return {
|
||||
type: ITEM_TYPES.sortreserve,
|
||||
name: sort.name,
|
||||
img: sort.img,
|
||||
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
|
||||
};
|
||||
}
|
||||
|
||||
static prepareSortAddLancement(sort, reveSort) {
|
||||
const precedents = sort.system.lancements ?? []
|
||||
const lancements = [...precedents, {
|
||||
timestamp: game.system.rdd.calendrier.getTimestamp(),
|
||||
reve: reveSort
|
||||
}]
|
||||
return lancements
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ITEM_TYPES, renderTemplate } from "./constants.js";
|
||||
import { ITEM_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
|
||||
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES, CATEGORIES_COMPETENCES_CREATURES } from "./item/base-items.js";
|
||||
import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js";
|
||||
|
||||
@@ -28,7 +28,7 @@ const typesInventaireMateriel = [
|
||||
]
|
||||
const typesInventaire = {
|
||||
materiel: typesInventaireMateriel,
|
||||
all: ['service'].concat(typesInventaireMateriel),
|
||||
all: [ITEM_TYPES.service].concat(typesInventaireMateriel),
|
||||
}
|
||||
|
||||
const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
|
||||
@@ -36,6 +36,10 @@ const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.s
|
||||
const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
|
||||
const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
|
||||
const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
|
||||
const typesAppreciable = [
|
||||
ITEM_TYPES.oeuvre, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.nourritureboisson,
|
||||
ITEM_TYPES.jeu, ITEM_TYPES.service
|
||||
]
|
||||
const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
|
||||
const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
|
||||
const typesEnvironnement = typesInventaireMateriel;
|
||||
@@ -96,14 +100,14 @@ export class RdDItem extends Item {
|
||||
switch (field) {
|
||||
case 'quantite':
|
||||
if (ITEM_TYPES.conteneur == type) {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
break;
|
||||
case 'cout':
|
||||
if (ITEM_TYPES.monnaie == type) {
|
||||
return game.user.isGM;
|
||||
}
|
||||
break;
|
||||
break
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -180,10 +184,10 @@ export class RdDItem extends Item {
|
||||
|
||||
isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
|
||||
isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
|
||||
isConteneur() { return this.type == ITEM_TYPES.conteneur; }
|
||||
isMonnaie() { return this.type == ITEM_TYPES.monnaie; }
|
||||
isConteneur() { return this.type == ITEM_TYPES.conteneur }
|
||||
isMonnaie() { return this.type == ITEM_TYPES.monnaie }
|
||||
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
|
||||
isService() { return this.type == ITEM_TYPES.service; }
|
||||
isService() { return this.type == ITEM_TYPES.service }
|
||||
isAttaque() { return false }
|
||||
isParade() { return false }
|
||||
isBouclier() { return false }
|
||||
@@ -205,7 +209,7 @@ export class RdDItem extends Item {
|
||||
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
|
||||
}
|
||||
|
||||
isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" }
|
||||
isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key }
|
||||
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
||||
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
|
||||
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
||||
@@ -214,6 +218,7 @@ export class RdDItem extends Item {
|
||||
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
|
||||
|
||||
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
|
||||
isAppreciable() { return typesAppreciable.includes(this.type) }
|
||||
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
|
||||
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
|
||||
isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
||||
@@ -364,11 +369,11 @@ export class RdDItem extends Item {
|
||||
getEnc() {
|
||||
switch (this.type) {
|
||||
case ITEM_TYPES.service:
|
||||
return 0;
|
||||
return 0
|
||||
case ITEM_TYPES.herbe:
|
||||
return this.getEncHerbe();
|
||||
return this.getEncHerbe()
|
||||
}
|
||||
return Math.max(this.system.encombrement ?? 0, 0);
|
||||
return Math.max(this.system.encombrement ?? 0.0, 0.0);
|
||||
}
|
||||
|
||||
getEncContenu() {
|
||||
@@ -384,9 +389,9 @@ export class RdDItem extends Item {
|
||||
getEncHerbe() {
|
||||
switch (this.system.categorie) {
|
||||
case 'Repos': case 'Soin': case 'Alchimie':
|
||||
return encBrin;
|
||||
return encBrin
|
||||
}
|
||||
return this.system.encombrement;
|
||||
return this.system.encombrement
|
||||
|
||||
}
|
||||
|
||||
@@ -629,7 +634,7 @@ export class RdDItem extends Item {
|
||||
_armeChatData() {
|
||||
return [
|
||||
`<b>Compétence</b>: ${this.system.competence}`,
|
||||
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`,
|
||||
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == RDD_CONFIG.encaissement.nonmortel ? '(Non mortel)' : ''}`,
|
||||
`<b>Force minimum</b>: ${this.system.force}`,
|
||||
`<b>Resistance</b>: ${this.system.resistance}`,
|
||||
...this._inventaireTemplateChatData()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ITEM_TYPES } from "../constants.js";
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
|
||||
import { RdDItem } from "../item.js";
|
||||
import { BASE_CORPS_A_CORPS } from "./base-items.js";
|
||||
import { Grammar } from "../grammar.js";
|
||||
@@ -27,10 +27,11 @@ export const ATTAQUE_TYPE = {
|
||||
TIR: '(tir)',
|
||||
LANCER: '(lancer)'
|
||||
}
|
||||
export const ATTAQUE_TYPE_MELEE = [ATTAQUE_TYPE.UNE_MAIN, ATTAQUE_TYPE.DEUX_MAINS, ATTAQUE_TYPE.CORPS_A_CORPS]
|
||||
|
||||
export const CORPS_A_CORPS = 'Corps à corps'
|
||||
export const PUGILAT = 'pugilat'
|
||||
export const EMPOIGNADE = 'empoignade'
|
||||
export const EMPOIGNADE = RDD_CONFIG.encaissement.empoignade
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemArme extends RdDItem {
|
||||
@@ -44,6 +45,16 @@ export class RdDItemArme extends RdDItem {
|
||||
isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
|
||||
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
|
||||
|
||||
|
||||
getCompetenceAction(main) {
|
||||
switch (main) {
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return this.competence2Mains()
|
||||
case ATTAQUE_TYPE.LANCER: return this.system.lancer
|
||||
case ATTAQUE_TYPE.TIR: return this.system.tir
|
||||
default: return this.system.competence
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static valeurMain(valeurs, main) {
|
||||
valeurs = valeurs?.toString() ?? ""
|
||||
@@ -77,17 +88,26 @@ export class RdDItemArme extends RdDItem {
|
||||
return arme.name
|
||||
case ITEM_TYPES.arme:
|
||||
switch (maniement) {
|
||||
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence;
|
||||
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence
|
||||
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
|
||||
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
|
||||
case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
|
||||
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer;
|
||||
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer
|
||||
case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
getTypeAttaques() {
|
||||
return [
|
||||
...(this.system.unemain && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.UNE_MAIN] : [],
|
||||
...(this.system.deuxmains && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.DEUX_MAINS] : [],
|
||||
...(this.system.lancer && this.system.resistance > 0) ? [ATTAQUE_TYPE.LANCER] : [],
|
||||
...(this.system.tir) ? [ATTAQUE_TYPE.TIR] : [],
|
||||
]
|
||||
}
|
||||
|
||||
static computeNiveauArmes(armes, competences) {
|
||||
for (const arme of armes) {
|
||||
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||
@@ -254,15 +274,27 @@ export class RdDItemArme extends RdDItem {
|
||||
return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0)
|
||||
}
|
||||
|
||||
isEmpoignade() {
|
||||
return this.system.mortalite == RDD_CONFIG.encaissement.empoignade
|
||||
}
|
||||
|
||||
isPossession() {
|
||||
return this.system.mortalite == RDD_CONFIG.encaissement.possession
|
||||
}
|
||||
|
||||
isUtilisableEmpoigne() {
|
||||
return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague"
|
||||
}
|
||||
|
||||
static pugilat(actor) {
|
||||
return RdDItemArme.$corpsACorps(actor, 'Pugilat', PUGILAT)
|
||||
}
|
||||
|
||||
static empoignade(actor) {
|
||||
return RdDItemArme.$corpsACorps(actor, 'Empoignade', EMPOIGNADE)
|
||||
return RdDItemArme.$corpsACorps(actor, 'Empoignade', RDD_CONFIG.encaissement.empoignade)
|
||||
}
|
||||
|
||||
static $corpsACorps(actor, name, cac, system) {
|
||||
static $corpsACorps(actor, name, cac) {
|
||||
const competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
|
||||
const melee = actor ? actor.system.carac['melee'].value : 0
|
||||
return new RdDItemArme({
|
||||
@@ -277,10 +309,10 @@ export class RdDItemArme extends RdDItem {
|
||||
force: 0,
|
||||
dommages: "0",
|
||||
dommagesReels: 0,
|
||||
mortalite: cac == EMPOIGNADE ? EMPOIGNADE : 'non-mortel',
|
||||
mortalite: cac == RDD_CONFIG.encaissement.empoignade ? RDD_CONFIG.encaissement.empoignade : RDD_CONFIG.encaissement.nonmortel,
|
||||
competence: CORPS_A_CORPS,
|
||||
resistance: 1,
|
||||
baseInit: cac == EMPOIGNADE ? 3 : 4,
|
||||
baseInit: cac == RDD_CONFIG.encaissement.empoignade ? 3 : 4,
|
||||
cac: cac,
|
||||
deuxmains: true,
|
||||
categorie_parade: 'sans-armes'
|
||||
|
||||
@@ -1,40 +1,46 @@
|
||||
export const POSSESSION_SANS_DRACONIC = { name: 'Sans draconic', type: 'competence', system: { niveau: 0, defaut_carac: "reve-actuel", }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
|
||||
export const CATEGORIES_COMPETENCES = {
|
||||
generale: { key: 'generale', base: -4, label: "Générales" },
|
||||
particuliere: { key: 'particuliere', base: -8, label: "Particulières" },
|
||||
specialisee: { key: 'specialisee', base: -11, label: "Spécialisées" },
|
||||
connaissance: { key: 'connaissance', base: -11, label: "Connaissances" },
|
||||
draconic: { key: 'draconic', base: -11, label: "Draconic" },
|
||||
melee: { key: 'melee', base: -6, label: "Mêlée" },
|
||||
tir: { key: 'tir', base: -8, label: "Tir" },
|
||||
lancer: { key: 'lancer', base: -8, label: "Lancer" }
|
||||
}
|
||||
export const CATEGORIES_COMPETENCE_COMBAT = [CATEGORIES_COMPETENCES.melee, CATEGORIES_COMPETENCES.tir, CATEGORIES_COMPETENCES.lancer].map(it => it.key)
|
||||
|
||||
export const CATEGORIES_COMPETENCES_CREATURES = {
|
||||
generale: { key: 'generale', base: 0, label: "Générale" },
|
||||
naturelle: { key: 'naturelle', base: 0, label: "Arme naturelle" },
|
||||
melee: { key: 'melee', base: 0, label: "Mêlée" },
|
||||
parade: { key: 'parade', base: 0, label: "Parade" },
|
||||
tir: { key: 'tir', base: 0, label: "Tir" },
|
||||
lancer: { key: 'lancer', base: 0, label: "Lancer" },
|
||||
possession: { key: 'possession', base: 0, label: "Possession" },
|
||||
}
|
||||
|
||||
export const POSSESSION_SANS_DRACONIC = {
|
||||
name: 'Sans draconic',
|
||||
type: ITEM_TYPES.competence,
|
||||
img: RDD_CONFIG.icons.possession,
|
||||
system: { niveau: 0, defaut_carac: CARACS.REVE_ACTUEL, categorie: CATEGORIES_COMPETENCES.draconic.key }
|
||||
}
|
||||
|
||||
export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
|
||||
export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }
|
||||
export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' }
|
||||
|
||||
export const SANS_COMPETENCE = {
|
||||
name: "Sans compétence",
|
||||
type: 'competence',
|
||||
type: ITEM_TYPES.competence,
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp",
|
||||
system: {
|
||||
niveau: 0,
|
||||
default_diffLibre: 0,
|
||||
base: 0,
|
||||
categorie: "Aucune",
|
||||
description: "",
|
||||
descriptionmj: "",
|
||||
defaut_carac: "",
|
||||
},
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp"
|
||||
}
|
||||
|
||||
export const CATEGORIES_COMPETENCES = {
|
||||
"generale": { base: -4, label: "Générales" },
|
||||
"particuliere": { base: -8, label: "Particulières" },
|
||||
"specialisee": { base: -11, label: "Spécialisées" },
|
||||
"connaissance": { base: -11, label: "Connaissances" },
|
||||
"draconic": { base: -11, label: "Draconic" },
|
||||
"melee": { base: -6, label: "Mêlée" },
|
||||
"tir": { base: -8, label: "Tir" },
|
||||
"lancer": { base: -8, label: "Lancer" }
|
||||
}
|
||||
|
||||
export const CATEGORIES_COMPETENCES_CREATURES = {
|
||||
"generale": { base: 0, label: "Générale" },
|
||||
"naturelle": { base: 0, label: "Arme naturelle" },
|
||||
"melee": { base: 0, label: "Mêlée" },
|
||||
"parade": { base: 0, label: "Parade" },
|
||||
"tir": { base: 0, label: "Tir" },
|
||||
"lancer": { base: 0, label: "Lancer" },
|
||||
"possession": { base: 0, label: "Possession" },
|
||||
categorie: CATEGORIES_COMPETENCES.generale.key,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,21 +71,25 @@ export class RdDItemBlessure extends RdDItem {
|
||||
return 0
|
||||
}
|
||||
|
||||
static async createBlessure(actor, gravite, localisation = '', attackerToken) {
|
||||
const definition = RdDItemBlessure.getDefinition(gravite)
|
||||
const blessure = {
|
||||
static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) {
|
||||
const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken);
|
||||
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
|
||||
return blessures[0]
|
||||
}
|
||||
|
||||
static prepareBlessure(gravite, localisation, attackerToken) {
|
||||
const definition = RdDItemBlessure.getDefinition(gravite);
|
||||
return {
|
||||
name: definition.label,
|
||||
type: 'blessure',
|
||||
img: definition.icon,
|
||||
system: {
|
||||
gravite: gravite,
|
||||
difficulte: - gravite,
|
||||
difficulte: -gravite,
|
||||
localisation: localisation,
|
||||
origine: attackerToken?.name ?? ""
|
||||
}
|
||||
}
|
||||
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
|
||||
return blessures[0]
|
||||
}
|
||||
|
||||
static async createTacheSoinBlessure(actor, gravite) {
|
||||
|
||||
@@ -12,12 +12,13 @@ const _SPACEHOLDER = { placeholder: true }
|
||||
|
||||
const _VENDRE = {
|
||||
code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar',
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0,
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce,
|
||||
action: (item, actor) => item.proposerVente()
|
||||
}
|
||||
const _ACHETER = {
|
||||
code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins',
|
||||
filter: it => Misc.toInt(it.system.quantite) > 0 && it.parent?.type == ACTOR_TYPES.commerce,
|
||||
filter: it => it.parent?.type == ACTOR_TYPES.commerce,
|
||||
allowLimited: true,
|
||||
action: (item, actor) => actor.vente(item)
|
||||
}
|
||||
const _MONTRER = {
|
||||
|
||||
@@ -76,7 +76,7 @@ export class RdDItemRace extends RdDItem {
|
||||
ui.notifications.warn("La Taille est inférieur au minimum racial")
|
||||
return min
|
||||
}
|
||||
const raceMax = this.system.carac.taille.max;
|
||||
const raceMax = this.system.carac.taille.max == undefined ? 15 + this.system.carac.taille.value : this.system.carac.taille.max
|
||||
const max = raceMax < 0 ? taille + 1 : raceMax
|
||||
if (max < taille) {
|
||||
ui.notifications.warn("La Taille est supérieure au maximum racial")
|
||||
|
||||
@@ -68,7 +68,7 @@ export class RdDRencontre extends RdDItem {
|
||||
}
|
||||
|
||||
static async appliquer(codes, tmrDialog, rencData) {
|
||||
for(const effet of RdDRencontre.mapEffets(codes)){
|
||||
for(let effet of RdDRencontre.mapEffets(codes)){
|
||||
await effet.method(tmrDialog, rencData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDRaretes } from "./item/raretes.js";
|
||||
import { VOIES_DRACONIC } from "./item-sort.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
import { APPRECIATION } from "./moral/apprecier.mjs";
|
||||
|
||||
class Migration {
|
||||
get code() { return "sample"; }
|
||||
@@ -33,7 +34,6 @@ class Migration {
|
||||
await Item.updateDocuments(itemUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class _1_5_34_migrationPngWebp {
|
||||
@@ -662,6 +662,37 @@ class _13_0_7_FixNiveauOeuvres extends Migration {
|
||||
}
|
||||
}
|
||||
|
||||
class _13_0_21_AjoutAppreciation extends Migration {
|
||||
get code() { return "ajout-appreciation" }
|
||||
get version() { return "13.0.21" }
|
||||
|
||||
async migrate() {
|
||||
await this.applyItemsUpdates(items => items
|
||||
.filter(it => it.isAppreciable())
|
||||
.filter(it => this.getBaseAppreciation(it))
|
||||
.map(it => {
|
||||
return { _id: it.id, 'system.appreciation': this.getBaseAppreciation(it) }
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
getBaseAppreciation(item) {
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.nourritureboisson: return APPRECIATION.CUISINE
|
||||
case ITEM_TYPES.service: return APPRECIATION.SERVICE
|
||||
case ITEM_TYPES.musique: return APPRECIATION.MUSIQUE
|
||||
case ITEM_TYPES.chant: return APPRECIATION.CHANT
|
||||
case ITEM_TYPES.danse: return APPRECIATION.DANSE
|
||||
case ITEM_TYPES.oeuvre: {
|
||||
const appreciation = foundry.utils.duplicate(APPRECIATION.OEUVRE)
|
||||
appreciation.competence = item.system.competence
|
||||
return appreciation
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
export class Migrations {
|
||||
static getMigrations() {
|
||||
return [
|
||||
@@ -687,6 +718,7 @@ export class Migrations {
|
||||
new _12_0_38_TachesEcriture(),
|
||||
new _13_0_4_FixReveActuel(),
|
||||
new _13_0_7_FixNiveauOeuvres(),
|
||||
new _13_0_21_AjoutAppreciation(),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -707,7 +739,10 @@ export class Migrations {
|
||||
}
|
||||
if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
|
||||
// if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||
const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion));
|
||||
const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion)
|
||||
/* uncomment and set the version to migrate to to force a migration */
|
||||
// ||m.version == "13.0.21"
|
||||
)
|
||||
if (migrations.length > 0) {
|
||||
migrations.sort((a, b) => this.compareVersions(a, b));
|
||||
migrations.forEach(async (m) => {
|
||||
|
||||
@@ -229,6 +229,14 @@ export class Misc {
|
||||
return undefined
|
||||
}
|
||||
|
||||
static async doIfOwner(document, action, orElse = async it => { ui.notifications.warn(`Vous n'avez pas le droit d'agir pour ${it.name}`) }) {
|
||||
if (Misc.isOwnerPlayer(document)) {
|
||||
return await action(document)
|
||||
} else {
|
||||
return await orElse(document)
|
||||
}
|
||||
}
|
||||
|
||||
static isOwnerPlayer(document) {
|
||||
return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { SANS_COMPETENCE } from "../item/base-items.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { RdDUtility } from "../rdd-utility.js"
|
||||
import { DIFF } from "../roll/roll-constants.mjs"
|
||||
import RollDialog from "../roll/roll-dialog.mjs"
|
||||
import { PART_COMP } from "../roll/roll-part-comp.mjs"
|
||||
|
||||
export const MORAL = {
|
||||
MALHEUREUX: "malheureux",
|
||||
NEUTRE: "neutre",
|
||||
HEUREUX: "heureux",
|
||||
TRESHEUREUX: "très heureux"
|
||||
}
|
||||
export const SITUATION_MORAL = {
|
||||
[MORAL.MALHEUREUX]: "malheureuse",
|
||||
[MORAL.NEUTRE]: "neutre",
|
||||
[MORAL.HEUREUX]: "heureuse",
|
||||
[MORAL.TRESHEUREUX]: "très heureuse",
|
||||
}
|
||||
export const APPRECIATION = {
|
||||
CUISINE: {
|
||||
bonmoment: "Cuisine", carac: CARACS.ODORATGOUT, competence: "Cuisine",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
MUSIQUE: {
|
||||
bonmoment: "Musique", carac: CARACS.OUIE, competence: "Musique",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
CHANT: {
|
||||
bonmoment: "Musique", carac: CARACS.OUIE, competence: "Chant",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
DANSE: {
|
||||
bonmoment: "Spectacle", carac: CARACS.EMPATHIE, competence: "Danse",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
JEU: {
|
||||
bonmoment: "Jeu", carac: CARACS.EMPATHIE, competence: "Jeu",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
OEUVRE: {
|
||||
bonmoment: "Spectacle", carac: CARACS.EMPATHIE, competence: "",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
|
||||
},
|
||||
SERVICE: {
|
||||
bonmoment: "Confort", carac: CARACS.EMPATHIE, competence: "",
|
||||
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: false
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
export class Apprecier {
|
||||
|
||||
static isAppreciable(item) {
|
||||
switch (item.type) {
|
||||
case ITEM_TYPES.nourritureboisson:
|
||||
case ITEM_TYPES.service:
|
||||
return item.system.qualite > 0
|
||||
case ITEM_TYPES.chant:
|
||||
case ITEM_TYPES.musique:
|
||||
case ITEM_TYPES.danse:
|
||||
case ITEM_TYPES.oeuvre:
|
||||
case ITEM_TYPES.jeu:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
static qualite(qualite, roll = undefined, comp = undefined) {
|
||||
if (roll && comp) {
|
||||
return roll.rolled.isSuccess ? qualite : Math.min(qualite, comp.system.niveau)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
static getAppreciation(qualite, appreciable, roll = undefined, comp = undefined) {
|
||||
return {
|
||||
qualite: (roll?.rolled.ptQualite ?? 0) + Apprecier.qualite(qualite, roll, comp),
|
||||
appreciation: foundry.utils.duplicate(appreciable.system.appreciation),
|
||||
messages: []
|
||||
}
|
||||
}
|
||||
|
||||
static onClickApprecier(roll) {
|
||||
const appreciation = roll.result.appreciation
|
||||
if (appreciation.moral == "") {
|
||||
return
|
||||
}
|
||||
RdDUtility.doWithSelectedActor(
|
||||
actor => new Apprecier(actor, appreciation, roll.result.qualite).apprecier(),
|
||||
actor => actor.isPersonnage())
|
||||
}
|
||||
|
||||
constructor(actor, appreciation, qualite) {
|
||||
this.actor = actor
|
||||
this.appreciation = foundry.utils.duplicate(appreciation)
|
||||
this.appreciation.situation = SITUATION_MORAL[appreciation.moral]
|
||||
this.qualite = qualite
|
||||
this.raisons = []
|
||||
}
|
||||
|
||||
apprecier(callbacks = []) {
|
||||
if (this.qualite <= 0) {
|
||||
this.raisons.push(`la qualité ${this.qualite} est négative.`)
|
||||
}
|
||||
if (this.qualite <= this.actor.getMoralTotal()) {
|
||||
this.raisons.push(`la qualité de ${this.qualite} est inférieure au moral de ${this.actor.getMoralTotal()}.`)
|
||||
}
|
||||
const competence = this.getCompetenceAppreciation()
|
||||
if (this.appreciation.compMinimum && this.qualite <= competence.system.niveau && competence.system.niveau > 0 && competence.id) {
|
||||
this.raisons.push(`la qualité ${this.qualite} est insuffisante pour le niveau ${competence.system.niveau} en ${competence.name}`)
|
||||
}
|
||||
const bonmoment = this.appreciation.bonmoment
|
||||
if (!["", undefined].includes(bonmoment) && this.actor.system.compteurs.bonmoments.includes(bonmoment)) {
|
||||
this.raisons.push(`du moral a déjà été gagné pour cause de ${bonmoment}`)
|
||||
}
|
||||
|
||||
if (this.appreciation.carac != "") {
|
||||
this.rollAppreciation(callbacks)
|
||||
}
|
||||
else {
|
||||
this.rollMoral()
|
||||
}
|
||||
}
|
||||
|
||||
getCompetenceAppreciation() {
|
||||
return [SANS_COMPETENCE.name, ""].includes(this.appreciation.competence) ? SANS_COMPETENCE : this.actor.getCompetence(this.appreciation.competence)
|
||||
}
|
||||
|
||||
rollAppreciation(rollCallbacks = []) {
|
||||
const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : ""
|
||||
const rollData = {
|
||||
ids: { actorId: this.actor.id },
|
||||
type: { allowed: [PART_COMP], current: PART_COMP, appreciation: true },
|
||||
selected: {
|
||||
carac: { key: this.appreciation.carac, forced: true },
|
||||
comp: { key: competence, forced: true },
|
||||
diff: { type: DIFF.IMPOSEE },
|
||||
apprecier: {
|
||||
appreciation: this.appreciation,
|
||||
qualite: this.qualite,
|
||||
raisons: this.raisons
|
||||
}
|
||||
}
|
||||
}
|
||||
RollDialog.create(rollData, {
|
||||
callbacks: [
|
||||
async r => await this.onRollAppreciation(r),
|
||||
...rollCallbacks
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
async onRollAppreciation(roll) {
|
||||
if (roll.rolled.isSuccess) {
|
||||
await this.rollMoral()
|
||||
}
|
||||
else {
|
||||
if (this.appreciation.moral == MORAL.TRESHEUREUX) {
|
||||
await this.rollMoral(MORAL.HEUREUX)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async rollMoral(moral = undefined) {
|
||||
if (this.raisons.length > 0) {
|
||||
ui.notifications.info('Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`)))
|
||||
return
|
||||
}
|
||||
|
||||
moral = moral ?? this.appreciation.moral
|
||||
// TODO: jet de moral
|
||||
await this.actor.jetDeMoral(moral, this.appreciation.bonmoment)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { RDD_CONFIG } from "./constants.js";
|
||||
import { RdDItemArme } from "./item/arme.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
@@ -35,7 +36,7 @@ export class RdDBonus {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static dmg(rollData, actor, isEntiteIncarnee = false) {
|
||||
static dmg(rollData, actor) {
|
||||
const diff = rollData.diffLibre;
|
||||
const dmgArme = RdDBonus.dmgArme(rollData.arme, rollData.arme?.system.dommagesReels)
|
||||
const forceRequise = rollData.arme ? RdDItemArme.valeurMain(rollData.arme.system.force ?? 0, RdDItemArme.getMainAttaque(rollData.competence)) : 0
|
||||
@@ -47,32 +48,33 @@ export class RdDBonus {
|
||||
penetration: RdDBonus._peneration(rollData),
|
||||
dmgTactique: RdDBonus.dmgBonus(rollData.tactique),
|
||||
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
|
||||
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used),
|
||||
mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee),
|
||||
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris?.used),
|
||||
mortalite: RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite),
|
||||
dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme),
|
||||
dmgForceInsuffisante: Math.min(0, actor.getForce() - forceRequise)
|
||||
}
|
||||
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante
|
||||
return dmg;
|
||||
return dmg
|
||||
}
|
||||
|
||||
static dmgRollV2(rollData, attaque) {
|
||||
const actor = rollData.active.actor
|
||||
const arme = attaque.arme
|
||||
const dmgArme = RdDBonus.dmgArme(arme, attaque.dommagesArme)
|
||||
const dmgArme = RdDBonus.dmgArme(arme, attaque.dommages)
|
||||
const dmg = {
|
||||
total: 0,
|
||||
dmgArme: dmgArme,
|
||||
penetration: arme?.penetration() ?? 0,
|
||||
penetration: arme?.system.penetration ?? 0,
|
||||
diff: attaque.diff,
|
||||
dmgTactique: attaque.tactique?.dmg ?? 0,
|
||||
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
|
||||
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
|
||||
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite, rollData.opponent?.actor?.isEntite()),
|
||||
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite),
|
||||
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise),
|
||||
dmgForceInsuffisante: Math.min(0, actor.getForce() - attaque.forceRequise),
|
||||
dmgForceInsuffisante: Math.min(0, actor.getForce() - (attaque.forceRequise ?? 0)),
|
||||
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
|
||||
}
|
||||
dmg.isEmpoignade = dmg.mortalite == RDD_CONFIG.encaissement.empoignade
|
||||
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante + dmg.dmgDiffLibre
|
||||
return dmg
|
||||
}
|
||||
@@ -93,21 +95,14 @@ export class RdDBonus {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _calculMortalite(rollData, isEntiteIncarnee) {
|
||||
return RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite, isEntiteIncarnee)
|
||||
}
|
||||
|
||||
static mortalite(mortaliteSelect, mortaliteArme, isEntiteIncarnee) {
|
||||
return isEntiteIncarnee ? "entiteincarnee"
|
||||
: mortaliteSelect
|
||||
?? mortaliteArme
|
||||
?? "mortel";
|
||||
static mortalite(mortaliteSelect, mortaliteArme) {
|
||||
return mortaliteSelect ?? mortaliteArme ?? RDD_CONFIG.encaissement.mortel
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static dmgArme(arme, dommagesMain) {
|
||||
static dmgArme(arme, dommages) {
|
||||
if (arme) {
|
||||
let dmgBase = dommagesMain ?? Number(arme.system.dommages ?? 0);
|
||||
let dmgBase = dommages ?? Number(arme.system.dommages ?? 0);
|
||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
||||
return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { ENTITE_BLURETTE, HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
@@ -15,9 +15,8 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { MAP_PHASE, RdDInitiative } from "./initiative.mjs";
|
||||
import RollDialog from "./roll/roll-dialog.mjs";
|
||||
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
|
||||
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
|
||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
||||
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
|
||||
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
|
||||
|
||||
@@ -57,6 +56,12 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static getCombatant(actorId, tokenId) {
|
||||
return game.combat?.combatants.find(it => it.actor.id == actorId &&
|
||||
it.token.id == tokenId
|
||||
)
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async nextRound() {
|
||||
await this.finDeRound();
|
||||
@@ -100,7 +105,7 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
else if (!combatant.actor.isActorCombat()) {
|
||||
if (options.warning) {
|
||||
ui.notifications.warn(`${combatant.name} ne peut pas combattre!`)
|
||||
ui.notifications.warn(`L'acteur ${combatant.name} ne peut pas combattre!`)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
@@ -310,6 +315,7 @@ export class RdDCombat {
|
||||
switch (sockmsg.msg) {
|
||||
case "msg_encaisser": return RdDCombat.onMsgEncaisser(sockmsg.data);
|
||||
case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data);
|
||||
case "msg_defense_v2": return RdDCombat.onMsgDefenseV2(sockmsg.data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,6 +368,18 @@ export class RdDCombat {
|
||||
return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target)
|
||||
}
|
||||
|
||||
static rddCombatForAttackV2(attackerRoll) {
|
||||
return RdDCombat.rddCombatForDefenseV2(RollBasicParts.prepareDefense(attackerRoll))
|
||||
}
|
||||
|
||||
static rddCombatForDefenseV2(defenderRoll) {
|
||||
let defenderToken = canvas.tokens.get(defenderRoll.active.tokenId)
|
||||
if (defenderToken) {
|
||||
return RdDCombat.rddCombatForAttackerAndDefender(defenderRoll.opponent.id, defenderRoll.opponent.tokenId, defenderRoll.active.tokenId)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgEncaisser(msg) {
|
||||
let defender = canvas.tokens.get(msg.defenderToken.id).actor;
|
||||
@@ -380,7 +398,7 @@ export class RdDCombat {
|
||||
if (defenderToken && Misc.isFirstConnectedGM()) {
|
||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
|
||||
rddCombat?.removeChatMessageActionsPasseArme(msg.paramChatDefense.attackerRoll.passeArme)
|
||||
if (msg.defenderRoll.ids) {/* TODO: delete roll V1 */
|
||||
if (msg.defenderRoll.v2) {/* TODO: delete roll V1 */
|
||||
RollDialog.loadRollData(msg.paramChatDefense)
|
||||
rddCombat?._chatMessageDefenseV2(msg.paramChatDefense)
|
||||
} else {
|
||||
@@ -403,7 +421,6 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
static registerChatCallbacks(html) {
|
||||
for (let button of [
|
||||
'.button-defense',
|
||||
'.button-parade',
|
||||
'.button-esquive',
|
||||
'.button-encaisser',
|
||||
@@ -475,8 +492,6 @@ export class RdDCombat {
|
||||
|
||||
switch (button) {
|
||||
case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
|
||||
case '.button-defense': return this.defenseV2(attackerRoll);
|
||||
|
||||
case '.button-parade': return this.parade(attackerRoll, armeParadeId);
|
||||
case '.button-esquive': return this.esquive(attackerRoll, compId, competence);
|
||||
case '.button-encaisser': return this.encaisser(attackerRoll, defenderRoll);
|
||||
@@ -561,7 +576,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEchecTotal(rollData) {
|
||||
if (rollData.ids /* roll V2*/) {
|
||||
if (rollData.v2 /* roll V2*/) {
|
||||
// TODO: en cas de demi-surprise à l'attaque, tout échec est un echec total.
|
||||
// TODO: en cas de demi-surprise en défense, pas de changement à la règle de base
|
||||
return rollData.rolled.isETotal
|
||||
@@ -575,7 +590,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isParticuliere(rollData) {
|
||||
if (rollData.ids /* roll V2*/) {
|
||||
if (rollData.v2 /* roll V2*/) {
|
||||
return rollData.rolled.isPart
|
||||
}
|
||||
if (rollData.attackerRoll || !rollData.ajustements.surprise.used) {
|
||||
@@ -586,7 +601,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isReussite(rollData) {
|
||||
if (rollData.ids /* roll V2*/) {
|
||||
if (rollData.v2 /* roll V2*/) {
|
||||
return rollData.rolled.isSuccess
|
||||
}
|
||||
if (!rollData.ajustements.surprise.used) {
|
||||
@@ -602,7 +617,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
async proposerAjustementTirLancer(rollData) {
|
||||
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
|
||||
if (this.defender.isEntite([ENTITE_BLURETTE])) {
|
||||
if (this.defender.isEntiteBlurette()) {
|
||||
ChatMessage.create({
|
||||
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
|
||||
whisper: ChatUtility.getGMs()
|
||||
@@ -685,12 +700,8 @@ export class RdDCombat {
|
||||
|
||||
async doRollAttaque(rollData, callbacks = []) {
|
||||
// TODO V2 await this.proposerAjustementTirLancer(rollData)
|
||||
await RollDialog.create(rollData, {
|
||||
onRollDone: (dialog) => {
|
||||
if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
|
||||
dialog.close()
|
||||
},
|
||||
customChatMessage: true,
|
||||
return await RollDialog.create(rollData, {
|
||||
onRollDone: RollDialog.onRollDoneClose,
|
||||
callbacks: [
|
||||
async (roll) => await this.onAttaqueV2(roll),
|
||||
...callbacks
|
||||
@@ -724,32 +735,45 @@ export class RdDCombat {
|
||||
await this._chatMessageDefenseV2(paramChatDefense);
|
||||
}
|
||||
else {
|
||||
this._socketSendMessageDefense(paramChatDefense, {});
|
||||
this._socketSendMessageDefenseV2(paramChatDefense);
|
||||
}
|
||||
}
|
||||
async _chatMessageDefenseV2(paramDemandeDefense) {
|
||||
const attackerRoll = paramDemandeDefense.attackerRoll;
|
||||
RollBasicParts.loadSurprises(attackerRoll)
|
||||
attackerRoll.passeArme = attackerRoll.passeArme ?? foundry.utils.randomID(16)
|
||||
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
|
||||
// attackerRoll.current.attaque.dmg = attackerRoll.dmg
|
||||
// attaque.dmg = attackerRoll.current.attaque.dmg
|
||||
const attaque = RollDialog.saveParts(attackerRoll)
|
||||
const defense = {
|
||||
attackerRoll: attaque,
|
||||
ids: RollBasicParts.reverseIds(attaque),
|
||||
passeArme: attaque.passeArme ?? foundry.utils.randomID(16)
|
||||
|
||||
_socketSendMessageDefenseV2(paramChatDefense) {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense_v2", data: {paramChatDefense} })
|
||||
}
|
||||
|
||||
static async onMsgDefenseV2(msg) {
|
||||
if (Misc.isFirstConnectedGM()) {
|
||||
const paramChatDefense = msg.paramChatDefense
|
||||
RollBasicParts.restore(paramChatDefense.attackerRoll)
|
||||
const rddCombat = RdDCombat.rddCombatForAttackV2(paramChatDefense.attackerRoll)
|
||||
rddCombat?.removeChatMessageActionsPasseArme(paramChatDefense.attackerRoll.passeArme)
|
||||
await rddCombat?._chatMessageDefenseV2(paramChatDefense)
|
||||
}
|
||||
}
|
||||
|
||||
async _chatMessageDefenseV2(paramDemandeDefense) {
|
||||
const attackerRoll = paramDemandeDefense.attackerRoll
|
||||
RollBasicParts.loadSurprises(attackerRoll)
|
||||
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
|
||||
|
||||
const defenseData = RollBasicParts.prepareDefense(attackerRoll)
|
||||
|
||||
const choixDefense = await ChatMessage.create({
|
||||
// message privé: du défenseur à lui même (et aux GMs)
|
||||
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
||||
alias: this.attacker?.getAlias(),
|
||||
whisper: ChatUtility.getOwners(this.defender),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', attackerRoll)
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData)
|
||||
});
|
||||
// flag pour garder les jets d'attaque/defense
|
||||
ChatUtility.setMessageData(choixDefense, 'rollData', defense)
|
||||
ChatUtility.setMessageData(choixDefense, 'demande-defense', true)
|
||||
ChatUtility.setMessageData(choixDefense, 'rollData', {
|
||||
ids: defenseData.ids,
|
||||
attackerRoll: RollDialog.saveParts(attackerRoll),
|
||||
passeArme: defenseData.passeArme
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -804,7 +828,7 @@ export class RdDCombat {
|
||||
essais: {}
|
||||
};
|
||||
|
||||
if (this.attacker.isCreatureEntite()) {
|
||||
if (this.attacker.isCreatureOuEntite()) {
|
||||
MappingCreatureArme.setRollDataCreature(rollData);
|
||||
}
|
||||
else if (arme) {
|
||||
@@ -873,7 +897,7 @@ export class RdDCombat {
|
||||
async _onAttaqueNormale(attackerRoll) {
|
||||
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
|
||||
|
||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
|
||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker);
|
||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||
attackerRoll.show = {
|
||||
cible: this.defender?.getAlias() ?? 'la cible',
|
||||
@@ -892,7 +916,10 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isPossession(attackerRoll) {
|
||||
return attackerRoll.selectedCarac.label.toLowerCase() == 'possession';
|
||||
const carac = attackerRoll.v2
|
||||
? attackerRoll.current.carac?.label
|
||||
: attackerRoll.selectedCarac.label
|
||||
return carac?.toLowerCase() == 'possession';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -1056,9 +1083,8 @@ export class RdDCombat {
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
async defenseV2(attackerRoll) {
|
||||
async defenseV2(attackerRoll, callbacks = []) {
|
||||
// this._prepareParade(attackerRoll, arme, competence);
|
||||
RollDialog.loadRollData(attackerRoll)
|
||||
await this.doRollDefense({
|
||||
ids: {
|
||||
actorId: this.defender.id,
|
||||
@@ -1067,15 +1093,14 @@ export class RdDCombat {
|
||||
opponentId: this.attackerId,
|
||||
},
|
||||
type: { allowed: [ROLL_TYPE_DEFENSE], current: ROLL_TYPE_DEFENSE },
|
||||
attackerRoll: RollDialogAdapter.mapActionAttaque(attackerRoll),
|
||||
attackerRoll: attackerRoll,
|
||||
passeArme: attackerRoll.passeArme,
|
||||
})
|
||||
}, callbacks)
|
||||
}
|
||||
|
||||
async doRollDefense(rollData, callbacks = []) {
|
||||
await RollDialog.create(rollData, {
|
||||
return await RollDialog.create(rollData, {
|
||||
onRollDone: RollDialog.onRollDoneClose,
|
||||
customChatMessage: true,
|
||||
callbacks: [
|
||||
async (roll) => {
|
||||
this.removeChatMessageActionsPasseArme(roll.passeArme);
|
||||
@@ -1109,7 +1134,7 @@ export class RdDCombat {
|
||||
show: {}
|
||||
};
|
||||
|
||||
if (this.defender.isCreatureEntite()) {
|
||||
if (this.defender.isCreatureOuEntite()) {
|
||||
MappingCreatureArme.setRollDataCreature(defenderRoll);
|
||||
}
|
||||
|
||||
@@ -1236,7 +1261,7 @@ export class RdDCombat {
|
||||
show: {}
|
||||
};
|
||||
|
||||
if (this.defender.isCreatureEntite()) {
|
||||
if (this.defender.isCreatureOuEntite()) {
|
||||
MappingCreatureArme.setRollDataCreature(rollData);
|
||||
}
|
||||
return rollData;
|
||||
|
||||
@@ -127,7 +127,7 @@ export class RdDCommands {
|
||||
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
|
||||
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise
|
||||
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
|
||||
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
|
||||
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en Désert à +2 pour les tokens sélectionnés
|
||||
`
|
||||
});
|
||||
this.registerCommand({
|
||||
@@ -137,7 +137,7 @@ export class RdDCommands {
|
||||
<br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0
|
||||
<br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2
|
||||
<br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2
|
||||
<br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en désert à +2
|
||||
<br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en Désert à +2
|
||||
`
|
||||
});
|
||||
this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
|
||||
@@ -461,12 +461,7 @@ export class RdDCommands {
|
||||
|
||||
async supprimerSignesDraconiquesEphemeres() {
|
||||
if (game.user.isGM) {
|
||||
game.actors.forEach(actor => {
|
||||
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
||||
if (ephemeres.length > 0) {
|
||||
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
||||
}
|
||||
});
|
||||
game.actors.forEach(actor => actor.supprimerSignesDraconiques(it => it.system.ephemere))
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
|
||||
|
||||
@@ -4,6 +4,8 @@ import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDRollResult } from "./rdd-roll-result.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
|
||||
import { MAP_PHASE } from "./initiative.mjs";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDEmpoignade {
|
||||
@@ -12,6 +14,58 @@ export class RdDEmpoignade {
|
||||
static init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCombatantEmpoignade(actorId, tokenId) {
|
||||
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
|
||||
return MAP_PHASE.empoignade.rang == combatant?.system.init?.rang
|
||||
}
|
||||
|
||||
static async ajustementEmpoignade(attacker, defender, adjust = 1) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
if (empoignade?.system.empoigneurid == defender.id) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(defender, attacker)
|
||||
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, defender, attacker, - adjust);
|
||||
}
|
||||
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, attacker, defender, adjust);
|
||||
}
|
||||
|
||||
|
||||
static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) {
|
||||
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16);
|
||||
const empFin = (empoignade?.system.pointsemp ?? 0) + adjust
|
||||
if (empoignade) {
|
||||
empoignade.system.pointsemp = empFin;
|
||||
await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender);
|
||||
}
|
||||
else {
|
||||
await RdDEmpoignade.$createEtatEmpoignade({
|
||||
name: `Empoignade de ${attacker.name} sur ${defender.name}`,
|
||||
type: ITEM_TYPES.empoignade,
|
||||
system: {
|
||||
description: "",
|
||||
empoignadeid: empId,
|
||||
empoigneurid: attacker.id,
|
||||
empoigneid: defender.id,
|
||||
pointsemp: empFin,
|
||||
empoigneurname: attacker.name,
|
||||
empoignename: defender.name
|
||||
}
|
||||
}, attacker, defender);
|
||||
}
|
||||
if (adjust != 0 && empFin == 2) {
|
||||
await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade);
|
||||
}
|
||||
const result = RdDEmpoignade.getEmpoignadeById(defender, empId);
|
||||
const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2);
|
||||
const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2);
|
||||
const grappling = Math.abs(result.system.pointsemp) > 0;
|
||||
await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled);
|
||||
await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled);
|
||||
await defender.setEffect(STATUSES.StatusGrappled, defGrappled);
|
||||
await attacker.setEffect(STATUSES.StatusGrappled, attGrappled);
|
||||
return result
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static registerChatCallbacks(html) {
|
||||
$(html).on("click", '.defense-empoignade-cac', event => {
|
||||
@@ -35,20 +89,20 @@ export class RdDEmpoignade {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.entrainerAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
ChatUtility.remover(chatMessage)()
|
||||
});
|
||||
$(html).on("click", '.empoignade-projeter-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.projeterAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
ChatUtility.remover(chatMessage)()
|
||||
});
|
||||
$(html).on("change", '.empoignade-perte-endurance', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
ChatUtility.remover(chatMessage)()
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -93,8 +147,7 @@ export class RdDEmpoignade {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignadeById(actor, id) {
|
||||
let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
||||
return emp && foundry.utils.duplicate(emp) || undefined;
|
||||
return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -184,16 +237,28 @@ export class RdDEmpoignade {
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
if (attacker.isCreatureEntite()) {
|
||||
if (attacker.isCreatureOuEntite()) {
|
||||
MappingCreatureArme.setRollDataCreature(rollData)
|
||||
}
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
if (!empoignade.system.ausol) {
|
||||
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade)
|
||||
} else {
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle)
|
||||
}
|
||||
}
|
||||
|
||||
static async proposerEntrainerAuSol(attacker, defender, empoignade) {
|
||||
if (!empoignade.system.ausol) {
|
||||
const mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||
const rollData = {
|
||||
mode, empoignade, attacker, defender,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetenceCorpsACorps(),
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
const msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,7 +269,14 @@ export class RdDEmpoignade {
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
|
||||
static async onImmobilisation(attacker, defender, empoignade) {
|
||||
static async onImmobilisation(attacker, empoignade) {
|
||||
const defender = game.actors.get(empoignade.system.empoigneid)
|
||||
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
|
||||
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
|
||||
await defender.updateEmbeddedDocuments('Item', [{
|
||||
_id: empDefenseur.id,
|
||||
'system.immobilise': true
|
||||
}])
|
||||
const rollData = {
|
||||
mode: "immobilise",
|
||||
empoignade, attacker, defender,
|
||||
@@ -237,10 +309,7 @@ export class RdDEmpoignade {
|
||||
|
||||
|
||||
if (rollData.rolled.isSuccess && isNouvelle) {
|
||||
const objectEmpoignade = rollData.empoignade.toObject();
|
||||
// Creer l'empoignade sur attaquant/defenseur
|
||||
attacker.creerObjetParMJ(objectEmpoignade);
|
||||
defender.creerObjetParMJ(objectEmpoignade);
|
||||
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
|
||||
}
|
||||
|
||||
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
|
||||
@@ -259,7 +328,7 @@ export class RdDEmpoignade {
|
||||
return
|
||||
}
|
||||
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
|
||||
if (!empoignade) {
|
||||
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
||||
@@ -317,27 +386,48 @@ export class RdDEmpoignade {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $updateEtatEmpoignade(empoignade) {
|
||||
console.log("UPDATE Empoignade", empoignade)
|
||||
static async $createEtatEmpoignade(empoignade) {
|
||||
console.log("CREATE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await defender.updateEmbeddedDocuments('Item', [update])
|
||||
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await attacker.updateEmbeddedDocuments('Item', [update])
|
||||
|
||||
// Creer l'empoignade sur attaquant/defenseur
|
||||
await attacker.creerObjetParMJ(empoignade)
|
||||
await defender.creerObjetParMJ(empoignade)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $updateEtatEmpoignade(empoignade, attacker, defender) {
|
||||
const belligerants = [
|
||||
attacker ?? game.actors.get(empoignade.system.empoigneurid),
|
||||
defender ?? game.actors.get(empoignade.system.empoigneid)]
|
||||
const removeEmp = empoignade.system.pointsemp == 0
|
||||
|
||||
if (removeEmp) {
|
||||
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
|
||||
}
|
||||
else {
|
||||
await Promise.all(
|
||||
belligerants.map(async belligerant => {
|
||||
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
|
||||
return await belligerant.updateEmbeddedDocuments('Item', [{
|
||||
_id: emp.id,
|
||||
"system.pointsemp": empoignade.system.pointsemp,
|
||||
"system.ausol": empoignade.system.ausol
|
||||
}])
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $deleteEmpoignade(empoignade) {
|
||||
console.log("DELETE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
const defender = game.actors.get(empoignade.system.empoigneid)
|
||||
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
await defender.deleteEmbeddedDocuments('Item', [emp.id])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -347,7 +437,7 @@ export class RdDEmpoignade {
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
|
||||
empoignade.system.ausol = true
|
||||
await this.$updateEtatEmpoignade(empoignade)
|
||||
@@ -366,7 +456,7 @@ export class RdDEmpoignade {
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
await this.$deleteEmpoignade(empoignade)
|
||||
@@ -379,29 +469,28 @@ export class RdDEmpoignade {
|
||||
static async perteEndurance(rollData, perteMode) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
//console.log("Perte d'endurance :!!!", perteMode)
|
||||
let endValue = defender.system.sante.endurance.value
|
||||
if (perteMode == "end0") {
|
||||
await defender.santeIncDec("endurance", -endValue);
|
||||
}
|
||||
if (perteMode == "end1") {
|
||||
await defender.santeIncDec("endurance", -(endValue - 1));
|
||||
}
|
||||
if (perteMode == "endmoitie") {
|
||||
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
|
||||
}
|
||||
if (perteMode == "endquart") {
|
||||
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||
}
|
||||
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.hbs');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
const perteEndurance = await RdDEmpoignade.$calcPerteEnd(perteMode, defender.system.sante.endurance.value)
|
||||
await defender.santeIncDec("endurance", -perteEndurance)
|
||||
await RdDRollResult.displayRollData({ attacker, defender, perteEndurance },
|
||||
attacker,
|
||||
'chat-empoignade-perte-endurance.hbs')
|
||||
}
|
||||
|
||||
static async $calcPerteEnd(perteMode, endValue) {
|
||||
switch (perteMode) {
|
||||
case "none": return 0
|
||||
case "end0": return endValue
|
||||
case "end1": return (endValue - 1)
|
||||
case "3/4": return Math.floor(3 * endValue / 4)
|
||||
case "1/2": return Math.floor(endValue / 2)
|
||||
case "1/4": return Math.floor(endValue / 4)
|
||||
}
|
||||
const rolled = await (new Roll(perteMode).evaluate())
|
||||
return rolled.total
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static async deleteAllEmpoignades() {
|
||||
for (let actor of game.actors) {
|
||||
@@ -416,16 +505,24 @@ export class RdDEmpoignade {
|
||||
let actor = game.actors.get(actorDeleteId)
|
||||
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
|
||||
if (emp) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
await actor.deleteEmbeddedDocuments('Item', [emp.id])
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createEmpoignade(attacker, defender) {
|
||||
return await Item.create({
|
||||
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
|
||||
type: 'empoignade',
|
||||
system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
|
||||
name: "Empoignade de " + attacker.name + ' sur ' + defender.name,
|
||||
type: ITEM_TYPES.empoignade,
|
||||
system: {
|
||||
description: "",
|
||||
empoignadeid: foundry.utils.randomID(16),
|
||||
empoigneurid: attacker.id,
|
||||
empoigneid: defender.id,
|
||||
pointsemp: 0,
|
||||
empoigneurname: attacker.name,
|
||||
empoignename: defender.name
|
||||
}
|
||||
},
|
||||
{
|
||||
temporary: true
|
||||
|
||||
@@ -89,6 +89,7 @@ import { Migrations } from './migrations.js'
|
||||
|
||||
import RollDialog from "./roll/roll-dialog.mjs"
|
||||
import ChatRollResult from "./roll/chat-roll-result.mjs"
|
||||
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
|
||||
|
||||
/**
|
||||
* RdD system
|
||||
@@ -296,6 +297,7 @@ export class SystemReveDeDragon {
|
||||
RdDPossession.init()
|
||||
TMRRencontres.init()
|
||||
ExportScriptarium.init()
|
||||
ExportPdf.init()
|
||||
RollDialog.init()
|
||||
ChatRollResult.init()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "./constants.js";
|
||||
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import RollDialog from "./roll/roll-dialog.mjs";
|
||||
import { Targets } from "./targets.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { ROLL_TYPE_POSSESSION } from "./roll/roll-constants.mjs";
|
||||
import { TokenActor } from "./technical/actor-token.mjs";
|
||||
|
||||
export const ACTIONS_POSSESSION = {
|
||||
ATTAQUE: 'attaque',
|
||||
POSSEDER: 'posseder',
|
||||
CONJURER: 'conjurer',
|
||||
DEFENSE: 'defense',
|
||||
DEFENSE_POSSESSION: 'defense-possession',
|
||||
DEFENSE_CONJURATION: 'defense-conjuration'
|
||||
}
|
||||
|
||||
export class RdDPossessionV2 {
|
||||
|
||||
static init() {
|
||||
}
|
||||
|
||||
static $isInverse(entite, victime) {
|
||||
return !entite.actor.isEntiteNonIncarnee() && victime.actor.isEntiteNonIncarnee()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findPossession(entite, victime) {
|
||||
if (RdDPossessionV2.$isInverse(entite, victime)) {
|
||||
return RdDPossessionV2.findPossession(victime, entite)
|
||||
}
|
||||
return victime.actor.itemTypes[ITEM_TYPES.possession].find(it => it.system.entiteid == entite.id)
|
||||
}
|
||||
|
||||
static async createPossessionIfMissing(entite, victime) {
|
||||
if (RdDPossessionV2.$isInverse(entite, victime)) {
|
||||
return await RdDPossessionV2.createPossessionIfMissing(victime, entite)
|
||||
}
|
||||
const existing = RdDPossessionV2.findPossession(entite, victime)
|
||||
if (!existing) {
|
||||
await victime.actor.createEmbeddedDocuments('Item', [{
|
||||
name: `Possession de ${entite.name}`,
|
||||
type: ITEM_TYPES.possession,
|
||||
img: RDD_CONFIG.icons.possession,
|
||||
system: {
|
||||
entiteid: entite.actor.id,
|
||||
entitetokenid: entite.token.id,
|
||||
victimeid: victime.actor.id,
|
||||
victimetokenid: victime.token.id,
|
||||
compteur: 0
|
||||
}
|
||||
}])
|
||||
}
|
||||
}
|
||||
|
||||
static getTypePossession(active, opponent) {
|
||||
const itemPossession = RdDPossessionV2.findPossession(active, opponent)
|
||||
const isEntite = active.actor.isEntiteNonIncarnee() && !opponent.actor.isEntiteNonIncarnee()
|
||||
const compteur = itemPossession?.system.compteur ?? 0
|
||||
|
||||
return {
|
||||
isEntite: isEntite,
|
||||
isPersonnage: active.actor.isPersonnage(),
|
||||
isCompteurPossession: Math.sign(compteur) >= 0,
|
||||
compteur: Math.abs(compteur)
|
||||
}
|
||||
}
|
||||
|
||||
static getTypePossessionAction(active, opponent, action) {
|
||||
const possession = RdDPossessionV2.getTypePossession(active, opponent)
|
||||
possession.isAttaque = RdDPossessionV2.isAttaque(action)
|
||||
possession.action = RdDPossessionV2.$getAction(possession.isAttaque, possession.isEntite)
|
||||
return possession
|
||||
}
|
||||
|
||||
static $getAction(isAttaque, isEntite) {
|
||||
if (isAttaque) {
|
||||
return isEntite ? ACTIONS_POSSESSION.POSSEDER : ACTIONS_POSSESSION.CONJURER
|
||||
}
|
||||
return isEntite ? ACTIONS_POSSESSION.DEFENSE_CONJURATION : ACTIONS_POSSESSION.DEFENSE_POSSESSION
|
||||
}
|
||||
|
||||
static actionTitle(action) {
|
||||
switch (action) {
|
||||
case ACTIONS_POSSESSION.POSSEDER: return "tente de posséder"
|
||||
case ACTIONS_POSSESSION.CONJURER: return "tente de conjurer"
|
||||
case ACTIONS_POSSESSION.DEFENSE_POSSESSION: return "résiste à la possession de"
|
||||
case ACTIONS_POSSESSION.DEFENSE_CONJURATION: return "résiste à la conjuration de"
|
||||
case ACTIONS_POSSESSION.DEFENSE: return "résiste à "
|
||||
}
|
||||
return "lutte contre"
|
||||
}
|
||||
|
||||
static isDefense(action) {
|
||||
return [ACTIONS_POSSESSION.DEFENSE, ACTIONS_POSSESSION.DEFENSE_POSSESSION, ACTIONS_POSSESSION.DEFENSE_CONJURATION].includes(action)
|
||||
}
|
||||
static isAttaque(action) {
|
||||
return [ACTIONS_POSSESSION.ATTAQUE, ACTIONS_POSSESSION.POSSEDER, ACTIONS_POSSESSION.CONJURER].includes(action)
|
||||
}
|
||||
|
||||
static async rollAttaquePossession(actor) {
|
||||
const selectedToken = RdDUtility.getSelectedToken(actor)
|
||||
Targets.selectOneTargetToken(async target => {
|
||||
RollDialog.create(
|
||||
{
|
||||
ids: {
|
||||
actorId: actor.id,
|
||||
actorTokenId: selectedToken.id,
|
||||
opponentId: target.actor.id,
|
||||
opponentTokenId: target.id
|
||||
},
|
||||
passeArme: foundry.utils.randomID(16),
|
||||
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
|
||||
},
|
||||
{
|
||||
onRollDone: RollDialog.onRollDoneClose,
|
||||
callbacks: [
|
||||
async (roll) => await RdDPossessionV2.createPossessionIfMissing(roll.active, roll.opponent),
|
||||
async (roll) => RdDPossessionV2.$setParticuliereFinesse(roll),
|
||||
async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)
|
||||
]
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
static async rollConjurerPossession(actor, possession) {
|
||||
if (possession.system.possede){
|
||||
ui.notifications.warn(`${actor.name} est totalement possédé, impossible de conjurer l'entité`)
|
||||
return
|
||||
}
|
||||
RollDialog.create(
|
||||
{
|
||||
ids: {
|
||||
actorId: possession.system.victimeid,
|
||||
actorTokenId: possession.system.victimetokenid,
|
||||
opponentId: possession.system.entiteid,
|
||||
opponentTokenId: possession.system.entitetokenid
|
||||
},
|
||||
passeArme: foundry.utils.randomID(16),
|
||||
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
|
||||
},
|
||||
{
|
||||
onRollDone: RollDialog.onRollDoneClose,
|
||||
callbacks: [
|
||||
async (roll) => await RdDPossessionV2.createPossessionIfMissing(roll.active, roll.opponent),
|
||||
async (roll) => RdDPossessionV2.$setParticuliereFinesse(roll),
|
||||
async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
static $setParticuliereFinesse(roll) {
|
||||
if (roll.rolled.isPart) {
|
||||
roll.particuliere = RDD_CONFIG.particuliere.finesse.key
|
||||
}
|
||||
}
|
||||
|
||||
static async rollDefensePossession(savedRoll, chatMessage) {
|
||||
RollBasicParts.restore(savedRoll)
|
||||
const attackerRoll = savedRoll.attackerRoll
|
||||
RollDialog.create(
|
||||
{
|
||||
ids: savedRoll.ids,
|
||||
passeArme: attackerRoll.passeArme,
|
||||
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.DEFENSE } },
|
||||
selected: { diff: { value: attackerRoll.selected?.diff?.value ?? 0 } },
|
||||
attackerRoll: attackerRoll
|
||||
},
|
||||
{
|
||||
onRollDone: RollDialog.onRollDoneClose, callbacks: [
|
||||
async roll => await RdDPossessionV2.onRollDefense(roll),
|
||||
ChatUtility.remover(chatMessage)
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static async onRollDefense(defense) {
|
||||
if (defense.rolled.isEchec) {
|
||||
await RdDPossessionV2.addPointPossession(defense.opponent.actor, defense.active.actor)
|
||||
}
|
||||
RdDPossessionV2.resetPossession(defense)
|
||||
}
|
||||
|
||||
|
||||
static async onMarquerPointPossession(roll) {
|
||||
roll.type = {}
|
||||
await RdDPossessionV2.addPointPossession(roll.opponent, roll.active)
|
||||
RdDPossessionV2.resetPossession(roll)
|
||||
|
||||
await ChatMessage.create({
|
||||
// message privé: du défenseur à lui même (et aux GMs)
|
||||
speaker: ChatMessage.getSpeaker({ actor: roll.active.actor, token: roll.active.token }),
|
||||
alias: roll.opponent.name,
|
||||
whisper: ChatUtility.getOwners(roll.active.actor),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/possession/chat-message-marquer.hbs`, roll)
|
||||
})
|
||||
}
|
||||
|
||||
static resetPossession(roll) {
|
||||
roll.type.possession = foundry.utils.mergeObject(
|
||||
roll.type.possession ?? {},
|
||||
RdDPossessionV2.getTypePossession(roll.opponent, roll.active))
|
||||
}
|
||||
|
||||
static async addPointPossession(entite, victime, points = 1) {
|
||||
if (RdDPossessionV2.$isInverse(entite, victime)) {
|
||||
return await RdDPossessionV2.addPointPossession(victime, entite, - points)
|
||||
}
|
||||
const existing = RdDPossessionV2.findPossession(entite, victime)
|
||||
if (existing) {
|
||||
const compteur = (existing.system.compteur ?? 0) + points
|
||||
await victime.actor.updateEmbeddedDocuments('Item', [{ _id: existing.id, 'system.compteur': compteur }])
|
||||
}
|
||||
}
|
||||
|
||||
static async chatMessageDefensePossession(attackerRoll) {
|
||||
|
||||
const defense = RollBasicParts.prepareDefense(attackerRoll)
|
||||
defense.type = {
|
||||
possession: RdDPossessionV2.getTypePossessionAction(defense.active, defense.opponent, ACTIONS_POSSESSION.DEFENSE)
|
||||
}
|
||||
|
||||
const chatDemandeDefense = await ChatMessage.create({
|
||||
// message privé: du défenseur à lui même (et aux GMs)
|
||||
speaker: ChatMessage.getSpeaker({ actor: defense.active.actor, token: defense.active.token }),
|
||||
alias: attackerRoll.active.name,
|
||||
whisper: ChatUtility.getOwners(defense.active.actor),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/possession/chat-demande-defense.hbs', defense)
|
||||
});
|
||||
ChatUtility.setMessageData(chatDemandeDefense, 'demande-defense', true)
|
||||
// // flag pour garder les jets d'attaque/defense
|
||||
ChatUtility.setMessageData(chatDemandeDefense, 'rollData', {
|
||||
ids: defense.ids,
|
||||
attackerRoll: RollDialog.saveParts(attackerRoll),
|
||||
passeArme: defense.passeArme
|
||||
})
|
||||
}
|
||||
|
||||
static async onPossession(actor, possession) {
|
||||
if (Math.abs(possession.system.compteur) >= 2) {
|
||||
await ChatMessage.create({
|
||||
alias: actor.getAlias(),
|
||||
whisper: ChatUtility.getOwners(actor),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/possession/chat-fin-possession.hbs', {
|
||||
possession,
|
||||
active: TokenActor.fromActor(actor),
|
||||
opponent: TokenActor.fromActor(game.actors.get(possession.system.entiteid))
|
||||
})
|
||||
})
|
||||
|
||||
if (possession.system.compteur <= -2) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [possession.id])
|
||||
}
|
||||
if (possession.system.compteur >= 2) {
|
||||
await actor.updateEmbeddedDocuments('Item', [{ _id: possession.id, 'system.possede': true }])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,9 +18,9 @@ export class RdDPossession {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static searchPossessionFromEntite(attacker, defender) {
|
||||
let poss = attacker.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||
let poss = attacker.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.victime.actorid == defender.id);
|
||||
if (!poss) {
|
||||
poss = defender.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||
poss = defender.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.victime.actorid == defender.id);
|
||||
}
|
||||
return poss && foundry.utils.duplicate(poss) || undefined;
|
||||
}
|
||||
@@ -94,8 +94,8 @@ export class RdDPossession {
|
||||
}
|
||||
|
||||
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
|
||||
rollData.competence = rollingActor.getDraconicOuPossession();
|
||||
if (rollingActor.isCreatureEntite()) {
|
||||
rollData.competence = rollingActor.getDraconicOuPossession().find(it => true);
|
||||
if (rollingActor.isCreatureOuEntite()) {
|
||||
const carac = rollingActor.system.carac
|
||||
rollData.carac = carac
|
||||
rollData.competence.system.defaut_carac = 'reve'
|
||||
@@ -132,7 +132,7 @@ export class RdDPossession {
|
||||
}
|
||||
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
|
||||
RdDPossession.storePossessionAttaque(possession, rollData)
|
||||
await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.hbs');
|
||||
await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-resultat-possession-v1.hbs');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -172,7 +172,7 @@ export class RdDPossession {
|
||||
rollData.possession = possession
|
||||
RdDPossession.$updateEtatPossession(rollData.possession)
|
||||
|
||||
await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.hbs')
|
||||
await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession-v1.hbs')
|
||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||
// conjuration
|
||||
await victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||
@@ -226,15 +226,18 @@ export class RdDPossession {
|
||||
/* -------------------------------------------- */
|
||||
static async createPossession(attacker, defender) {
|
||||
return await Item.create({
|
||||
name: "Possession en cours de " + attacker.name, type: 'possession',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||
name: `Possession de ${entite.name}`,
|
||||
type: ITEM_TYPES.possession,
|
||||
img: RDD_CONFIG.icons.possession,
|
||||
system: {
|
||||
description: "", typepossession: attacker.name,
|
||||
typepossession: attacker.name,
|
||||
possede: false,
|
||||
possessionid: foundry.utils.randomID(16),
|
||||
entiteid: attacker.id,
|
||||
victimeid: defender.id,
|
||||
compteur: 0,
|
||||
entite: { actorid: attacker.id },
|
||||
victime: { actorid: defender.id },
|
||||
compteur: 0
|
||||
victime: { actorid: defender.id }
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -16,17 +16,20 @@ const levelDown = [
|
||||
];
|
||||
const levelImpossible = { score: 0, norm: 0, sign: 0, part: 0, epart: 0, etotal: 1 };
|
||||
|
||||
const reussiteNormale = { code: "norm", isPart: false, isSign: false, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 1, ptQualite: 0, quality: "Réussite normale", condition: (target, roll) => (roll > target.sign && roll <= target.norm) };
|
||||
const reussiteSignificative = { code: "sign", isPart: false, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 2, ptQualite: 1, quality: "Réussite significative", condition: (target, roll) => (roll > target.part && roll <= target.sign) };
|
||||
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
||||
|
||||
const reussites = [
|
||||
{ code: "etotal", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: -4, ptQualite: -6, quality: "Echec total", condition: (target, roll) => roll >= target.etotal && roll <= 100 },
|
||||
{ code: "epart", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: false, ptTache: -2, ptQualite: -4, quality: "Echec particulier", condition: (target, roll) => (roll >= target.epart && roll < target.etotal) },
|
||||
{ code: "echec", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Echec normal", condition: (target, roll) => (roll > target.norm && roll < target.etotal) },
|
||||
{ code: "norm", isPart: false, isSign: false, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 1, ptQualite: 0, quality: "Réussite normale", condition: (target, roll) => (roll > target.sign && roll <= target.norm) },
|
||||
{ code: "sign", isPart: false, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 2, ptQualite: 1, quality: "Réussite significative", condition: (target, roll) => (roll > target.part && roll <= target.sign) },
|
||||
reussiteNormale,
|
||||
reussiteSignificative,
|
||||
{ code: "part", isPart: true, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 3, ptQualite: 2, quality: "Réussite Particulière!", condition: (target, roll) => (roll > 0 && roll <= target.part) },
|
||||
{ code: "error", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: 0, ptQualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) }
|
||||
];
|
||||
|
||||
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
||||
/* -------------------------------------------- */
|
||||
const CARAC_MAXIMUM_RESOLUTION = 40;
|
||||
/* -------------------------------------------- */
|
||||
@@ -156,6 +159,11 @@ export class RdDResolutionTable {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static replaceParticuliereDemiSurprise(chances) {
|
||||
foundry.utils.mergeObject(chances, reussites.find(x => x.code == 'part'), { overwrite: true });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static significativeRequise(chances) {
|
||||
chances.roll = Math.min(chances.part + 1, chances.sign)
|
||||
@@ -192,6 +200,7 @@ export class RdDResolutionTable {
|
||||
if (chances.norm < roll * diviseur) {
|
||||
return reussiteInsuffisante
|
||||
}
|
||||
return reussiteSignificative
|
||||
}
|
||||
return reussite
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, renderTemplate } from "./constants.js";
|
||||
import { ENTITE_NONINCARNE, RDD_CONFIG, renderTemplate } from "./constants.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/**
|
||||
@@ -16,34 +16,29 @@ export class RdDEncaisser extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor) {
|
||||
let dialogConf = {
|
||||
if (actor.isEntiteNonIncarnee()) {
|
||||
throw `${actor.name} est une entité non incarnée et ne peut pas subnir de dommages`
|
||||
}
|
||||
|
||||
const dialogConf = {
|
||||
title: "Jet d'Encaissement",
|
||||
content: html,
|
||||
}
|
||||
|
||||
if (!actor.isEntite()) {
|
||||
dialogConf.default = "mortel";
|
||||
dialogConf.buttons = {
|
||||
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
|
||||
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
|
||||
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
|
||||
};
|
||||
}
|
||||
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
|
||||
dialogConf.default = "entiteincarnee"
|
||||
dialogConf.buttons = {
|
||||
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
|
||||
default: RDD_CONFIG.encaissement.mortel,
|
||||
buttons: {
|
||||
[RDD_CONFIG.encaissement.mortel]: { label: "Mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.mortel) },
|
||||
}
|
||||
}
|
||||
|
||||
let dialogOptions = {
|
||||
classes: ["rdd-roll-dialog"],
|
||||
width: 320,
|
||||
height: 'fit-content'
|
||||
if (!actor.isEntite()) {
|
||||
dialogConf.buttons[RDD_CONFIG.encaissement.nonmortel] = { label: "Non-mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.nonmortel) }
|
||||
dialogConf.buttons["sonne"] = { label: "Sonné", callback: html => this.actor.setSonne() }
|
||||
}
|
||||
|
||||
// Select proper roll dialog template and stuff
|
||||
super(dialogConf, dialogOptions);
|
||||
super(dialogConf, {
|
||||
classes: ["rdd-roll-dialog"],
|
||||
width: 320,
|
||||
height: 'fit-content'
|
||||
});
|
||||
|
||||
this.actor = actor;
|
||||
this.modifier = 0;
|
||||
|
||||
@@ -25,7 +25,7 @@ export class RdDRollDialogEthylisme extends Dialog {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
this.bringToTop();
|
||||
this.bringToFront();
|
||||
|
||||
this.html.find(".force-alcool").change((event) => {
|
||||
this.rollData.forceAlcool = Misc.toInt(event.currentTarget.value);
|
||||
|
||||
@@ -22,7 +22,7 @@ export class RdDRollResolutionTable extends Dialog {
|
||||
RdDRollResolutionTable.resolutionTable.render(true);
|
||||
}
|
||||
else{
|
||||
RdDRollResolutionTable.resolutionTable.bringToTop();
|
||||
RdDRollResolutionTable.resolutionTable.bringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ export class RdDRollResolutionTable extends Dialog {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
this.bringToTop();
|
||||
this.bringToFront();
|
||||
|
||||
|
||||
this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));
|
||||
|
||||
@@ -8,7 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { ACTOR_TYPES, renderTemplate } from "./constants.js";
|
||||
import { ACTOR_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
|
||||
import { EMPOIGNADE } from "./item/arme.js";
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ export class RdDRoll extends Dialog {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
this.bringToTop();
|
||||
this.bringToFront();
|
||||
|
||||
console.log('RdDRoll.activateListeners', this.rollData);
|
||||
|
||||
@@ -206,7 +206,7 @@ export class RdDRoll extends Dialog {
|
||||
this.updateRollResult(html);
|
||||
});
|
||||
this.html.find("input.check-mortalite").change((event) => {
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? RDD_CONFIG.encaissement.nonmortel : RDD_CONFIG.encaissement.mortel;
|
||||
this.updateRollResult(html);
|
||||
});
|
||||
this.html.find('.cuisine-proportions').change((event) => {
|
||||
@@ -333,8 +333,8 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
// Mise à jour valeurs
|
||||
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
||||
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel');
|
||||
this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == EMPOIGNADE ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
|
||||
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == RDD_CONFIG.encaissement.nonmortel);
|
||||
this.html.find("label.dmg-arme-actor").text(rollData.dmg.isEmpoignade ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
|
||||
this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
|
||||
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
|
||||
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
|
||||
|
||||
@@ -82,7 +82,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.subdialog = undefined
|
||||
this.displaySize = undefined
|
||||
if (!this.viewOnly && !game.user.isGM) {
|
||||
this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
|
||||
ChatUtility.tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
|
||||
}
|
||||
this.callbacksOnAnimate = [];
|
||||
const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def);
|
||||
@@ -125,7 +125,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor()));
|
||||
|
||||
this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop());
|
||||
this.html.find('form.tmr-dialog *').click(event => {
|
||||
if (this.subdialog?.rendered){
|
||||
this.subdialog?.bringToFront()
|
||||
}
|
||||
})
|
||||
|
||||
// Roll Sort
|
||||
this.html.find('.lancer-sort').click(event => this.lancerUnSort());
|
||||
@@ -169,26 +173,26 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
async forceTMRDisplay() {
|
||||
if (this.rendered) {
|
||||
this.bringToTop()
|
||||
this.bringSubDialogToTop();
|
||||
this.bringToFront()
|
||||
this.bringSubDialogToFront();
|
||||
}
|
||||
}
|
||||
|
||||
bringSubDialogToTop() {
|
||||
if (this.subdialog?.bringToTop && this.subdialog?.element && this.subdialog?.element[0]) {
|
||||
this.subdialog.bringToTop();
|
||||
bringSubDialogToFront() {
|
||||
if (this.subdialog?.bringToFront && this.subdialog?.element && this.subdialog?.element[0]) {
|
||||
this.subdialog.bringToFront();
|
||||
}
|
||||
}
|
||||
|
||||
async restoreTMRAfterAction() {
|
||||
this.subdialog = undefined
|
||||
await this.maximize()
|
||||
this.bringToTop()
|
||||
this.bringToFront()
|
||||
}
|
||||
|
||||
forceTMRContinueAction() {
|
||||
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
|
||||
this.bringSubDialogToTop();
|
||||
this.bringSubDialogToFront();
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -343,19 +347,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.forceTMRContinueAction()
|
||||
return false
|
||||
}
|
||||
this.descenteTMR = true;
|
||||
if (this.actor.tmrApp) {
|
||||
this.actor.tmrApp = undefined // Cleanup reference
|
||||
const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue")
|
||||
await this.actor.santeIncDec(
|
||||
appliquerFatigue ? "fatigue" : "endurance",
|
||||
(appliquerFatigue ? 1 : -1) * this.cumulFatigue)
|
||||
if (!this.viewOnly) {
|
||||
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
||||
this.$tellToUserAndGM(message)
|
||||
}
|
||||
|
||||
}
|
||||
this.descenteTMR = true
|
||||
await await this.actor.quitterTMR(message, this.viewOnly, this.cumulFatigue)
|
||||
this.pixiTMR.close();
|
||||
this.pixiTMR = undefined
|
||||
await super.close();
|
||||
@@ -412,7 +405,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
async $ignorerRencontre() {
|
||||
if (this.currentRencontre) {
|
||||
console.log("-> ignorer", this.currentRencontre);
|
||||
this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
|
||||
ChatUtility.tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
|
||||
await this.$deleteRencontreTMRAtPosition()
|
||||
this.updateTokens();
|
||||
this.$updateValuesDisplay();
|
||||
@@ -578,29 +571,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tellToUser(message) {
|
||||
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
$tellToGM(message) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: message,
|
||||
whisper: ChatUtility.getGMs()
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
$tellToUserAndGM(message) {
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
content: message,
|
||||
whisper: ChatUtility.getUserAndGMs()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async manageRencontre(tmr) {
|
||||
if (this.viewOnly) {
|
||||
@@ -676,14 +646,14 @@ export class RdDTMRDialog extends Dialog {
|
||||
? TMRUtility.getTMRType(tmr.coord) + " ??"
|
||||
: tmr.label + " (" + tmr.coord + ")");
|
||||
|
||||
this.setTMRPendingAction({ bringToTop: () => { } })
|
||||
this.setTMRPendingAction({ bringToFront: () => { } })
|
||||
const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
|
||||
this.restoreTMRAfterAction()
|
||||
if (myRoll == 7) {
|
||||
this._tellToUser(myRoll + ": Rencontre en " + coordTMR);
|
||||
ChatUtility.tellToUser(myRoll + ": Rencontre en " + coordTMR);
|
||||
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
||||
} else {
|
||||
this._tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
|
||||
ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ export class RdDTokenHud {
|
||||
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
|
||||
if (actor) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
await RdDTokenHud.addExtensionHudCombat(html, combatant, actor, token)
|
||||
await RdDTokenHud.addExtensionHudCombatV2(html, combatant, actor, token)
|
||||
}
|
||||
else {
|
||||
const actions = RdDCombatManager.listActionsActorCombatant(actor)
|
||||
@@ -47,17 +47,28 @@ export class RdDTokenHud {
|
||||
}
|
||||
}
|
||||
|
||||
static async addExtensionHudCombat(html, combatant, actor, token) {
|
||||
const actionsActor = actor.listActionsCombat();
|
||||
static async addExtensionHudCombatV2(html, combatant, actor, token) {
|
||||
const isPossession = actor.listActionsPossessions().length > 0;
|
||||
const actionsCombat = isPossession ? [] : actor.listAttaques()
|
||||
const ajustements = combatant?.initiative ?
|
||||
[
|
||||
{ label: 'Initiative +1', action: 'delta', value: 1 },
|
||||
{ label: 'Initiative -1', action: 'delta', value: -1 }
|
||||
] : []
|
||||
const autres = [{ label: "Autre action", action: 'autre' }]
|
||||
const actions = Misc.indexed(actionsActor.concat(ajustements).concat(autres))
|
||||
const actions = Misc.indexed([
|
||||
...actionsCombat,
|
||||
...ajustements,
|
||||
...autres
|
||||
])
|
||||
|
||||
const hudData = { combatant, token, actions };
|
||||
const hudData = {
|
||||
combatant,
|
||||
token,
|
||||
isPossession,
|
||||
isEntiteNonIncarnee: actor.isEntiteNonIncarnee(),
|
||||
actions,
|
||||
};
|
||||
const hud = $(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/hud-actor-combat.hbs', hudData))
|
||||
$(html).find('div.col.left').append(hud)
|
||||
|
||||
@@ -84,6 +95,7 @@ export class RdDTokenHud {
|
||||
}
|
||||
})
|
||||
list.find('.rdd-attaque-v2').click(event => combatant.actor.rollAttaque(token))
|
||||
list.find('.rdd-possession-v2').click(event => combatant.actor.rollPossession())
|
||||
}
|
||||
|
||||
static async addExtensionHudInit(html, combatant, actions) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
import { ExperienceLog } from "./actor/experience-log.js";
|
||||
import { RdDCoeur } from "./coeur/rdd-coeur.js";
|
||||
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js";
|
||||
import { ITEM_TYPES, RDD_CONFIG, SYSTEM_RDD } from "./constants.js";
|
||||
import { ACTOR_TYPES, ITEM_TYPES, RDD_CONFIG, SYSTEM_RDD } from "./constants.js";
|
||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
|
||||
@@ -26,6 +26,8 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Monnaie } from "./item-monnaie.js";
|
||||
import { ItemAction } from "./item/item-actions.js";
|
||||
import { Targets } from "./targets.js";
|
||||
import { DialogSelect } from "./dialog-select.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@@ -75,30 +77,27 @@ const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
|
||||
/* -------------------------------------------- */
|
||||
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const definitionsEncaissement = {
|
||||
"mortel": [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
|
||||
],
|
||||
"non-mortel": [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
|
||||
],
|
||||
"entiteincarnee": [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
|
||||
]
|
||||
};
|
||||
const TABLE_ENCAISSEMENT_MORTEL = [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
|
||||
]
|
||||
const TABLE_ENCAISSEMENT_NONMORTEL = [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
|
||||
]
|
||||
const TABLE_ENCAISSEMENT_ENTITE = [
|
||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
|
||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
|
||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 4 },
|
||||
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 6 },
|
||||
]
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDUtility {
|
||||
@@ -183,9 +182,14 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.hbs',
|
||||
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/queue-sheet.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-header.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-hautrevant.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-frequence.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-description.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-appreciable.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-bonmoment.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-carac.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-moral.hbs',
|
||||
// partial enums
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.hbs',
|
||||
@@ -235,9 +239,6 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/resolution-table.hbs',
|
||||
// Dialogs
|
||||
@@ -278,7 +279,7 @@ export class RdDUtility {
|
||||
|
||||
Handlebars.registerHelper('plusMoins', diff => parseInt(diff) ? (diff > 0 ? '+' : '') + Math.round(diff) : diff)
|
||||
Handlebars.registerHelper('fractionOneN', n => new Handlebars.SafeString(Misc.getFractionOneN(n)))
|
||||
|
||||
|
||||
// Handle v12 removal of this helper
|
||||
Handlebars.registerHelper('select', function (selected, options) {
|
||||
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
|
||||
@@ -286,7 +287,7 @@ export class RdDUtility {
|
||||
const html = options.fn(this);
|
||||
return html.replace(rgx, "$& selected");
|
||||
})
|
||||
|
||||
|
||||
// logic
|
||||
Handlebars.registerHelper('either', (a, b) => a ?? b);
|
||||
// string manipulation
|
||||
@@ -299,7 +300,7 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
|
||||
Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
|
||||
Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
|
||||
|
||||
|
||||
// math
|
||||
Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
|
||||
Handlebars.registerHelper('math-abs', diff => Math.abs(parseInt(diff)))
|
||||
@@ -613,20 +614,20 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getLocalisation(type = 'personnage') {
|
||||
const loc = { result: await RdDDice.rollTotal("1d20")};
|
||||
const loc = { result: await RdDDice.rollTotal("1d20") };
|
||||
if (type == 'personnage') {
|
||||
if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
|
||||
else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
|
||||
else if (loc.result <= 9) loc.txt = "Ventre, reins";
|
||||
else if (loc.result <= 12) loc.txt = "Poitrine, dos";
|
||||
else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude";
|
||||
else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate";
|
||||
else if (loc.result == 19) loc.txt = "Tête";
|
||||
else if (loc.result == 20) loc.txt = "Tête (visage)";
|
||||
if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
|
||||
else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
|
||||
else if (loc.result <= 9) loc.txt = "Ventre, reins";
|
||||
else if (loc.result <= 12) loc.txt = "Poitrine, dos";
|
||||
else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude";
|
||||
else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate";
|
||||
else if (loc.result == 19) loc.txt = "Tête";
|
||||
else if (loc.result == 20) loc.txt = "Tête (visage)";
|
||||
} else {
|
||||
if (loc.result <= 7) loc.txt = "Jambes/Pattes";
|
||||
else if (loc.result <= 18) loc.txt = "Corps";
|
||||
else if (loc.result <= 20) loc.txt = "Tête";
|
||||
if (loc.result <= 7) loc.txt = "Jambes/Pattes";
|
||||
else if (loc.result <= 18) loc.txt = "Corps";
|
||||
else if (loc.result <= 20) loc.txt = "Tête";
|
||||
}
|
||||
return loc
|
||||
}
|
||||
@@ -671,13 +672,13 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async prepareEncaissement(actor, dmg, roll, armure) {
|
||||
static async prepareEncaissement(targetActor, dmg, roll, armure) {
|
||||
const jetTotal = roll.total + dmg.total - armure
|
||||
const encaissement = RdDUtility._selectEncaissement(jetTotal, dmg.mortalite);
|
||||
const over20 = Math.max(jetTotal - 20, 0);
|
||||
const encaissement = RdDUtility.$selectEncaissement(targetActor, jetTotal, dmg.mortalite)
|
||||
const over20 = Math.max(jetTotal - 20, 0)
|
||||
encaissement.dmg = dmg
|
||||
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
|
||||
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(actor.type)
|
||||
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type)
|
||||
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
|
||||
}
|
||||
else {
|
||||
@@ -693,15 +694,21 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _selectEncaissement(degats, mortalite) {
|
||||
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
|
||||
for (let encaissement of table) {
|
||||
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
|
||||
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
|
||||
return foundry.utils.duplicate(encaissement);
|
||||
}
|
||||
static $selectEncaissement(targetActor, degats, mortalite) {
|
||||
const table = RdDUtility.$getTableEncaissement(targetActor, mortalite)
|
||||
const encaissement = table.find(it => ((it.minimum ?? degats) <= degats && degats <= (it.maximum ?? degats)))
|
||||
return foundry.utils.duplicate(encaissement ?? table[0])
|
||||
}
|
||||
|
||||
static $getTableEncaissement(targetActor, mortalite) {
|
||||
if (targetActor.isEntite()) {
|
||||
return TABLE_ENCAISSEMENT_ENTITE
|
||||
}
|
||||
return foundry.utils.duplicate(table[0]);
|
||||
switch (mortalite) {
|
||||
case RDD_CONFIG.encaissement.nonmortel: return TABLE_ENCAISSEMENT_NONMORTEL
|
||||
case RDD_CONFIG.encaissement.entiteincarnee: return TABLE_ENCAISSEMENT_ENTITE
|
||||
}
|
||||
return TABLE_ENCAISSEMENT_MORTEL
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -773,8 +780,9 @@ export class RdDUtility {
|
||||
let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
|
||||
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
|
||||
if (actor) {
|
||||
actor.payerSols(sommeAPayer);
|
||||
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
||||
actor.payerSols(sommeAPayer)
|
||||
const chatMessage = RdDUtility.findChatMessageId(event.currentTarget)
|
||||
ChatUtility.remover(chatMessage)()
|
||||
}
|
||||
});
|
||||
$(html).on("click", '.rdd-world-content-link', async event => {
|
||||
@@ -843,6 +851,26 @@ export class RdDUtility {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static doWithSelectedActor(onSelected = () => { }, filter = actor => true) {
|
||||
const selected = RdDUtility.getSelectedActor()
|
||||
if (selected) {
|
||||
onSelected(selected)
|
||||
}
|
||||
else {
|
||||
const actors = game.actors
|
||||
.filter(it => it.getUserLevel(game.user) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
||||
.filter(it => ![ACTOR_TYPES.commerce, ACTOR_TYPES.vehicule].includes(it.type))
|
||||
.filter(filter)
|
||||
const selectData = {
|
||||
title: "Choisir un acteur",
|
||||
label: "Choisir un acteur",
|
||||
list: actors.map(it => Targets.extractActorData(it))
|
||||
};
|
||||
DialogSelect.select(selectData, it => onSelected(game.actors.get(it.id)))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static createMonnaie(name, cout, img = "", enc = 0.01) {
|
||||
let piece = {
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import { ChatUtility } from "../chat-utility.js"
|
||||
import RollDialog from "./roll-dialog.mjs"
|
||||
import RollDialog, { ALL_ROLL_TYPES } from "./roll-dialog.mjs"
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RdDCombat } from "../rdd-combat.js"
|
||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { RdDResolutionTable } from "../rdd-resolution-table.js"
|
||||
import { RDD_CONFIG, renderTemplate } from "../constants.js"
|
||||
import { EMPOIGNADE } from "../item/arme.js"
|
||||
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"
|
||||
import { RollTypeCuisine } from "./roll-type-cuisine.mjs"
|
||||
import { RollTypeMeditation } from "./roll-type-meditation.mjs"
|
||||
import { PART_DEFENSE } from "./roll-part-defense.mjs"
|
||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
||||
import { RdDRollTables } from "../rdd-rolltables.js"
|
||||
import { RdDEmpoignade } from "../rdd-empoignade.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { RollBasicParts } from "./roll-basic-parts.mjs"
|
||||
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
|
||||
import { Apprecier } from "../moral/apprecier.mjs"
|
||||
|
||||
export default class ChatRollResult {
|
||||
static init() {
|
||||
@@ -19,10 +27,15 @@ export default class ChatRollResult {
|
||||
static onReady() {
|
||||
foundry.applications.handlebars.loadTemplates({
|
||||
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
|
||||
'partial-apprecier': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-apprecier.hbs',
|
||||
'partial-appreciation': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appreciation.hbs',
|
||||
'partial-attaque-particuliere': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-attaque-particuliere.hbs',
|
||||
'partial-choix-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-choix-maladresse.hbs',
|
||||
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
|
||||
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
|
||||
'partial-infojet': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-infojet.hbs',
|
||||
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
|
||||
'partial-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-maladresse.hbs',
|
||||
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
|
||||
})
|
||||
}
|
||||
|
||||
@@ -38,35 +51,53 @@ export default class ChatRollResult {
|
||||
)
|
||||
const save = RollDialog.saveParts(roll, impacts)
|
||||
|
||||
ChatUtility.setMessageData(chatMessage, 'rollData', save)
|
||||
await this.saveChatMessageRoll(chatMessage, save)
|
||||
return chatMessage
|
||||
}
|
||||
|
||||
prepareDisplay(roll) {
|
||||
roll.done = roll.done ?? {}
|
||||
roll.show = roll.show ?? {}
|
||||
roll.show.chance = this.isAppelChancePossible(roll)
|
||||
roll.show.encaissement = this.isShowEncaissement(roll)
|
||||
roll.show.recul = this.getRecul(roll)
|
||||
//roll.show.particuliere = roll.show.particuliere ?? []
|
||||
roll.show.chance = this.$isAppelChancePossible(roll)
|
||||
roll.show.encaissement = this.$isShowEncaissement(roll)
|
||||
roll.show.recul = this.$getRecul(roll)
|
||||
roll.show.maladresse = this.$getMaladresse(roll)
|
||||
}
|
||||
|
||||
isAppelChancePossible(roll) {
|
||||
$isAppelChancePossible(roll) {
|
||||
return roll.active.actor.isPersonnage() &&
|
||||
roll.rolled.isEchec &&
|
||||
RdDCarac.isActionPhysique(roll.current.carac?.key)
|
||||
RdDCarac.isActionPhysique(roll.current.carac?.key) &&
|
||||
!roll.type.appreciation
|
||||
}
|
||||
|
||||
isShowEncaissement(roll) {
|
||||
$isShowEncaissement(roll) {
|
||||
switch (roll.type.current) {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
return roll.rolled.isEchec && roll.attackerRoll?.dmg.mortalite != EMPOIGNADE
|
||||
return roll.rolled.isEchec
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
$getMaladresse(roll) {
|
||||
switch (roll.type.current) {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
if (roll.rolled.isETotal) {
|
||||
const arme = roll.current[PART_DEFENSE].arme
|
||||
return arme ? 'avec-arme' : 'sans-arme'
|
||||
}
|
||||
break
|
||||
case ROLL_TYPE_ATTAQUE:
|
||||
if (roll.rolled.isETotal || (roll.rolled.isEchec && roll.active.surprise == 'demi')) {
|
||||
const arme = roll.current[PART_ATTAQUE].arme
|
||||
return arme.system.baseInit > 4 ? 'avec-arme' : 'sans-arme'
|
||||
}
|
||||
break
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
|
||||
$getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
|
||||
switch (roll.type.current) {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
{
|
||||
@@ -100,7 +131,7 @@ export default class ChatRollResult {
|
||||
}
|
||||
|
||||
async buildRollHtml(roll) {
|
||||
const template = `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${roll.type.current}.hbs`
|
||||
const template = ALL_ROLL_TYPES.find(it => it.code == roll.type.current).chatResultTemplate
|
||||
const html = await renderTemplate(template, roll)
|
||||
return await RdDTextEditor.enrichHTML(html, undefined, { showLink: false })
|
||||
}
|
||||
@@ -108,11 +139,17 @@ export default class ChatRollResult {
|
||||
async chatListeners(html) {
|
||||
$(html).on("click", '.appel-chance', event => this.onClickAppelChance(event))
|
||||
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
|
||||
$(html).on("click", '.button-defense', event => this.onClickDefense(event))
|
||||
$(html).on("click", '.button-defense-possession', event => this.onClickDefensePossession(event))
|
||||
$(html).on("click", '.marquer-point-possession', event => this.onClickMarquerPointPossession(event))
|
||||
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
|
||||
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
|
||||
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
|
||||
$(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event))
|
||||
|
||||
$(html).on("click", '.apprecier', event => this.onClickApprecier(event))
|
||||
$(html).on("click", '.monter-tmr-normale', event => this.onClickMonteeTMR(event, 'normal'))
|
||||
$(html).on("click", '.monter-tmr-rapide', event => this.onClickMonteeTMR(event, 'rapide'))
|
||||
$(html).on("click", '.tirer-maladresse', event => this.onClickTirerMaladresse(event))
|
||||
}
|
||||
|
||||
getCombat(roll) {
|
||||
@@ -120,46 +157,57 @@ export default class ChatRollResult {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.opponentId, roll.ids.opponentTokenId, roll.ids.actorTokenId)
|
||||
case ROLL_TYPE_ATTAQUE:
|
||||
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.actorId, roll.ids.actorTokenId, roll.ids.opponentId)
|
||||
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.actorId, roll.ids.actorTokenId, roll.ids.opponentTokenId)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
async saveChatMessageRoll(chatMessage, savedRoll) {
|
||||
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
|
||||
}
|
||||
|
||||
loadChatMessageRoll(chatMessage) {
|
||||
return ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
}
|
||||
|
||||
async updateChatMessage(chatMessage, savedRoll) {
|
||||
ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
|
||||
await this.saveChatMessageRoll(chatMessage, savedRoll)
|
||||
const copy = foundry.utils.duplicate(savedRoll)
|
||||
RollDialog.loadRollData(copy)
|
||||
savedRoll.dmg = copy.current.attaque?.dmg
|
||||
this.prepareDisplay(copy)
|
||||
chatMessage.update({ content: await this.buildRollHtml(copy) })
|
||||
chatMessage.render(true)
|
||||
}
|
||||
|
||||
onClickAppelChance(event) {
|
||||
event.preventDefault()
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const actor = game.actors.get(savedRoll.ids.actorId)
|
||||
actor.rollAppelChance(
|
||||
Misc.doIfOwner(actor, it => it.rollAppelChance(
|
||||
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
|
||||
() => this.onAppelChanceEchec(savedRoll, chatMessage))
|
||||
event.preventDefault()
|
||||
)
|
||||
}
|
||||
|
||||
onAppelChanceSuccess(savedRoll, chatMessage) {
|
||||
async onAppelChanceSuccess(savedRoll, chatMessage) {
|
||||
const reRoll = foundry.utils.duplicate(savedRoll)
|
||||
console.log('onAppelChanceSuccess savedRoll', savedRoll)
|
||||
reRoll.type.retry = true
|
||||
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
|
||||
await this.updateChatMessage(chatMessage, reRoll)
|
||||
const callbacks = [ChatUtility.remover(chatMessage)]
|
||||
|
||||
// TODO: annuler les effets
|
||||
switch (reRoll.type.current) {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
this.getCombat(reRoll)?.doRollDefense(reRoll, callbacks)
|
||||
break
|
||||
case ROLL_TYPE_ATTAQUE:
|
||||
// TODO
|
||||
this.getCombat(reRoll)?.doRollAttaque(reRoll, callbacks)
|
||||
break
|
||||
default: {
|
||||
RollDialog.create(reRoll, { callbacks: callbacks })
|
||||
await RollDialog.create(reRoll, { onRollDone: RollDialog.onRollDoneClose, callbacks })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,54 +218,127 @@ export default class ChatRollResult {
|
||||
}
|
||||
|
||||
onClickAppelDestinee(event) {
|
||||
event.preventDefault()
|
||||
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const actor = game.actors.get(savedRoll.ids.actorId)
|
||||
|
||||
actor.appelDestinee(async () => {
|
||||
Misc.doIfOwner(actor, it => it.appelDestinee(async () => {
|
||||
const reRoll = foundry.utils.duplicate(savedRoll)
|
||||
reRoll.type.retry = true
|
||||
RdDResolutionTable.significativeRequise(reRoll.rolled)
|
||||
await this.updateChatMessage(chatMessage, reRoll)
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
async onClickDefense(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
RollBasicParts.restore(savedRoll)
|
||||
const attackerRoll = savedRoll.attackerRoll
|
||||
RollDialog.loadRollData(attackerRoll)
|
||||
this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
|
||||
[ChatUtility.remover(chatMessage)]
|
||||
)
|
||||
}
|
||||
|
||||
async onClickDefensePossession(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
await RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage)
|
||||
}
|
||||
|
||||
async onClickMarquerPointPossession(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
RollBasicParts.restore(savedRoll)
|
||||
await RdDPossessionV2.onMarquerPointPossession(savedRoll)
|
||||
ChatUtility.remover(chatMessage)()
|
||||
}
|
||||
|
||||
async onClickEncaissement(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const isMessageDemande = ChatUtility.getMessageData(chatMessage, 'demande-defense')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const attaque = savedRoll.attackerRoll
|
||||
const defender = game.actors.get(savedRoll.ids.actorId)
|
||||
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
||||
const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined
|
||||
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
|
||||
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
|
||||
|
||||
savedRoll.done.encaissement = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
const defender = defenderToken?.actor ?? game.actors.get(savedRoll.ids.actorId)
|
||||
Misc.doIfOwner(defender, async defender => {
|
||||
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
|
||||
const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId)
|
||||
switch (attaque.dmg.mortalite) {
|
||||
case RDD_CONFIG.encaissement.empoignade:
|
||||
savedRoll.done = savedRoll.done ?? {}
|
||||
savedRoll.done.empoignade = await RdDEmpoignade.ajustementEmpoignade(attackerToken.actor, defenderToken.actor)
|
||||
break
|
||||
case RDD_CONFIG.encaissement.entiteincarnee:
|
||||
case RDD_CONFIG.encaissement.nonmortel:
|
||||
case RDD_CONFIG.encaissement.mortel:
|
||||
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
|
||||
break
|
||||
}
|
||||
if (isMessageDemande) {
|
||||
ChatUtility.remover(chatMessage)()
|
||||
} else {
|
||||
savedRoll.done.encaissement = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
async onClickRecul(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
// TODO: gestion sur token non liés?
|
||||
const defender = game.actors.get(savedRoll.ids.actorId)
|
||||
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
||||
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
|
||||
// const reculChoc = this.getReculChoc(savedRoll, defender, attacker)
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
Misc.doIfOwner(defender, async defender => {
|
||||
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
||||
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
})
|
||||
}
|
||||
|
||||
async onClickChoixParticuliere(event) {
|
||||
const choix = event.currentTarget.attributes['data-particuliere'].value
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
savedRoll.particuliere = choix
|
||||
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll, callbacks)
|
||||
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll)
|
||||
}
|
||||
|
||||
async onClickFaireGouter(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
if (!savedRoll.type.retry) {
|
||||
savedRoll.type.retry = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
await new RollTypeCuisine().onFaireGouter(savedRoll)
|
||||
}
|
||||
}
|
||||
async onClickApprecier(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
await Apprecier.onClickApprecier(savedRoll)
|
||||
}
|
||||
|
||||
async onClickMonteeTMR(event, mode) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
|
||||
savedRoll.done.meditation = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
}
|
||||
|
||||
async onClickTirerMaladresse(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const typeMaladresse = event.currentTarget.attributes['data-maladresse'].value
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false })
|
||||
savedRoll.type.retry = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export class RollBasicParts {
|
||||
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
|
||||
rollData.active = RollBasicParts.getTokenActor(rollData)
|
||||
rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
|
||||
if (rollData.type.opposed == undefined) {
|
||||
if (rollData.type && rollData.type.opposed == undefined) {
|
||||
rollData.type.opposed = rollData.opponent != null
|
||||
}
|
||||
}
|
||||
@@ -26,7 +26,7 @@ export class RollBasicParts {
|
||||
static loadSurprise(who, forceRequise) {
|
||||
if (who?.actor) {
|
||||
foundry.utils.mergeObject(who,
|
||||
StatusEffects.getActorEffetSurprise(who.actor, forceRequise),
|
||||
StatusEffects.getActorEffetSurprise(who.actor),
|
||||
{ overwrite: true, inPlace: true })
|
||||
}
|
||||
}
|
||||
@@ -46,21 +46,35 @@ export class RollBasicParts {
|
||||
type: rollData.type,
|
||||
ids: {
|
||||
sceneId: rollData.ids.sceneId,
|
||||
actorId: rollData.active.id,
|
||||
actorTokenId: rollData.active.tokenId,
|
||||
opponentId: isOpposed ? rollData.opponent.id : undefined,
|
||||
opponentTokenId: isOpposed ? rollData.opponent.tokenId : undefined,
|
||||
actorId: rollData.ids.actorId,
|
||||
actorTokenId: rollData.ids.actorTokenId,
|
||||
opponentId: isOpposed ? rollData.ids.opponentId : undefined,
|
||||
opponentTokenId: isOpposed ? rollData.ids.opponentTokenId : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static prepareDefense(attackerRoll) {
|
||||
if (!attackerRoll.passeArme) {
|
||||
attackerRoll.passeArme = foundry.utils.randomID(16);
|
||||
}
|
||||
return {
|
||||
ids: RollBasicParts.reverseIds(attackerRoll),
|
||||
active: attackerRoll.opponent,
|
||||
opponent: attackerRoll.active,
|
||||
attackerRoll: attackerRoll,
|
||||
passeArme: attackerRoll.passeArme,
|
||||
show: { encaissement: true }
|
||||
}
|
||||
}
|
||||
|
||||
static reverseIds(rollData) {
|
||||
return {
|
||||
sceneId: rollData.ids.sceneId,
|
||||
actorId: rollData.ids.opponentId,
|
||||
actorTokenId: rollData.ids.opponentTokenId,
|
||||
opponentId: rollData.ids.actorId,
|
||||
opponentTokenId: rollData.actorTokenId
|
||||
opponentTokenId: rollData.ids.actorTokenId
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
export const ROLL_TYPE_ATTAQUE = 'attaque'
|
||||
export const ROLL_TYPE_POSSESSION = 'possession'
|
||||
export const ROLL_TYPE_COMP = 'comp'
|
||||
export const ROLL_TYPE_CUISINE = 'cuisine'
|
||||
export const ROLL_TYPE_DEFENSE = 'defense'
|
||||
@@ -12,8 +13,7 @@ export const ROLL_TYPE_TACHE = 'tache'
|
||||
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
|
||||
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
|
||||
export const DEMIREVE_ROLL_TYPES = [ROLL_TYPE_SORT]
|
||||
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_JEU]
|
||||
export const ALL_ROLL_TYPES = [...DEFAULT_ROLL_TYPES, ...COMBAT_ROLL_TYPES, ...DEMIREVE_ROLL_TYPES]
|
||||
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_JEU]
|
||||
|
||||
|
||||
export const DIFF = {
|
||||
@@ -28,8 +28,8 @@ export const DIFF = {
|
||||
export const DIFFS = {
|
||||
[DIFF.LIBRE]: { key: DIFF.LIBRE, label: "Difficulté libre", libre: true, visible: true, max: 0 },
|
||||
[DIFF.ATTAQUE]: { key: DIFF.ATTAQUE, label: "Difficulté d'attaque", libre: true, visible: true, max: 0 },
|
||||
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Diffficulté imposée", libre: false, visible: true, max: 0 },
|
||||
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Diffficulté défense", libre: false, visible: true, max: 0 },
|
||||
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Difficulté imposée", libre: false, visible: true, max: 20 },
|
||||
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Difficulté défense", libre: false, visible: true, max: 0 },
|
||||
[DIFF.DEFAUT]: { key: DIFF.DEFAUT, label: "Difficulté", libre: true, visible: true, max: 5 },
|
||||
[DIFF.AUCUN]: { key: DIFF.AUCUN, label: "", libre: false, visible: false, max: 0 },
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import { RdDItemArme } from "../item/arme.js";
|
||||
import { RdDBonus } from "../rdd-bonus.js";
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
|
||||
import { CARACS } from "../rdd-carac.js";
|
||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE } from "./roll-constants.mjs";
|
||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_OEUVRE } from "./roll-constants.mjs";
|
||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -27,7 +27,8 @@ export class RollDialogAdapter {
|
||||
RollDialogAdapter.setRollDataRolled(rollData, rolled, rollTitle)
|
||||
RollDialogAdapter.adjustRollDataForV1(rollData)
|
||||
RollDialogAdapter.adjustAttaqueParticuliere(rollData)
|
||||
|
||||
RollDialogAdapter.adjustAttaqueDmg(rollData)
|
||||
RollDialogAdapter.adjustDemiSurprise(rollData)
|
||||
return rolled
|
||||
}
|
||||
|
||||
@@ -76,7 +77,7 @@ export class RollDialogAdapter {
|
||||
const compKey = rollData.current.comp?.key
|
||||
if (compKey) {
|
||||
rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp
|
||||
rollData.jetResistance = rollData.type.jetResistance
|
||||
rollData.jetResistance = rollData.type.resistance
|
||||
}
|
||||
if (rollData.type.current == ROLL_TYPE_OEUVRE) {
|
||||
const oeuvreKey = rollData.current.oeuvre?.key
|
||||
@@ -95,16 +96,27 @@ export class RollDialogAdapter {
|
||||
rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rollData.selectedCarac.value, 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.ajustements = rollData.ajustements.map(a => { return { label: a.label, value: a.value } })
|
||||
}
|
||||
|
||||
static adjustDemiSurprise(rollData) {
|
||||
if (rollData.active.surprise == 'demi' && rollData.rolled.isPart) {
|
||||
RdDResolutionTable.replaceParticuliereDemiSurprise(rollData.rolled)
|
||||
}
|
||||
}
|
||||
|
||||
static adjustAttaqueDmg(rollData) {
|
||||
switch (rollData.type.current) {
|
||||
case ROLL_TYPE_ATTAQUE:
|
||||
rollData.dmg = RdDBonus.dmgRollV2(rollData, rollData.current.attaque)
|
||||
break
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
rollData.dmg = RdDBonus.dmgRollV2(rollData.attackerRoll, rollData.attackerRoll.current.attaque)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static adjustAttaqueParticuliere(rollData) {
|
||||
if (rollData.type.current != ROLL_TYPE_ATTAQUE || !rollData.rolled.isPart) {
|
||||
return
|
||||
@@ -112,7 +124,7 @@ export class RollDialogAdapter {
|
||||
|
||||
const attaque = rollData.current.attaque;
|
||||
const choix = []
|
||||
const isEmpoignade = attaque.dmg.mortalite == 'empoignade';
|
||||
const isEmpoignade = attaque.dmg.isEmpoignade
|
||||
const isCharge = attaque.tactique == 'charge'
|
||||
/* TODO: cas de créatures faisant des lancers, Glou, Glipzouk */
|
||||
const isMeleeDiffNegative = (attaque.comp.type == ITEM_TYPES.competencecreature || rollData.current.carac.key == CARACS.MELEE)
|
||||
@@ -153,8 +165,6 @@ export class RollDialogAdapter {
|
||||
comp: attackerRoll.competence,
|
||||
main: RdDItemArme.getMainAttaque(attackerRoll.competence),
|
||||
equipe: attackerRoll.arme.system.equipe,
|
||||
// carac: { key: caracCode, value: caracValue },
|
||||
// dommagesArme: dommagesArme,
|
||||
diff: attackerRoll.diffLibre,
|
||||
particuliere: attackerRoll.particuliere,
|
||||
tactique: RdDBonus.find(attackerRoll.tactique),
|
||||
|
||||
@@ -44,14 +44,22 @@ import { RollTypeCuisine } from "./roll-type-cuisine.mjs";
|
||||
import { RollPartCuisine } from "./roll-part-cuisine.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js";
|
||||
import { ActorImpacts } from "../technical/actor-impacts.mjs";
|
||||
import { RollPartEmpoignade } from "./roll-part-empoignade.mjs";
|
||||
import { RollPartEmpoignadeTaille } from "./roll-part-empoignade-taille.mjs";
|
||||
import { RollPartEcailles } from "./roll-part-ecailles.mjs";
|
||||
import { RollPartResistance } from "./roll-part-resistance.mjs";
|
||||
import { RollTypePossession } from "./roll-type-possession.mjs";
|
||||
import { RollPartPossession } from "./roll-part-possession.mjs";
|
||||
import { RollPartApprecier } from "./roll-part-apprecier.mjs";
|
||||
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
|
||||
|
||||
const ALL_ROLL_TYPES = [
|
||||
export const ALL_ROLL_TYPES = [
|
||||
new RollTypeComp(),
|
||||
new RollTypeTache(),
|
||||
new RollTypeAttaque(),
|
||||
new RollTypePossession(),
|
||||
new RollTypeDefense(),
|
||||
new RollTypeSort(),
|
||||
new RollTypeMeditation(),
|
||||
@@ -66,11 +74,14 @@ const ROLL_PARTS = [
|
||||
new RollPartActor(),
|
||||
new RollPartAction(),
|
||||
new RollPartOpponent(),
|
||||
new RollPartResistance(),
|
||||
new RollPartCarac(),
|
||||
new RollPartComp(),
|
||||
|
||||
new RollPartDiff(),
|
||||
new RollPartApprecier(),
|
||||
new RollPartAttaque(),
|
||||
new RollPartPossession(),
|
||||
new RollPartDefense(),
|
||||
new RollPartMeditation(),
|
||||
new RollPartSort(),
|
||||
@@ -81,10 +92,13 @@ const ROLL_PARTS = [
|
||||
|
||||
new RollPartSign(),
|
||||
|
||||
new RollPartEcailles(),
|
||||
new RollPartEtat(),
|
||||
new RollPartConditions(),
|
||||
new RollPartEthylisme(),
|
||||
new RollPartMalusArmure(),
|
||||
new RollPartEmpoignadeTaille(),
|
||||
new RollPartEmpoignade(),
|
||||
new RollPartEncTotal(),
|
||||
new RollPartSurEnc(),
|
||||
new RollPartAppelMoral(),
|
||||
@@ -173,18 +187,25 @@ const ROLL_PARTS = [
|
||||
/* -------------------------------------------- */
|
||||
export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2)
|
||||
{
|
||||
static onRollDoneDoNothing(dialog) {
|
||||
dialog.render()
|
||||
}
|
||||
static onRollDoneClose(dialog) {
|
||||
if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
|
||||
static onCloseDoNothing() { }
|
||||
|
||||
static onRollDoneDoNothing(dialog, roll) {
|
||||
if (roll.type.retry) {
|
||||
dialog.close()
|
||||
}
|
||||
else {
|
||||
dialog.render()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static init() {
|
||||
static onRollDoneClose(dialog, roll) {
|
||||
if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST)) {
|
||||
dialog.close()
|
||||
}
|
||||
}
|
||||
|
||||
static init() { }
|
||||
|
||||
static onReady() {
|
||||
|
||||
foundry.applications.handlebars.loadTemplates({
|
||||
@@ -198,7 +219,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
|
||||
ChatRollResult.onReady()
|
||||
|
||||
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.template))
|
||||
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.chatResultTemplate))
|
||||
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
|
||||
ROLL_PARTS.forEach(p => p.onReady())
|
||||
|
||||
@@ -234,8 +255,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
|
||||
|
||||
static async create(rollData, rollOptions = {}) {
|
||||
const rollDialog = new RollDialog(rollData, rollOptions)
|
||||
rollDialog.render(true)
|
||||
rollData = RollDialog.$prepareRollData(rollData)
|
||||
return Misc.doIfOwner(rollData.active.actor,
|
||||
actor => {
|
||||
const rollDialog = new RollDialog(rollData, rollOptions)
|
||||
rollDialog.render(true)
|
||||
return rollDialog
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
static get PARTS() {
|
||||
@@ -293,15 +320,33 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
return rollData
|
||||
}
|
||||
|
||||
static saveParts(rollData, impacts) {
|
||||
static saveParts(rollData, impacts = undefined) {
|
||||
if (rollData == undefined) {
|
||||
return undefined
|
||||
}
|
||||
|
||||
function saveBasics(from, to) {
|
||||
if (from) {
|
||||
to.passeArme = from.passeArme
|
||||
to.rolled = from.rolled
|
||||
to.particuliere = from.particuliere
|
||||
to.result = from.result
|
||||
to.done = from.done ?? {}
|
||||
to.dmg = from.dmg
|
||||
if (from.attackerRoll) {
|
||||
to.attackerRoll = {}
|
||||
saveBasics(from.attackerRoll, to.attackerRoll)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const target = RollBasicParts.initFrom(rollData)
|
||||
ROLL_PARTS.filter(p => p.isActive(rollData))
|
||||
.forEach(p => p.storeClean(rollData, target))
|
||||
target.attackerRoll = rollData.attackerRoll
|
||||
target.rolled = rollData.rolled
|
||||
target.result = rollData.result
|
||||
target.done = rollData.done ?? {}
|
||||
target.dmg = rollData.dmg
|
||||
if (rollData.current) {
|
||||
// stockage de current
|
||||
ROLL_PARTS.filter(p => p.isActive(rollData))
|
||||
.forEach(p => p.storeClean(rollData, target))
|
||||
}
|
||||
saveBasics(rollData, target)
|
||||
if (impacts) {
|
||||
target.reverse = {
|
||||
active: impacts.active?.reverseImpacts(),
|
||||
@@ -309,30 +354,48 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
}
|
||||
return target
|
||||
|
||||
}
|
||||
|
||||
constructor(rollData, rollOptions) {
|
||||
super()
|
||||
|
||||
this.rollData = RollDialog.$prepareRollData(rollData)
|
||||
this.hooks = []
|
||||
this.rollData = rollData
|
||||
this.rollOptions = {
|
||||
callbacks: [
|
||||
async r => await r.active.actor.appliquerAjoutExperience(r),
|
||||
async r => await r.active.actor.appliquerAppelMoral(r),
|
||||
...(rollOptions.callbacks ?? [])
|
||||
],
|
||||
customChatMessage: rollOptions.customChatMessage,
|
||||
onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing
|
||||
onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing,
|
||||
onClose: rollOptions.onClose ?? RollDialog.onCloseDoNothing
|
||||
}
|
||||
this.chatRollResult = new ChatRollResult();
|
||||
this.chatRollResult = new ChatRollResult()
|
||||
this.selectType()
|
||||
this.registerHooks(rollData)
|
||||
}
|
||||
|
||||
registerHooks(rollData) {
|
||||
ROLL_PARTS.filter(p => p.isValid(rollData))
|
||||
.forEach(p => p.getHooks(this).forEach(h => {
|
||||
const hook = h.hook;
|
||||
const id = Hooks.on(hook, h.fn)
|
||||
this.hooks.push({ hook, id })
|
||||
}))
|
||||
}
|
||||
|
||||
unregisterHooks() {
|
||||
this.hooks.forEach(h => Hooks.off(h.hook, h.id))
|
||||
}
|
||||
|
||||
|
||||
selectType() {
|
||||
const selectedType = this.getSelectedType();
|
||||
this.rollData.type.label = selectedType.title(this.rollData)
|
||||
const selectedType = this.getSelectedType()
|
||||
selectedType.prepare(this.rollData)
|
||||
selectedType.setRollDataType(this.rollData)
|
||||
selectedType.onSelect(this.rollData)
|
||||
this.rollData.type.label = selectedType.title(this.rollData)
|
||||
|
||||
ROLL_PARTS.find(it => it.code == PART_CARAC).filterCaracs(this.rollData)
|
||||
ROLL_PARTS.find(it => it.code == PART_COMP).filterComps(this.rollData)
|
||||
@@ -383,7 +446,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
return RollDialog.getActiveParts(rollData)
|
||||
.map(p => p.getAjustements(rollData))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.sort((a, b) => a.diff == undefined ? 1 : b.diff == undefined ? -1 : 0)
|
||||
.sort((a, b) => a.value == undefined ? 1 : b.value == undefined ? -1 : 0)
|
||||
}
|
||||
|
||||
async buildHTMLTable(carac, diff) {
|
||||
@@ -405,7 +468,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
|
||||
visibleRollParts.forEach(p => p.prepareContext(rollData))
|
||||
|
||||
RollDialog.calculAjustements(rollData)
|
||||
RollDialog.calculAjustement(rollData)
|
||||
|
||||
const templates = RollDialog.getActiveParts(rollData).map(p => p.toTemplateData())
|
||||
const context = await super._prepareContext()
|
||||
@@ -427,12 +490,11 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
}
|
||||
}
|
||||
|
||||
static calculAjustements(rollData) {
|
||||
static calculAjustement(rollData) {
|
||||
rollData.ajustements = RollDialog.getAjustements(rollData)
|
||||
rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
|
||||
rollData.current.totaldiff = rollData.ajustements
|
||||
.map(adj => adj.diff)
|
||||
.filter(d => d != undefined)
|
||||
.filter(a => a.value != undefined)
|
||||
.map(a => a.value)
|
||||
.reduce(Misc.sum(), 0)
|
||||
}
|
||||
|
||||
@@ -440,20 +502,25 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
return ALL_ROLL_TYPES.find(m => m.code == this.rollData.type.current)
|
||||
}
|
||||
|
||||
async close(options) {
|
||||
if (this.rollOptions.onClose) {
|
||||
this.rollOptions.onClose()
|
||||
}
|
||||
this.unregisterHooks()
|
||||
return await super.close(options)
|
||||
}
|
||||
|
||||
async roll() {
|
||||
|
||||
const roll = RollDialog.saveParts(this.rollData)
|
||||
this.loadRollData(roll)
|
||||
RollDialog.loadRollData(roll)
|
||||
const selectedRollType = this.getSelectedType(roll);
|
||||
selectedRollType.onSelect(roll)
|
||||
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
|
||||
roll.choix = {}
|
||||
roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll))
|
||||
|
||||
const impacts = {
|
||||
active: new ActorImpacts(roll.active),
|
||||
opponent: roll.opponent ? new ActorImpacts(roll.opponent) : undefined
|
||||
}
|
||||
const impacts = new ActorImpacts(roll.active)
|
||||
|
||||
roll.result = selectedRollType.getResult(roll, impacts)
|
||||
|
||||
@@ -465,17 +532,17 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
|
||||
await Promise.all(callbacks.map(async callback => await callback(roll)))
|
||||
|
||||
await impacts.active?.applyImpacts()
|
||||
await impacts.opponent?.applyImpacts()
|
||||
await impacts.applyImpacts()
|
||||
selectedRollType.onApplyImpacts(roll, impacts)
|
||||
await this.chatRollResult.display(roll, impacts)
|
||||
this.rollOptions.onRollDone(this)
|
||||
this.rollOptions.onRollDone(this, roll)
|
||||
}
|
||||
|
||||
loadRollData(roll) {
|
||||
static loadRollData(roll) {
|
||||
RollDialog.$prepareRollData(roll)
|
||||
RollDialog.calculAjustements(roll)
|
||||
RollDialog.calculAjustement(roll)
|
||||
roll.v2 = true
|
||||
return roll
|
||||
}
|
||||
|
||||
async defaultCallback(roll, rolled) {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
|
||||
|
||||
export const PART_APPRECIER = "apprecier"
|
||||
|
||||
export class RollPartApprecier extends RollPart {
|
||||
|
||||
get code() { return PART_APPRECIER }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
restore(rollData) {
|
||||
this.setCurrent(rollData, this.getSaved(rollData))
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, this.getCurrent(rollData))
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
return rollData.type.appreciation
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.appreciation.jetQualite){
|
||||
return [{
|
||||
label: 'Qualité',
|
||||
value: Math.abs(current.qualite)
|
||||
}]
|
||||
}
|
||||
return []
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
|
||||
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
export const PART_ASTROLOGIQUE = "astrologique"
|
||||
@@ -15,7 +16,7 @@ export class RollPartAstrologique extends RollPartCheckbox {
|
||||
}
|
||||
|
||||
isLancementRituel(rollData) {
|
||||
return false
|
||||
return rollData.type.current == ROLL_TYPE_SORT && rollData.current.sort?.sort?.system.isrituel
|
||||
}
|
||||
|
||||
isJetChance(rollData) {
|
||||
|
||||
@@ -1,15 +1,25 @@
|
||||
import { RDD_CONFIG } from "../constants.js"
|
||||
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
|
||||
import { RdDBonus } from "../rdd-bonus.js"
|
||||
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { RdDEmpoignade } from "../rdd-empoignade.js"
|
||||
import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP } from "./roll-constants.mjs"
|
||||
import RollDialog from "./roll-dialog.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { PART_DIFF } from "./roll-part-diff.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { PART_SIGN } from "./roll-part-sign.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_ATTAQUE = 'attaque'
|
||||
|
||||
const TACTIQUES = RdDBonus.tactiques.filter(it => it.isTactique)
|
||||
|
||||
const FILTER_ATTAQUE_EMPOIGNADE = attaque => attaque.arme.isEmpoignade()
|
||||
const FILTER_ATTAQUE_NON_EMPOIGNADE = attaque => !attaque.arme.isEmpoignade()
|
||||
const FILTER_ATTAQUE_EMPOIGNE = attaque => attaque.arme.isUtilisableEmpoigne() && ATTAQUE_TYPE_MELEE.includes(attaque.main)
|
||||
|
||||
export class RollPartAttaque extends RollPartSelect {
|
||||
|
||||
get code() { return PART_ATTAQUE }
|
||||
@@ -20,7 +30,8 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const attaques = rollData.active.actor.listAttaques()
|
||||
refs.attaques = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor))
|
||||
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor))
|
||||
this.filterAttaquesEmpoignade(rollData)
|
||||
refs.tactiques = TACTIQUES
|
||||
if (refs.attaques.length > 0) {
|
||||
const attaque = this.findAttaque(refs.attaques, this.getSaved(rollData))
|
||||
@@ -28,6 +39,10 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
}
|
||||
}
|
||||
|
||||
isAttaqueEmpoignade(it) {
|
||||
return it.arme.isEmpoignade()
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
super.store(rollData, targetData)
|
||||
this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg
|
||||
@@ -36,7 +51,7 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
restore(rollData) {
|
||||
const saved = this.getSaved(rollData)
|
||||
super.restore(rollData)
|
||||
if (saved.dmg) {
|
||||
if (saved.dmg != undefined) {
|
||||
this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg
|
||||
}
|
||||
}
|
||||
@@ -50,14 +65,6 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
choices(refs) { return refs.attaques }
|
||||
|
||||
static $extractAttaque(attaque, actor) {
|
||||
// const extracted = foundry.utils.mergeObject({
|
||||
// key: `${attaque.action}::${attaque.label}`,
|
||||
// tactique: TACTIQUES[0]
|
||||
// },
|
||||
// attaque
|
||||
// )
|
||||
// return extracted
|
||||
// extracted.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
|
||||
attaque.key = `${attaque.action}::${attaque.label}`
|
||||
attaque.tactique = TACTIQUES[0]
|
||||
attaque.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
|
||||
@@ -65,20 +72,28 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.filterAttaquesEmpoignade(rollData)
|
||||
const current = this.getCurrent(rollData)
|
||||
current.dmg = RdDBonus.dmgRollV2(rollData, current)
|
||||
}
|
||||
|
||||
filterAttaquesEmpoignade(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const isEmpoignade = RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
|
||||
refs.isEmpoignadeEnCours = RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor)
|
||||
const filterAttaques = isEmpoignade ?
|
||||
FILTER_ATTAQUE_EMPOIGNADE
|
||||
: refs.isEmpoignadeEnCours
|
||||
? FILTER_ATTAQUE_EMPOIGNE
|
||||
: FILTER_ATTAQUE_NON_EMPOIGNADE
|
||||
refs.attaques = refs.all.filter(filterAttaques)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const ajustements = []
|
||||
if (current.tactique) {
|
||||
ajustements.push({ label: current.tactique.label, diff: current.tactique.attaque })
|
||||
}
|
||||
if (rollData.opponent?.surprise) {
|
||||
ajustements.push({ label: rollData.opponent.surprise.label, diff: rollData.opponent.surprise.attaque })
|
||||
}
|
||||
return ajustements
|
||||
const tactique = current.tactique ? [{ label: current.tactique.label, value: current.tactique.attaque }] : []
|
||||
const surprise = rollData.opponent?.surprise ? [{ label: rollData.opponent.surprise.label, value: rollData.opponent.surprise.attaque }] : []
|
||||
return [...tactique, ...surprise]
|
||||
}
|
||||
|
||||
|
||||
@@ -90,6 +105,7 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
const selectAttaque = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-attaque"]`)
|
||||
const selectTactique = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tactique"]`)
|
||||
const checkMortalite = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="check-mortalite"]`)
|
||||
const utiliserDagueEmpoignade = rollDialog.element.querySelector(`roll-section[name="${this.code}"] a.utiliser-dague-empoignade`)
|
||||
const current = this.getCurrent(rollDialog.rollData)
|
||||
|
||||
selectAttaque.addEventListener("change", e => {
|
||||
@@ -107,9 +123,27 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
})
|
||||
|
||||
checkMortalite?.addEventListener("change", e => {
|
||||
current.dmg.mortalite = (e.currentTarget.checked ? 'mortel' : 'non-mortel')
|
||||
current.dmg.mortalite = (e.currentTarget.checked ? RDD_CONFIG.encaissement.mortel : RDD_CONFIG.encaissement.nonmortel)
|
||||
rollDialog.render()
|
||||
})
|
||||
utiliserDagueEmpoignade?.addEventListener("click", e => {
|
||||
e.preventDefault()
|
||||
const rollData = rollDialog.rollData
|
||||
this.utiliserDagueEmpoignade(rollData)
|
||||
})
|
||||
}
|
||||
|
||||
utiliserDagueEmpoignade(rollData) {
|
||||
RollDialog.create({
|
||||
ids: { actorId: rollData.ids.actorId, actorTokenId: rollData.ids.actorTokenId },
|
||||
type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP },
|
||||
selected: {
|
||||
carac: { key: CARACS.DEXTERITE, forced: true },
|
||||
comp: { key: 'Dague', forced: true },
|
||||
diff: { type: DIFF.IMPOSEE, value: -4 }
|
||||
}
|
||||
},
|
||||
{ onRollDone: RollDialog.onRollDoneClose })
|
||||
}
|
||||
|
||||
impactOtherPart(part, rollData) {
|
||||
@@ -123,7 +157,9 @@ export class RollPartAttaque extends RollPartSelect {
|
||||
part.setDiff(rollData, { type: DIFF.ATTAQUE, value: current.initialDiff })
|
||||
current.initialDiff = undefined
|
||||
}
|
||||
break
|
||||
}
|
||||
case PART_SIGN: return part.setArme(rollData, false, current.forceRequise)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
@@ -12,22 +13,34 @@ export class RollPartCarac extends RollPartSelect {
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.all = this.$getActorCaracs(rollData)
|
||||
const selected = this.getSelected(rollData)
|
||||
const actor = rollData.active.actor
|
||||
refs.all = [...this.$getActorCaracs(actor), ...this.$getCaracCompetenceCreature(actor)]
|
||||
if (selected.forced && selected.key) {
|
||||
refs.all = refs.all.filter(c => c.key == selected.key || Grammar.includesLowerCaseNoAccent(c.label, selected.key))
|
||||
}
|
||||
refs.caracs = refs.all
|
||||
this.$selectCarac(rollData)
|
||||
}
|
||||
|
||||
choices(refs) { return refs.caracs }
|
||||
|
||||
$getActorCaracs(rollData) {
|
||||
return Object.entries(rollData.active.actor.getCarac())
|
||||
$getActorCaracs(actor) {
|
||||
return Object.entries(actor.getCarac())
|
||||
.filter(([key, c]) => key != 'taille')
|
||||
/* TODO: filter by context */
|
||||
.map(([key, carac]) => {
|
||||
return RollPartCarac.$extractCarac(key, carac)
|
||||
})
|
||||
}
|
||||
|
||||
$getCaracCompetenceCreature(actor) {
|
||||
if (actor.isPersonnage()) {
|
||||
return []
|
||||
}
|
||||
return actor.getCompetences()
|
||||
.map(it => { return { key: it.name, label: it.name, value: parseInt(it.system.carac_value) } })
|
||||
}
|
||||
|
||||
static $extractCarac(key, carac) {
|
||||
return {
|
||||
key: key,
|
||||
@@ -40,7 +53,6 @@ export class RollPartCarac extends RollPartSelect {
|
||||
allowed = allowed.filter(it => it != undefined)
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.caracs = allowed.length > 0
|
||||
// ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.key)))
|
||||
? refs.all.filter(it => allowed.includes(it.key))
|
||||
: refs.all
|
||||
this.$selectCarac(rollData)
|
||||
|
||||
@@ -35,7 +35,7 @@ export class RollPartCheckbox extends RollPart {
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.checked) {
|
||||
return [{ label: this.getCheckboxLabelAjustement(rollData), diff: current.value }]
|
||||
return [{ label: this.getCheckboxLabelAjustement(rollData), value: current.value }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ export class RollPartCoeur extends RollPartSelect {
|
||||
if (current.key != '') {
|
||||
return [{
|
||||
label: "Coeur pour " + current.label,
|
||||
diff: current.value
|
||||
value: current.value
|
||||
}]
|
||||
}
|
||||
return []
|
||||
|
||||
@@ -18,12 +18,21 @@ export class RollPartComp extends RollPartSelect {
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const selected = this.getSelected(rollData)
|
||||
refs.all = this.$getActorComps(rollData)
|
||||
.filter(comp => !selected.forced ||
|
||||
(selected.key ?
|
||||
Grammar.includesLowerCaseNoAccent(comp.name, selected.key)
|
||||
: comp.key == '')
|
||||
)
|
||||
const all = this.$getActorComps(rollData)
|
||||
if (selected.forced) {
|
||||
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
|
||||
if (refs.all.length == 0) {
|
||||
if (selected.key.length > 0) {
|
||||
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
|
||||
}
|
||||
else {
|
||||
refs.all = all.filter(comp => comp == SANS_COMPETENCE)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
refs.all = all
|
||||
}
|
||||
refs.comps = refs.all
|
||||
this.$selectComp(rollData)
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export class RollPartConditions extends RollPart {
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.value != 0) {
|
||||
return [{ label: DESCR_CONDITIONS, diff: current.value }]
|
||||
return [{ label: DESCR_CONDITIONS, value: current.value }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
|
||||
import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js"
|
||||
import { RdDBonus } from "../rdd-bonus.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { StatusEffects } from "../settings/status-effects.js"
|
||||
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
@@ -18,7 +15,9 @@ export class RollPartDefense extends RollPartSelect {
|
||||
|
||||
get code() { return PART_DEFENSE }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) }
|
||||
|
||||
isValid(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
|
||||
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
|
||||
|
||||
static getDiffAttaque(attackerRoll) {
|
||||
// TODO: rollDataV2?
|
||||
@@ -30,13 +29,22 @@ export class RollPartDefense extends RollPartSelect {
|
||||
const attackerRoll = rollData.attackerRoll
|
||||
const defenseur = rollData.active.actor
|
||||
refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main)
|
||||
const esquives = refs.isDistance == ATTAQUE_TYPE.TIR ? [] : defenseur.getCompetencesEsquive()
|
||||
.map(it => RollPartDefense.$extractEsquive(it, defenseur))
|
||||
const isEmpoignade = attackerRoll.dmg.isEmpoignade
|
||||
const isEmpoignadeEnCours = isEmpoignade && defenseur.itemTypes[ITEM_TYPES.empoignade].find(it =>
|
||||
[it.system.empoigneurid, it.system.empoigneid].includes(rollData.ids.opponentId) &&
|
||||
it.system.pointsemp != 0)
|
||||
|
||||
const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
|
||||
.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
|
||||
const esquives = (refs.isDistance == ATTAQUE_TYPE.TIR || isEmpoignadeEnCours)
|
||||
? []
|
||||
: defenseur.getCompetencesEsquive()
|
||||
const parades = isEmpoignade
|
||||
? [RdDItemArme.empoignade(defenseur)]
|
||||
: defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
|
||||
|
||||
refs.defenses = [...esquives, ...parades].filter(it => it != undefined)
|
||||
refs.defenses = [
|
||||
...esquives.map(it => RollPartDefense.$extractEsquive(it, defenseur)),
|
||||
...parades.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
|
||||
]
|
||||
this.$selectDefense(rollData)
|
||||
}
|
||||
|
||||
@@ -104,7 +112,7 @@ export class RollPartDefense extends RollPartSelect {
|
||||
case PART_CARAC: return part.filterCaracs(rollData, [current.carac])
|
||||
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
|
||||
case PART_DIFF: return part.setDiff(rollData, this.getDiffDefense(rollData))
|
||||
case PART_SIGN: return part.setArmeDisparate(rollData, this.isArmeDisparate(rollData))
|
||||
case PART_SIGN: return part.setArme(rollData, this.isArmeDisparate(rollData), current.forceRequise)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
@@ -113,7 +121,7 @@ export class RollPartDefense extends RollPartSelect {
|
||||
isArmeDisparate(rollData) {
|
||||
const armeDefense = this.getCurrent(rollData).arme
|
||||
if (armeDefense) {
|
||||
const armeAttaque = rollData.attackerRoll?.arme
|
||||
const armeAttaque = rollData.attackerRoll?.current.attaque.arme
|
||||
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
|
||||
}
|
||||
return false
|
||||
@@ -126,7 +134,11 @@ export class RollPartDefense extends RollPartSelect {
|
||||
return { diff: 0, type: DIFF.LIBRE }
|
||||
}
|
||||
else {
|
||||
return { diff: rollData.attackerRoll.diff ?? 0, type: DIFF.DEFENSE }
|
||||
const attackerRoll = rollData.attackerRoll
|
||||
const diff = attackerRoll.v2
|
||||
? attackerRoll.selected.diff.value
|
||||
: attackerRoll.diff
|
||||
return { diff: diff ?? 0, type: DIFF.DEFENSE }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ export class RollPartDiff extends RollPart {
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
if (EXCLUDED_ROLL_TYPES.includes(rollData.type.current)) {
|
||||
if (EXCLUDED_ROLL_TYPES.includes(rollData.type.current) || rollData.type.appreciation) {
|
||||
return false
|
||||
}
|
||||
const current = this.getCurrent(rollData)
|
||||
@@ -66,7 +66,7 @@ export class RollPartDiff extends RollPart {
|
||||
const current = this.getCurrent(rollData)
|
||||
return [{
|
||||
label: current.label,
|
||||
diff: current.value
|
||||
value: current.value
|
||||
}]
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
import { RDD_CONFIG } from "../constants.js"
|
||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
import { PART_DEFENSE } from "./roll-part-defense.mjs"
|
||||
|
||||
const ECAILLES = "ecailles"
|
||||
|
||||
export class RollPartEcailles extends RollPartCheckbox {
|
||||
|
||||
get code() { return ECAILLES }
|
||||
|
||||
isValid(rollData) {
|
||||
return this.isRollType(rollData, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE)
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
return this.getEcailles(rollData) != 0
|
||||
|
||||
}
|
||||
|
||||
getEcailles(rollData) {
|
||||
const arme = this.getArme(rollData)
|
||||
return arme?.system.magique ? arme?.system.ecaille_efficacite : 0
|
||||
}
|
||||
|
||||
getArme(rollData) {
|
||||
return this.isRollType(rollData, ROLL_TYPE_ATTAQUE)
|
||||
? rollData.current[PART_ATTAQUE]?.arme
|
||||
: this.isRollType(rollData, ROLL_TYPE_DEFENSE)
|
||||
? rollData.current[PART_DEFENSE]?.arme
|
||||
: undefined
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.loadRefs(rollData)
|
||||
super.prepareContext(rollData)
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) {
|
||||
return this.getEcailles(rollData) > 0
|
||||
? `<img src="${RDD_CONFIG.icons.magique}">`
|
||||
: `<img src="${RDD_CONFIG.icons.armebrisee}">`
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) {
|
||||
return this.getEcailles(rollData) > 0
|
||||
? "Efficacité"
|
||||
: "Défauts"
|
||||
}
|
||||
|
||||
getCheckboxValue(rollData) { return this.getEcailles(rollData) }
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import { RDD_CONFIG } from "../constants.js"
|
||||
import { RdDEmpoignade } from "../rdd-empoignade.js"
|
||||
import { COMBAT_ROLL_TYPES } from "./roll-constants.mjs"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const EMPOIGNADE_TAILLE = "empoignade-taille"
|
||||
|
||||
export class RollPartEmpoignadeTaille extends RollPartCheckbox {
|
||||
|
||||
get code() { return EMPOIGNADE_TAILLE }
|
||||
|
||||
isValid(rollData) {
|
||||
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
return COMBAT_ROLL_TYPES.includes(rollData.type.current) &&
|
||||
RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor) &&
|
||||
this.getTailleDiff(rollData) != 0
|
||||
}
|
||||
|
||||
getTailleDiff(rollData) {
|
||||
const taille = rollData.active.actor.getTaille()
|
||||
const tailleOpponent = rollData.opponent.actor.getTaille()
|
||||
const diff = taille - tailleOpponent
|
||||
const diffTailleAbs = Math.max(0, Math.abs(diff) - 1)
|
||||
const signDiff = Math.sign(diff)
|
||||
return signDiff * diffTailleAbs
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.empoignade}">` }
|
||||
getCheckboxLabel(rollData) {
|
||||
return `Taille ${rollData.active.actor.getTaille()} vs ${rollData.opponent.actor.getTaille()} `
|
||||
}
|
||||
getCheckboxValue(rollData) {
|
||||
return this.getTailleDiff(rollData)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import { RDD_CONFIG } from "../constants.js"
|
||||
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
|
||||
import { RdDEmpoignade } from "../rdd-empoignade.js"
|
||||
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const EMPOIGNADE = "empoignade"
|
||||
|
||||
export class RollPartEmpoignade extends RollPartCheckbox {
|
||||
|
||||
get code() { return EMPOIGNADE }
|
||||
|
||||
isValid(rollData) {
|
||||
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.opponentId, rollData.ids.opponentTokenId) &&
|
||||
!RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
return rollData.type.current == ROLL_TYPE_ATTAQUE &&
|
||||
ATTAQUE_TYPE_MELEE.includes(rollData.current[PART_ATTAQUE].main) &&
|
||||
RdDEmpoignade.isCombatantEmpoignade(rollData.ids.opponentId, rollData.ids.opponentTokenId) &&
|
||||
!RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId) &&
|
||||
!RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor)
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.empoignade}">` }
|
||||
getCheckboxLabel(rollData) { return "vs. empoigneur" }
|
||||
getCheckboxValue(rollData) { return 4 }
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { RDD_CONFIG } from "../constants.js"
|
||||
import { RdDItemCompetence } from "../item-competence.js"
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
@@ -25,7 +26,7 @@ export class RollPartEncTotal extends RollPartCheckbox {
|
||||
})
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) { return '<i class="fa-solid fa-weight-hanging"></i>' }
|
||||
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.surenc}">` }
|
||||
getCheckboxLabel(rollData) { return "Enc. total" }
|
||||
getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() }
|
||||
}
|
||||
|
||||
@@ -81,7 +81,9 @@ export class RollPartJeu extends RollPartSelect {
|
||||
|
||||
$selectJeu(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
RollPartJeu.forceCompJeu(rollData)
|
||||
if (rollData.type.current == ROLL_TYPE_JEU) {
|
||||
RollPartJeu.forceCompJeu(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
static forceCompJeu(rollData) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { CARACS, RdDCarac } from "../rdd-carac.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js"
|
||||
import { TMRUtility } from "../tmr-utility.js"
|
||||
import { ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_CARAC, RollPartCarac } 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"
|
||||
@@ -34,8 +34,9 @@ export class RollPartMeditation extends RollPartSelect {
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.meditations = rollData.active.actor.itemTypes[ITEM_TYPES.meditation]
|
||||
.map(it => RollPartMeditation.$extractMeditation(it, rollData.active.actor))
|
||||
const actor = rollData.active.actor
|
||||
refs.meditations = actor.itemTypes[ITEM_TYPES.meditation]
|
||||
.map(it => RollPartMeditation.$extractMeditation(it, actor))
|
||||
|
||||
if (refs.meditations.length > 0) {
|
||||
this.$selectMeditation(rollData)
|
||||
@@ -72,9 +73,10 @@ export class RollPartMeditation extends RollPartSelect {
|
||||
}
|
||||
|
||||
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])]
|
||||
const malus = this.getMalusEchecs(rollData)
|
||||
const malusEchecs = malus == 0 ? [] : [{ label: "Méditation", value: malus }]
|
||||
const malusConditions = { label: "Conditions", value: this.getMalusConditions(rollData) }
|
||||
return [malusConditions, ...malusEchecs]
|
||||
}
|
||||
|
||||
$selectMeditation(rollData, key) {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
|
||||
import { ROLL_TYPE_POSSESSION } 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_POSSESSION = "possession"
|
||||
|
||||
export class RollPartPossession extends RollPartSelect {
|
||||
|
||||
/** TODO: remplacer selectOption par un sélecteur plus sympa (avec image de compétence, par exemple? */
|
||||
|
||||
get code() { return PART_POSSESSION }
|
||||
get name() { return 'Possession' }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_POSSESSION) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.all = this.$getActorConjurations(rollData)
|
||||
this.$selectPossession(rollData)
|
||||
}
|
||||
|
||||
|
||||
choices(refs) { return refs.all }
|
||||
|
||||
$getActorConjurations(rollData) {
|
||||
const competences = rollData.active.actor.getDraconicOuPossession()
|
||||
return competences.map(RollPartPossession.extractPossession)
|
||||
}
|
||||
|
||||
static extractPossession(comp) {
|
||||
return {
|
||||
key: comp.id ?? comp.name,
|
||||
label: `${comp.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key ? 'Possession' : 'Conjuration'} (${comp.name})`,
|
||||
value: comp.system.niveau,
|
||||
comp: comp
|
||||
}
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.$selectPossession(rollData)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const rollData = rollDialog.rollData
|
||||
const select = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-possession"]`)
|
||||
const button = rollDialog.element.querySelector(`roll-section[name="${this.code}"] button[name="creer-possession"]`)
|
||||
select?.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectPossession(rollData, selectOptions[index]?.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
button?.addEventListener("click", async e => {
|
||||
e.preventDefault()
|
||||
await RdDPossessionV2.createPossessionIfMissing(rollData.active, rollData.opponent)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
$selectPossession(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
impactOtherPart(part, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (part.code) {
|
||||
case PART_CARAC: return part.filterCaracs(rollData, [rollData.type.possession.isPersonnage ? CARACS.REVE_ACTUEL : CARACS.REVE])
|
||||
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
}
|
||||