Merge branch 'main' into feature/granular-action-outcomes
|
|
@ -1,5 +1,6 @@
|
||||||
[*]
|
[*]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
indent_style = spaces
|
indent_style = spaces
|
||||||
|
end_of_line = lf
|
||||||
[*.yml]
|
[*.yml]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
FOUNDRY_MAIN_PATH=/path/to/foundry/resources/app/main.js
|
FOUNDRY_MAIN_PATH=/path/to/foundry/resources/app/main.js
|
||||||
FOUNDRY_DATA_PATH=/path/to/foundry/data
|
FOUNDRY_DATA_PATH=/path/to/foundry/
|
||||||
13
.prettierrc
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"trailingComma": "none",
|
|
||||||
"tabWidth": 4,
|
|
||||||
"useTabs": false,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"quoteProps": "consistent",
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"arrowParens": "avoid",
|
|
||||||
"printWidth": 120,
|
|
||||||
"endOfLine": "lf",
|
|
||||||
"bracketSameLine": true
|
|
||||||
}
|
|
||||||
3
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"js/ts.preferGoToSourceDefinition": true
|
||||||
|
}
|
||||||
16
README.md
|
|
@ -38,11 +38,13 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
||||||
|
|
||||||
3. **Configure your Foundry paths:**
|
3. **Configure your Foundry paths:**
|
||||||
|
|
||||||
```bash
|
Copy `.env.example` to `.env` and set up the foundry path and data path. The foundry path must point to main.js, and the data path must point the folder containing the Data folder itself (but not the `Data` folder itself).
|
||||||
npm run setup:dev -- --foundry-path="/path/to/foundry/main.js" --data-path="/path/to/data"
|
|
||||||
```
|
|
||||||
|
|
||||||
4. **Start developing:**
|
4. **Setup symlinks:**
|
||||||
|
|
||||||
|
In a shell with elevated privilages, run `npm run createSymlink`. It will add a foundry folder for types, and add a symlink to the daggerheart folder into your foundry data.
|
||||||
|
|
||||||
|
5. **Start developing:**
|
||||||
```bash
|
```bash
|
||||||
npm start
|
npm start
|
||||||
```
|
```
|
||||||
|
|
@ -51,7 +53,7 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
||||||
|
|
||||||
- `npm start` - Start development with file watching and Foundry launching
|
- `npm start` - Start development with file watching and Foundry launching
|
||||||
- `npm run build` - One-time build
|
- `npm run build` - One-time build
|
||||||
- `npm run setup:dev -- --foundry-path="<path>" --data-path="<path>"` - Configure development environment
|
- `npm run createSymlink` - Setup types and output symlinks
|
||||||
|
|
||||||
### Notes
|
### Notes
|
||||||
|
|
||||||
|
|
@ -66,6 +68,10 @@ You can find the documentation here: https://github.com/Foundryborne/daggerheart
|
||||||
|
|
||||||
Looking to contribute to the project? Look no further, check out our [contributing guide](CONTRIBUTING.md), and keep the [Code of Conduct](coc.md) in mind when working on things.
|
Looking to contribute to the project? Look no further, check out our [contributing guide](CONTRIBUTING.md), and keep the [Code of Conduct](coc.md) in mind when working on things.
|
||||||
|
|
||||||
|
## AI Policy
|
||||||
|
|
||||||
|
The Foundryborne Daggerheart system does not make use of AI (generative or otherwise) for any area of its implementation. We expect all contributors to follow this same policy when contributing with a pull request; contributions made using AI will be rejected outright.
|
||||||
|
|
||||||
## Disclaimer:
|
## Disclaimer:
|
||||||
|
|
||||||
**Daggerheart System**
|
**Daggerheart System**
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M374 74.47c-7.1.26-10.8 6.79-4.3 15.89l24-3.41c-6.5-9.11-14.1-12.69-19.7-12.48zm-38 9.1c-3.5 0-6.6 1.01-9 2.73-7.1 5.1-7.6 16.8 7.9 28-8.9 15.9-29.8 45.8-60.2 43.2l32.1 9.8c-2.7 1.6-5.7 3.1-9.2 4.5C118.7 119.4 29.29 275.1 29.29 275.1c51.1 69.9 4.1 98.9 4.1 98.9l7.81 63h28.81l3.19-41s32.5-3 62.8-63.3c29 9.8 71 9.1 102.6 3.3l-4.1 7.1-37.4 11.1c31.2 2.8 58.5-2.3 78.7-8.5-3.4-15.1-4.5-31.5 3.5-52.8L307.2 437h25.9s-4.6-75 34.4-143.5c5-7.8 9.4-15.1 13.1-23.7l2 11.1-10.5 23.2s39-15.7 29.2-96c23 3.9 45.6 1.7 66.6-4.6 5.3-1.7 9.5-5.8 11.2-11 5-15.6 9.5-32.5 10.4-47.3l-9.7.8c-.2-15.3-21.2-13.1-14.9.8l-10.5.5-4.9-15.5s16.9-12.3 38.4-7.1c-.9-3.2-2.2-6-3.9-8.6-13.8-20.8-54.3-27.8-122.4-15.6-8-12.24-17.8-16.96-25.6-16.93zm49.9 33.83c12.4 1.4 21.9 4.3 30.2 9.6h-15.9c-1.6 4.8-7.5 8.4-14.5 8.4s-12.9-3.6-14.5-8.4h-15.5c4.2-3 15.3-9.7 30.2-9.6zm9.6 181.6c-15.2 30.3-34.5 33.8-34.5 33.8-13.4 37.7-10.4 71.8 1.8 103.9H385c-3.8-44.7-3.2-78.4 10.5-137.7zm-251.1 50.3L126.6 376l27.2 25.1 13.9 35.6h29.9l-20.1-81.8z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M374 74.47c-7.1.26-10.8 6.79-4.3 15.89l24-3.41c-6.5-9.11-14.1-12.69-19.7-12.48zm-38 9.1c-3.5 0-6.6 1.01-9 2.73-7.1 5.1-7.6 16.8 7.9 28-8.9 15.9-29.8 45.8-60.2 43.2l32.1 9.8c-2.7 1.6-5.7 3.1-9.2 4.5C118.7 119.4 29.29 275.1 29.29 275.1c51.1 69.9 4.1 98.9 4.1 98.9l7.81 63h28.81l3.19-41s32.5-3 62.8-63.3c29 9.8 71 9.1 102.6 3.3l-4.1 7.1-37.4 11.1c31.2 2.8 58.5-2.3 78.7-8.5-3.4-15.1-4.5-31.5 3.5-52.8L307.2 437h25.9s-4.6-75 34.4-143.5c5-7.8 9.4-15.1 13.1-23.7l2 11.1-10.5 23.2s39-15.7 29.2-96c23 3.9 45.6 1.7 66.6-4.6 5.3-1.7 9.5-5.8 11.2-11 5-15.6 9.5-32.5 10.4-47.3l-9.7.8c-.2-15.3-21.2-13.1-14.9.8l-10.5.5-4.9-15.5s16.9-12.3 38.4-7.1c-.9-3.2-2.2-6-3.9-8.6-13.8-20.8-54.3-27.8-122.4-15.6-8-12.24-17.8-16.96-25.6-16.93zm49.9 33.83c12.4 1.4 21.9 4.3 30.2 9.6h-15.9c-1.6 4.8-7.5 8.4-14.5 8.4s-12.9-3.6-14.5-8.4h-15.5c4.2-3 15.3-9.7 30.2-9.6zm9.6 181.6c-15.2 30.3-34.5 33.8-34.5 33.8-13.4 37.7-10.4 71.8 1.8 103.9H385c-3.8-44.7-3.2-78.4 10.5-137.7zm-251.1 50.3L126.6 376l27.2 25.1 13.9 35.6h29.9l-20.1-81.8z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><path d="M0 0h512v512H0z" fill="#000" fill-opacity="1"></path><g class="" transform="translate(0,0)" style=""><path d="M369.1 21.22c-19.2 0-36.2 10.63-47.9 26.47-11.7 15.84-18.6 37.03-18.6 60.31 0 21.1 5.7 40.5 15.5 55.7-5.7 1.6-11 3.9-15.9 6.6-10.2-8.5-22.6-13.6-35.9-13.6-19.3 0-36.3 10.6-48 26.4-4.7 6.4-8.6 13.6-11.6 21.5-4.8-2.4-9.9-4.3-15.5-5.6 9.4-15.1 14.8-34.1 14.8-54.7 0-23.2-6.9-44.43-18.6-60.27-11.7-15.84-28.7-26.5-47.9-26.5s-36.2 10.66-47.94 26.5C79.87 99.87 73 121.1 73 144.3c0 21.1 5.69 40.5 15.47 55.8-32.07 9.1-50.29 37.1-59.44 70-9.79 35.2-10.87 77.3-10.87 115.6v9.4h45.5l6.78 99.3h18.75l-7.28-106.5-4.1-80-18.65 1 3.47 67.5H36.97c.24-35.2 1.97-72.1 10.09-101.2 8.78-31.6 23.32-52.8 51.25-58.2l4.69-.1c10.3 8.8 22.9 14.2 36.5 14.2 14.1 0 26.9-5.7 37.4-15h4.6c7.8 1.2 14.4 3.5 20.1 6.7-1.2 6.6-1.9 13.5-1.9 20.6 0 21.1 5.7 40.5 15.5 55.8-32.1 9.1-50.3 37.2-59.4 70-9.8 35.2-10.9 77.3-10.9 115.6v9.4c21.7-.3 42.8.2 64.3.2l-.5-7.3-4.1-80-18.7.9 3.4 67.5h-25.6c.3-35.2 2-72.1 10.1-101.2 8.7-31.6 23.3-52.7 51.1-58.2l4.9-.1c10.3 8.8 22.8 14.2 36.4 14.2 14.1 0 27-5.7 37.5-15h4.4c15.4 2.4 26.1 8.9 34.5 18.6 8.5 9.7 14.5 23.2 18.5 39.2 7.3 29.5 7.7 66.9 7.7 102.5h-23.4l3.5-67.5-18.7-.9-4.2 82-.3 5.3c20.8 0 43.3-.3 61.9-.2v-9.4c0-38.1.5-80.6-8.4-116.3-4.4-17.8-11.3-34.1-22.4-47-9.7-11.1-22.7-19.4-38.8-23.4 9.4-15.1 14.7-34.1 14.7-54.7 0-22.5-6.4-43.2-17.5-58.8 3.9-1.8 8.1-3.1 12.7-4h4.7c10.3 8.8 22.9 14.2 36.5 14.2 14.1 0 27-5.8 37.4-15l4.6-.1c15.4 2.5 26 8.9 34.4 18.6 8.5 9.8 14.5 23.3 18.5 39.3 7.3 29.4 7.7 66.8 7.7 102.4h-23.4l3.5-67.4-18.7-1-4.1 79.7-8.6 143.1h18.7l8.2-135.7h43.1v-9.3c0-38.2.6-80.7-8.3-116.3-4.5-17.9-11.4-34.2-22.5-47-9.6-11.2-22.6-19.5-38.8-23.5 9.4-15.1 14.8-34 14.8-54.6 0-23.28-6.9-44.47-18.6-60.31-11.6-15.29-31.5-26.13-47.9-26.47zm0 18.69c12.4 0 23.9 6.69 32.9 18.87 9 12.19 14.9 29.67 14.9 49.22 0 19.5-5.9 37-14.9 49.2-9 12.2-20.5 18.9-32.9 18.9-12.3 0-23.9-6.7-32.9-18.9s-14.9-29.7-14.9-49.2c0-19.55 5.9-37.03 14.9-49.22 9-12.18 20.6-18.87 32.9-18.87zM139.5 76.22c12.4 0 23.9 6.72 32.9 18.9s14.9 29.68 14.9 49.18-5.9 37-14.9 49.2c-9 12.2-20.5 18.9-32.9 18.9-12.4 0-23.9-6.7-32.9-18.9-8.97-12.2-14.91-29.7-14.91-49.2 0-19.5 5.94-37 14.91-49.17 9-12.19 20.5-18.91 32.9-18.91zm197.8 22.34v18.64h22.5V98.56h-22.5zm41.1 0v18.64h22.5V98.56h-22.5zM107.7 134.9v18.7h22.5v-18.7h-22.5zm41.1 0v18.7h22.5v-18.7h-22.5zm117.5 40.4c12.3 0 23.8 6.7 32.8 18.9 9 12.2 15 29.7 15 49.2 0 19.6-6 37-15 49.2-9 12.2-20.5 18.9-32.8 18.9-12.4 0-24-6.7-33-18.9-8.9-12.2-14.9-29.6-14.9-49.2 0-19.5 6-37 14.9-49.2 9-12.2 20.6-18.9 33-18.9zM234.5 234v18.7h22.4V234zm41.1 0v18.7H298V234h-22.4z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><path d="M0 0h512v512H0z" fill="#000" fill-opacity="1"></path><g class="" transform="translate(0,0)" style=""><path d="M369.1 21.22c-19.2 0-36.2 10.63-47.9 26.47-11.7 15.84-18.6 37.03-18.6 60.31 0 21.1 5.7 40.5 15.5 55.7-5.7 1.6-11 3.9-15.9 6.6-10.2-8.5-22.6-13.6-35.9-13.6-19.3 0-36.3 10.6-48 26.4-4.7 6.4-8.6 13.6-11.6 21.5-4.8-2.4-9.9-4.3-15.5-5.6 9.4-15.1 14.8-34.1 14.8-54.7 0-23.2-6.9-44.43-18.6-60.27-11.7-15.84-28.7-26.5-47.9-26.5s-36.2 10.66-47.94 26.5C79.87 99.87 73 121.1 73 144.3c0 21.1 5.69 40.5 15.47 55.8-32.07 9.1-50.29 37.1-59.44 70-9.79 35.2-10.87 77.3-10.87 115.6v9.4h45.5l6.78 99.3h18.75l-7.28-106.5-4.1-80-18.65 1 3.47 67.5H36.97c.24-35.2 1.97-72.1 10.09-101.2 8.78-31.6 23.32-52.8 51.25-58.2l4.69-.1c10.3 8.8 22.9 14.2 36.5 14.2 14.1 0 26.9-5.7 37.4-15h4.6c7.8 1.2 14.4 3.5 20.1 6.7-1.2 6.6-1.9 13.5-1.9 20.6 0 21.1 5.7 40.5 15.5 55.8-32.1 9.1-50.3 37.2-59.4 70-9.8 35.2-10.9 77.3-10.9 115.6v9.4c21.7-.3 42.8.2 64.3.2l-.5-7.3-4.1-80-18.7.9 3.4 67.5h-25.6c.3-35.2 2-72.1 10.1-101.2 8.7-31.6 23.3-52.7 51.1-58.2l4.9-.1c10.3 8.8 22.8 14.2 36.4 14.2 14.1 0 27-5.7 37.5-15h4.4c15.4 2.4 26.1 8.9 34.5 18.6 8.5 9.7 14.5 23.2 18.5 39.2 7.3 29.5 7.7 66.9 7.7 102.5h-23.4l3.5-67.5-18.7-.9-4.2 82-.3 5.3c20.8 0 43.3-.3 61.9-.2v-9.4c0-38.1.5-80.6-8.4-116.3-4.4-17.8-11.3-34.1-22.4-47-9.7-11.1-22.7-19.4-38.8-23.4 9.4-15.1 14.7-34.1 14.7-54.7 0-22.5-6.4-43.2-17.5-58.8 3.9-1.8 8.1-3.1 12.7-4h4.7c10.3 8.8 22.9 14.2 36.5 14.2 14.1 0 27-5.8 37.4-15l4.6-.1c15.4 2.5 26 8.9 34.4 18.6 8.5 9.8 14.5 23.3 18.5 39.3 7.3 29.4 7.7 66.8 7.7 102.4h-23.4l3.5-67.4-18.7-1-4.1 79.7-8.6 143.1h18.7l8.2-135.7h43.1v-9.3c0-38.2.6-80.7-8.3-116.3-4.5-17.9-11.4-34.2-22.5-47-9.6-11.2-22.6-19.5-38.8-23.5 9.4-15.1 14.8-34 14.8-54.6 0-23.28-6.9-44.47-18.6-60.31-11.6-15.29-31.5-26.13-47.9-26.47zm0 18.69c12.4 0 23.9 6.69 32.9 18.87 9 12.19 14.9 29.67 14.9 49.22 0 19.5-5.9 37-14.9 49.2-9 12.2-20.5 18.9-32.9 18.9-12.3 0-23.9-6.7-32.9-18.9s-14.9-29.7-14.9-49.2c0-19.55 5.9-37.03 14.9-49.22 9-12.18 20.6-18.87 32.9-18.87zM139.5 76.22c12.4 0 23.9 6.72 32.9 18.9s14.9 29.68 14.9 49.18-5.9 37-14.9 49.2c-9 12.2-20.5 18.9-32.9 18.9-12.4 0-23.9-6.7-32.9-18.9-8.97-12.2-14.91-29.7-14.91-49.2 0-19.5 5.94-37 14.91-49.17 9-12.19 20.5-18.91 32.9-18.91zm197.8 22.34v18.64h22.5V98.56h-22.5zm41.1 0v18.64h22.5V98.56h-22.5zM107.7 134.9v18.7h22.5v-18.7h-22.5zm41.1 0v18.7h22.5v-18.7h-22.5zm117.5 40.4c12.3 0 23.8 6.7 32.8 18.9 9 12.2 15 29.7 15 49.2 0 19.6-6 37-15 49.2-9 12.2-20.5 18.9-32.8 18.9-12.4 0-24-6.7-33-18.9-8.9-12.2-14.9-29.6-14.9-49.2 0-19.5 6-37 14.9-49.2 9-12.2 20.6-18.9 33-18.9zM234.5 234v18.7h22.4V234zm41.1 0v18.7H298V234h-22.4z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M200.947 18.686c-6.98.087-14.64.774-22.85 1.9 27.57 20.468 51.098 45.25 67.594 70.527 1.66 0 3.312.012 4.958.047 18.066.39 35.487 2.906 53.217 7.2-15.695-28.457-29.935-50.19-47.45-63.22-13.817-10.278-30.063-16.168-52.52-16.454-.967-.013-1.95-.013-2.948 0zm-91.66 22.96c-.73-.002-1.46.006-2.195.022-14.045.31-29.36 3.92-46.86 11.13 56.18 18.807 106.985 50.468 133.907 83.585 18.377-5.13 29.44-14.72 36.454-28.817C195.84 78.18 168.118 56.19 140.65 46.96c-10.168-3.418-20.433-5.306-31.363-5.315zm-.203 52.786c-39.42 6.758-74.73 31.854-87.822 74.19v322.345h212.73C100.352 442.58 61.19 206.49 187.115 230.104c5.838-14.164 9.92-28.027 11.018-41.465l18.627 1.522c-1.684 20.592-8.828 40.49-18.033 59.943-.732 2.035-1.472 4.12-2.186 6.063 32.842 85.24 113.77 160.69 169.495 168.197.915.033 1.905-.002 2.953-.09 17.016 1.035 35.86-4.222 52.21-22.304l7.984-8.83-10.473-5.658c-6.507-3.515-14.29-7.094-18.167-10.925-1.938-1.916-2.793-3.47-3.074-5.194-.282-1.725-.13-4.227 2.23-8.578l10.673-19.656-21.484 6.222c-6.304 1.825-17.305-3.032-23.224-10.71-2.96-3.84-4.408-7.907-4.387-10.843.02-2.938.72-5.125 4.747-8.05l19.453-14.125-23.884-2.72c-9.974-1.137-16.37-6.658-19.17-12.294-2.802-5.634-2.312-10.084 1.375-13.31l12.204-10.677-15.358-5.205c-6.717-2.276-10.296-7.555-10.357-10.633-.028-1.373.238-2.666 1.843-4.476 10.93-2.39 21.258-.45 28.088 6.374 6.154 6.146 8.35 15.128 6.977 24.832 8.55-2.254 16.985-1.616 24.112 2.494 9.34 5.387 14.647 15.692 15.67 27.965 15.212-10.132 32.152-12.725 45.262-5.164 15.467 8.92 21.36 29.513 16.805 51.75 23.992-33.355 34.588-75.717 5.617-120.43-46.726-4.442-81.693-30.676-93.293-67.64-5.026-16.016-21.284-28.67-42-37.904l-.08.217c-29.74-10.823-55.575-17.35-82.604-18.733l.08.155c-2.294-.093-4.56-.16-6.762-.172-9.537 22.874-28.662 39.9-57.436 46.054l-5.906 1.262-3.576-4.864c-14.216-19.33-41.23-40.452-74.002-58.074zm156.215 65.26c27.927-.073 44.874 11.617 42.09 44.45-35.844 3.39-51.933-16.683-63.074-42.632 7.507-1.155 14.538-1.8 20.983-1.817zm48.407 66.363c3.708.07 7.14.994 10.014 2.812a35.171 35.171 0 0 0-4.16 3.543c-5.246 5.24-8.087 12.122-7.956 18.742.183 9.322 5.27 17.184 12.68 22.56-3.14 8.103-2.452 17.455 1.407 25.22 3.813 7.668 10.54 14.273 19.302 18.398-1.445 3.366-2.375 6.862-2.4 10.33-.062 8.407 3.38 16.042 8.273 22.39 6.792 8.81 16.862 15.936 28.026 17.91-.183 2.18-.204 4.333.133 6.407 1.05 6.444 4.515 11.66 8.38 15.48 3.41 3.37 7.19 5.892 10.798 7.993-6.345 4.792-12.414 7.056-18.618 7.79-6.515-7.937-9.71-19.084-9.41-31.454-11.767 6.177-24.21 7.156-34.12 1.44-14.668-8.46-19.393-29.036-13.187-50.33-11.336 2.77-22.13.92-29.187-6.132-8.875-8.865-9.535-23.626-3.094-37.95-3.676-.615-6.963-2.166-9.525-4.725-8.808-8.798-5.773-26.09 6.776-38.626 7.843-7.835 17.546-11.957 25.87-11.8z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M200.947 18.686c-6.98.087-14.64.774-22.85 1.9 27.57 20.468 51.098 45.25 67.594 70.527 1.66 0 3.312.012 4.958.047 18.066.39 35.487 2.906 53.217 7.2-15.695-28.457-29.935-50.19-47.45-63.22-13.817-10.278-30.063-16.168-52.52-16.454-.967-.013-1.95-.013-2.948 0zm-91.66 22.96c-.73-.002-1.46.006-2.195.022-14.045.31-29.36 3.92-46.86 11.13 56.18 18.807 106.985 50.468 133.907 83.585 18.377-5.13 29.44-14.72 36.454-28.817C195.84 78.18 168.118 56.19 140.65 46.96c-10.168-3.418-20.433-5.306-31.363-5.315zm-.203 52.786c-39.42 6.758-74.73 31.854-87.822 74.19v322.345h212.73C100.352 442.58 61.19 206.49 187.115 230.104c5.838-14.164 9.92-28.027 11.018-41.465l18.627 1.522c-1.684 20.592-8.828 40.49-18.033 59.943-.732 2.035-1.472 4.12-2.186 6.063 32.842 85.24 113.77 160.69 169.495 168.197.915.033 1.905-.002 2.953-.09 17.016 1.035 35.86-4.222 52.21-22.304l7.984-8.83-10.473-5.658c-6.507-3.515-14.29-7.094-18.167-10.925-1.938-1.916-2.793-3.47-3.074-5.194-.282-1.725-.13-4.227 2.23-8.578l10.673-19.656-21.484 6.222c-6.304 1.825-17.305-3.032-23.224-10.71-2.96-3.84-4.408-7.907-4.387-10.843.02-2.938.72-5.125 4.747-8.05l19.453-14.125-23.884-2.72c-9.974-1.137-16.37-6.658-19.17-12.294-2.802-5.634-2.312-10.084 1.375-13.31l12.204-10.677-15.358-5.205c-6.717-2.276-10.296-7.555-10.357-10.633-.028-1.373.238-2.666 1.843-4.476 10.93-2.39 21.258-.45 28.088 6.374 6.154 6.146 8.35 15.128 6.977 24.832 8.55-2.254 16.985-1.616 24.112 2.494 9.34 5.387 14.647 15.692 15.67 27.965 15.212-10.132 32.152-12.725 45.262-5.164 15.467 8.92 21.36 29.513 16.805 51.75 23.992-33.355 34.588-75.717 5.617-120.43-46.726-4.442-81.693-30.676-93.293-67.64-5.026-16.016-21.284-28.67-42-37.904l-.08.217c-29.74-10.823-55.575-17.35-82.604-18.733l.08.155c-2.294-.093-4.56-.16-6.762-.172-9.537 22.874-28.662 39.9-57.436 46.054l-5.906 1.262-3.576-4.864c-14.216-19.33-41.23-40.452-74.002-58.074zm156.215 65.26c27.927-.073 44.874 11.617 42.09 44.45-35.844 3.39-51.933-16.683-63.074-42.632 7.507-1.155 14.538-1.8 20.983-1.817zm48.407 66.363c3.708.07 7.14.994 10.014 2.812a35.171 35.171 0 0 0-4.16 3.543c-5.246 5.24-8.087 12.122-7.956 18.742.183 9.322 5.27 17.184 12.68 22.56-3.14 8.103-2.452 17.455 1.407 25.22 3.813 7.668 10.54 14.273 19.302 18.398-1.445 3.366-2.375 6.862-2.4 10.33-.062 8.407 3.38 16.042 8.273 22.39 6.792 8.81 16.862 15.936 28.026 17.91-.183 2.18-.204 4.333.133 6.407 1.05 6.444 4.515 11.66 8.38 15.48 3.41 3.37 7.19 5.892 10.798 7.993-6.345 4.792-12.414 7.056-18.618 7.79-6.515-7.937-9.71-19.084-9.41-31.454-11.767 6.177-24.21 7.156-34.12 1.44-14.668-8.46-19.393-29.036-13.187-50.33-11.336 2.77-22.13.92-29.187-6.132-8.875-8.865-9.535-23.626-3.094-37.95-3.676-.615-6.963-2.166-9.525-4.725-8.808-8.798-5.773-26.09 6.776-38.626 7.843-7.835 17.546-11.957 25.87-11.8z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.8 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><path d="M0 0h512v512H0z" fill="#000" fill-opacity="1"></path><g class="" transform="translate(0,0)" style=""><path d="M418.813 30.625c-21.178 26.27-49.712 50.982-84.125 70.844-36.778 21.225-75.064 33.62-110.313 38.06a310.317 310.317 0 0 0 6.813 18.25c16.01.277 29.366-.434 36.406-1.5l9.47-1.53 8.436-1.28.22 10.186a307.48 307.48 0 0 1-1.095 18.72l56.625 8.843c.86-.095 1.713-.15 2.563-.157 11.188-.114 21.44 7.29 24.468 18.593.657 2.448.922 4.903.845 7.313 5.972-2.075 11.753-4.305 17.28-6.72l9.595-4.188 2.313 10.22a340.211 340.211 0 0 1 7.375 48.062C438.29 247.836 468.438 225.71 493 197.5c-3.22-36.73-16.154-78.04-39.125-117.813a290.509 290.509 0 0 0-2.22-3.78l-27.56 71.374c5.154.762 10.123 3.158 14.092 7.126 9.81 9.807 9.813 25.69 0 35.5-9.812 9.81-25.722 9.807-35.53 0-8.86-8.858-9.69-22.68-2.532-32.5l38.938-100.844a322.02 322.02 0 0 0-20.25-25.937zM51.842 118.72c-8.46 17.373-15.76 36.198-21.187 56.436-14.108 52.617-13.96 103.682-2.812 143.438 13.3-2.605 26.442-3.96 39.312-4.03 1.855-.012 3.688.02 5.53.06 20.857.48 40.98 4.332 59.97 11.5a355.064 355.064 0 0 1-1.656-34.218c0-27.8 3.135-54.377 9-78.937l2.47-10.407 9.655 4.562c29.467 13.98 66.194 23.424 106.28 25.22 5.136-20.05 8.19-39.78 9.408-58.75-35.198 4.83-75.387 2.766-116.407-8.22-38.363-10.272-72.314-26.78-99.562-46.656zm230.594 82.218c-1.535 10.452-3.615 21.03-6.218 31.687a312.754 312.754 0 0 0 46-3.97 24.98 24.98 0 0 1-1.532-21.748l-38.25-5.97zM105 201.375l4.156 18.22-21.594 4.905c8.75 5.174 13.353 15.703 10.594 26-3.32 12.394-16.045 19.758-28.437 16.438-12.394-3.32-19.76-16.075-16.44-28.47a23.235 23.235 0 0 1 3.126-6.874l-21.062 4.78-4.125-18.218 73.78-16.78zm388.594 22.813c-25.53 25.46-55.306 45.445-86.906 60.5.05 2.397.093 4.8.093 7.218 0 9.188-.354 18.232-1.03 27.125 16.635 1.33 32.045-1.7 45.344-9.374 25.925-14.962 40.608-45.694 42.5-85.47zm-338.844 3c-4.03 19.993-6.33 41.31-6.406 63.593l.125-.342c30.568 10.174 62.622 17.572 95.25 21.375l7.5.875.718 7.5 5.687 60.125-18.625 1.75-2.53-26.75a23.117 23.117 0 0 1-14.845.968c-12.393-3.32-19.76-16.042-16.438-28.436.285-1.06.647-2.08 1.063-3.063a496.627 496.627 0 0 1-57.406-14.53c2.69 49.62 16.154 94.04 36.094 126.656 22.366 36.588 52.13 57.78 83.968 57.78 31.838.003 61.602-21.19 83.97-57.78 19.536-31.96 32.846-75.244 35.905-123.656a499.132 499.132 0 0 1-48.25 11.656c1.914 4.57 2.415 9.78 1.033 14.938-3.322 12.394-16.045 19.758-28.438 16.437a23.01 23.01 0 0 1-2.125-.686l-2.5 26.47-18.594-1.752 5.688-60.125.72-7.5 7.498-.875c29.245-3.407 57.995-9.717 85.657-18.312v-1.594c0-21.573-2.27-42.23-6.064-61.75C351.132 242.653 313.092 250 272.312 250c-43.59 0-83.986-8.658-117.562-22.813zm-87.5 105.968c-10.87.102-21.995 1.22-33.375 3.313 12.695 31.62 33.117 53.07 59 60 16.9 4.523 34.896 2.536 52.813-5.25-4.382-13.89-7.874-28.606-10.344-43.97-21.115-9.623-43.934-14.32-68.094-14.094zm137.5 80.22h130.813c-40.082 44.594-92.623 42.844-130.813 0z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><path d="M0 0h512v512H0z" fill="#000" fill-opacity="1"></path><g class="" transform="translate(0,0)" style=""><path d="M418.813 30.625c-21.178 26.27-49.712 50.982-84.125 70.844-36.778 21.225-75.064 33.62-110.313 38.06a310.317 310.317 0 0 0 6.813 18.25c16.01.277 29.366-.434 36.406-1.5l9.47-1.53 8.436-1.28.22 10.186a307.48 307.48 0 0 1-1.095 18.72l56.625 8.843c.86-.095 1.713-.15 2.563-.157 11.188-.114 21.44 7.29 24.468 18.593.657 2.448.922 4.903.845 7.313 5.972-2.075 11.753-4.305 17.28-6.72l9.595-4.188 2.313 10.22a340.211 340.211 0 0 1 7.375 48.062C438.29 247.836 468.438 225.71 493 197.5c-3.22-36.73-16.154-78.04-39.125-117.813a290.509 290.509 0 0 0-2.22-3.78l-27.56 71.374c5.154.762 10.123 3.158 14.092 7.126 9.81 9.807 9.813 25.69 0 35.5-9.812 9.81-25.722 9.807-35.53 0-8.86-8.858-9.69-22.68-2.532-32.5l38.938-100.844a322.02 322.02 0 0 0-20.25-25.937zM51.842 118.72c-8.46 17.373-15.76 36.198-21.187 56.436-14.108 52.617-13.96 103.682-2.812 143.438 13.3-2.605 26.442-3.96 39.312-4.03 1.855-.012 3.688.02 5.53.06 20.857.48 40.98 4.332 59.97 11.5a355.064 355.064 0 0 1-1.656-34.218c0-27.8 3.135-54.377 9-78.937l2.47-10.407 9.655 4.562c29.467 13.98 66.194 23.424 106.28 25.22 5.136-20.05 8.19-39.78 9.408-58.75-35.198 4.83-75.387 2.766-116.407-8.22-38.363-10.272-72.314-26.78-99.562-46.656zm230.594 82.218c-1.535 10.452-3.615 21.03-6.218 31.687a312.754 312.754 0 0 0 46-3.97 24.98 24.98 0 0 1-1.532-21.748l-38.25-5.97zM105 201.375l4.156 18.22-21.594 4.905c8.75 5.174 13.353 15.703 10.594 26-3.32 12.394-16.045 19.758-28.437 16.438-12.394-3.32-19.76-16.075-16.44-28.47a23.235 23.235 0 0 1 3.126-6.874l-21.062 4.78-4.125-18.218 73.78-16.78zm388.594 22.813c-25.53 25.46-55.306 45.445-86.906 60.5.05 2.397.093 4.8.093 7.218 0 9.188-.354 18.232-1.03 27.125 16.635 1.33 32.045-1.7 45.344-9.374 25.925-14.962 40.608-45.694 42.5-85.47zm-338.844 3c-4.03 19.993-6.33 41.31-6.406 63.593l.125-.342c30.568 10.174 62.622 17.572 95.25 21.375l7.5.875.718 7.5 5.687 60.125-18.625 1.75-2.53-26.75a23.117 23.117 0 0 1-14.845.968c-12.393-3.32-19.76-16.042-16.438-28.436.285-1.06.647-2.08 1.063-3.063a496.627 496.627 0 0 1-57.406-14.53c2.69 49.62 16.154 94.04 36.094 126.656 22.366 36.588 52.13 57.78 83.968 57.78 31.838.003 61.602-21.19 83.97-57.78 19.536-31.96 32.846-75.244 35.905-123.656a499.132 499.132 0 0 1-48.25 11.656c1.914 4.57 2.415 9.78 1.033 14.938-3.322 12.394-16.045 19.758-28.438 16.437a23.01 23.01 0 0 1-2.125-.686l-2.5 26.47-18.594-1.752 5.688-60.125.72-7.5 7.498-.875c29.245-3.407 57.995-9.717 85.657-18.312v-1.594c0-21.573-2.27-42.23-6.064-61.75C351.132 242.653 313.092 250 272.312 250c-43.59 0-83.986-8.658-117.562-22.813zm-87.5 105.968c-10.87.102-21.995 1.22-33.375 3.313 12.695 31.62 33.117 53.07 59 60 16.9 4.523 34.896 2.536 52.813-5.25-4.382-13.89-7.874-28.606-10.344-43.97-21.115-9.623-43.934-14.32-68.094-14.094zm137.5 80.22h130.813c-40.082 44.594-92.623 42.844-130.813 0z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 2.9 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M169.92 15.654c-10.512 16.697-22.392 34.058-41.688 50.473.46.447.934.89 1.405 1.336l23.55-.406-3.527 10.7a71.131 71.131 0 0 1-1.678 4.552 183.485 183.485 0 0 0 8.872 5.788l25.052 15.33-45.99-.793c-1.954 2.474-4.06 4.9-6.305 7.275 8.8 11.517 22.045 22.713 38.675 32.766l-12.404-.365-.015 5.678c8.53 6.358 17.792 12.448 27.162 18.48 18.11-11.568 31.79-24.5 39.51-37.616l-57.353.99 25.052-15.33c8.97-5.488 16.525-11.115 23.082-16.867-5.098-5.475-9-10.962-11.257-16.69l-4.04-10.246 29.742-1.823C205.14 54.41 182.44 38.31 169.92 15.654zm234.605 13.223c-6.537 12.962-13.88 29.016-23.638 44.63 10.927 18.367 24.428 35.997 46.773 52.382l20.42 14.97-52.51-1.085c6.956 12.136 19.936 26.858 34.58 40.047 19.157 17.254 40.928 32.572 53.907 39.914l11.34 6.418c.005-4.163.005-7.382.015-13.972-17.176-11.938-29.767-25.795-36.322-42.2l-4.115-10.298 43.605-2.58c-9.91-4.358-19.747-8.263-28.723-12.06-8.498-3.594-16.23-7.107-22.724-11.23-6.495-4.122-12.102-8.954-14.858-15.943l-3.93-9.962 36.077-3.178c-24.245-20.226-47.223-48.756-59.897-75.853zM84.027 34.62c-12.52 22.656-35.22 38.757-57.843 53.234l29.738 1.822-4.037 10.244c-4.78 12.125-16.815 24.123-33.182 36.873-.295 11.21-.392 17.66-.385 17.732.005.044.19 1.1.29 3.127.038.742.04 3.177.066 4.358l13.828.797-.004.55-3.906 9.778c-1.18 2.955-2.498 6.07-4.16 9.232l11.525-7.05c37.376-22.87 50.42-48.163 67.395-74.833l-.233 6.366 4.474-1.875a72.336 72.336 0 0 1-3.305-8.25l-3.528-10.7 26.582.46C107.068 69.66 94.836 51.787 84.027 34.618zM263.06 61.036c-10.808 17.168-23.04 35.04-43.314 51.86l26.582-.458-3.527 10.7c-6.657 20.188-22.772 37.89-44.874 52.91l17.916 11.573 18.273.688-4.127 10.5c-2.305 5.863-5.355 11.4-9.01 16.65l8.737-6.19c17.913-12.69 36.773-27.495 51.8-41.534 10.026-9.365 17.978-18.52 23.083-25.914l-50.537-3.715 16.5-12.773c10.37-8.027 20.973-15.94 30.924-24.178-15.49-11.246-29.53-24.024-38.423-40.12zm93.07.68c-12.76 26.805-36.227 46.04-59.107 63.506l31.39 2.306-3.194 9.726c-4.503 13.7-16.983 27.412-32.783 42.172-10.794 10.083-23.245 20.29-35.896 29.926l49.278 3.494-3.26 9.78c-11.273 33.806-46.845 56.924-75.816 75.597 13.487 8.056 27.67 15.44 39.813 22.318 68.34 18.82 147.594 6.972 200.924-16-13.19-7.554-23.844-14.547-32.748-23.006-11.805-11.216-20.072-24.96-26.377-44.183l-3.017-9.208 51.97-6.61c-11.874-8.21-25.17-18.39-37.867-29.825-20.11-18.113-38.394-38.003-43.915-58.067L372.68 123.3l27.867.577c-21.174-20.07-33.542-41.485-44.416-62.16zM108.78 121.84c-10.807 17.168-23.038 35.04-43.313 51.86l26.582-.456-3.53 10.697c-8.24 24.998-30.974 46.186-61.625 63.185l52.94 1.99-4.126 10.496c-11.05 28.11-29.76 52.974-61.038 71.585 73.885 22.566 156.574 31.568 231.582-3.572-12.908-7.055-26.9-14.653-40.33-23.56-18.07-11.983-34.525-25.736-41.71-43.713l-4.116-10.3 48.4-2.864c-11.828-7.625-23.415-15.48-33.557-23.383-16.245-12.663-29.06-24.086-34.02-36.664l-4.04-10.247 29.74-1.823c-22.62-14.476-45.318-30.576-57.84-53.23zm-40.52 67.816-49.016.844c-.168.218-.32.44-.492.656-.276 21.495-.448 33.384-.502 42.38 23.342-13.057 40.863-28.338 50.01-43.88zm105.674 12.403a189.592 189.592 0 0 0 10.845 9.124 360.036 360.036 0 0 0 11.14 8.308c5.44-5.177 10.084-10.545 13.692-16.092l-35.678-1.34zm41.658 20.428a112.599 112.599 0 0 1-5.947 6.504 619.186 619.186 0 0 0 28.38 17.815l17.645 10.427c11.34-9.42 21.135-19.423 27.215-29.972l-67.293-4.774zm279.803 10.334-68.383 8.698c4.666 11.45 10.047 19.75 17.28 26.992l-.21-9.6c17.455-.996 34.705-3.352 51.4-7.363-.065-7.174-.084-12.42-.087-18.728zm-243.96 27.852-66.394 3.928c3.903 5.187 9.085 10.326 15.097 15.314a495.837 495.837 0 0 0 19.455 3.504c10.638-7.12 21.72-14.713 31.842-22.746zm-219.744 2.64-.29 35.618c10.746-10.37 18.692-21.97 24.83-34.694l-24.54-.924zm413.947 66.534c-14.262 4.577-29.517 8.396-45.38 11.222l5.55 132.18h42.978l-3.148-143.402zm-181.83 7.002a257.23 257.23 0 0 1-8.018 4.046l-.927 114.274h52.682l-2.426-110.496c-13.946-1.552-27.788-4.123-41.313-7.824zm120.54 6.693c-15.085 1.992-30.582 3.05-46.18 2.994l-.386 139.742h52.56l-5.994-142.737zm-353.38 9.146-.924 114.04H74.31l1.975-104.398c-15.362-2.464-30.51-5.75-45.318-9.643zm174.72 6.27c-11.576 2.87-23.226 4.935-34.898 6.284l3.915 66.195h33.065l-2.084-72.48zm-113.443 5.628-2.508 132.56 72.692-2.287-7.584-128.21c-20.97 1.29-41.936.424-62.6-2.062z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M169.92 15.654c-10.512 16.697-22.392 34.058-41.688 50.473.46.447.934.89 1.405 1.336l23.55-.406-3.527 10.7a71.131 71.131 0 0 1-1.678 4.552 183.485 183.485 0 0 0 8.872 5.788l25.052 15.33-45.99-.793c-1.954 2.474-4.06 4.9-6.305 7.275 8.8 11.517 22.045 22.713 38.675 32.766l-12.404-.365-.015 5.678c8.53 6.358 17.792 12.448 27.162 18.48 18.11-11.568 31.79-24.5 39.51-37.616l-57.353.99 25.052-15.33c8.97-5.488 16.525-11.115 23.082-16.867-5.098-5.475-9-10.962-11.257-16.69l-4.04-10.246 29.742-1.823C205.14 54.41 182.44 38.31 169.92 15.654zm234.605 13.223c-6.537 12.962-13.88 29.016-23.638 44.63 10.927 18.367 24.428 35.997 46.773 52.382l20.42 14.97-52.51-1.085c6.956 12.136 19.936 26.858 34.58 40.047 19.157 17.254 40.928 32.572 53.907 39.914l11.34 6.418c.005-4.163.005-7.382.015-13.972-17.176-11.938-29.767-25.795-36.322-42.2l-4.115-10.298 43.605-2.58c-9.91-4.358-19.747-8.263-28.723-12.06-8.498-3.594-16.23-7.107-22.724-11.23-6.495-4.122-12.102-8.954-14.858-15.943l-3.93-9.962 36.077-3.178c-24.245-20.226-47.223-48.756-59.897-75.853zM84.027 34.62c-12.52 22.656-35.22 38.757-57.843 53.234l29.738 1.822-4.037 10.244c-4.78 12.125-16.815 24.123-33.182 36.873-.295 11.21-.392 17.66-.385 17.732.005.044.19 1.1.29 3.127.038.742.04 3.177.066 4.358l13.828.797-.004.55-3.906 9.778c-1.18 2.955-2.498 6.07-4.16 9.232l11.525-7.05c37.376-22.87 50.42-48.163 67.395-74.833l-.233 6.366 4.474-1.875a72.336 72.336 0 0 1-3.305-8.25l-3.528-10.7 26.582.46C107.068 69.66 94.836 51.787 84.027 34.618zM263.06 61.036c-10.808 17.168-23.04 35.04-43.314 51.86l26.582-.458-3.527 10.7c-6.657 20.188-22.772 37.89-44.874 52.91l17.916 11.573 18.273.688-4.127 10.5c-2.305 5.863-5.355 11.4-9.01 16.65l8.737-6.19c17.913-12.69 36.773-27.495 51.8-41.534 10.026-9.365 17.978-18.52 23.083-25.914l-50.537-3.715 16.5-12.773c10.37-8.027 20.973-15.94 30.924-24.178-15.49-11.246-29.53-24.024-38.423-40.12zm93.07.68c-12.76 26.805-36.227 46.04-59.107 63.506l31.39 2.306-3.194 9.726c-4.503 13.7-16.983 27.412-32.783 42.172-10.794 10.083-23.245 20.29-35.896 29.926l49.278 3.494-3.26 9.78c-11.273 33.806-46.845 56.924-75.816 75.597 13.487 8.056 27.67 15.44 39.813 22.318 68.34 18.82 147.594 6.972 200.924-16-13.19-7.554-23.844-14.547-32.748-23.006-11.805-11.216-20.072-24.96-26.377-44.183l-3.017-9.208 51.97-6.61c-11.874-8.21-25.17-18.39-37.867-29.825-20.11-18.113-38.394-38.003-43.915-58.067L372.68 123.3l27.867.577c-21.174-20.07-33.542-41.485-44.416-62.16zM108.78 121.84c-10.807 17.168-23.038 35.04-43.313 51.86l26.582-.456-3.53 10.697c-8.24 24.998-30.974 46.186-61.625 63.185l52.94 1.99-4.126 10.496c-11.05 28.11-29.76 52.974-61.038 71.585 73.885 22.566 156.574 31.568 231.582-3.572-12.908-7.055-26.9-14.653-40.33-23.56-18.07-11.983-34.525-25.736-41.71-43.713l-4.116-10.3 48.4-2.864c-11.828-7.625-23.415-15.48-33.557-23.383-16.245-12.663-29.06-24.086-34.02-36.664l-4.04-10.247 29.74-1.823c-22.62-14.476-45.318-30.576-57.84-53.23zm-40.52 67.816-49.016.844c-.168.218-.32.44-.492.656-.276 21.495-.448 33.384-.502 42.38 23.342-13.057 40.863-28.338 50.01-43.88zm105.674 12.403a189.592 189.592 0 0 0 10.845 9.124 360.036 360.036 0 0 0 11.14 8.308c5.44-5.177 10.084-10.545 13.692-16.092l-35.678-1.34zm41.658 20.428a112.599 112.599 0 0 1-5.947 6.504 619.186 619.186 0 0 0 28.38 17.815l17.645 10.427c11.34-9.42 21.135-19.423 27.215-29.972l-67.293-4.774zm279.803 10.334-68.383 8.698c4.666 11.45 10.047 19.75 17.28 26.992l-.21-9.6c17.455-.996 34.705-3.352 51.4-7.363-.065-7.174-.084-12.42-.087-18.728zm-243.96 27.852-66.394 3.928c3.903 5.187 9.085 10.326 15.097 15.314a495.837 495.837 0 0 0 19.455 3.504c10.638-7.12 21.72-14.713 31.842-22.746zm-219.744 2.64-.29 35.618c10.746-10.37 18.692-21.97 24.83-34.694l-24.54-.924zm413.947 66.534c-14.262 4.577-29.517 8.396-45.38 11.222l5.55 132.18h42.978l-3.148-143.402zm-181.83 7.002a257.23 257.23 0 0 1-8.018 4.046l-.927 114.274h52.682l-2.426-110.496c-13.946-1.552-27.788-4.123-41.313-7.824zm120.54 6.693c-15.085 1.992-30.582 3.05-46.18 2.994l-.386 139.742h52.56l-5.994-142.737zm-353.38 9.146-.924 114.04H74.31l1.975-104.398c-15.362-2.464-30.51-5.75-45.318-9.643zm174.72 6.27c-11.576 2.87-23.226 4.935-34.898 6.284l3.915 66.195h33.065l-2.084-72.48zm-113.443 5.628-2.508 132.56 72.692-2.287-7.584-128.21c-20.97 1.29-41.936.424-62.6-2.062z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M27.47 15.344c62.946 25.422 108.824 61.313 115.843 132.03v.188c52.31 30.132 92.605 72.538 104.28 119.938a109.714 109.714 0 0 1 3.126 22.03c31.737-3.283 64-20.935 87.843-46.624 26.42-28.467 42.056-65.91 36.843-103.03-15.205 1.917-30.855.922-46.5-2.314-50.282-10.398-101.7-42.974-148.562-77.875-4.79-4.21-9.93-8.084-15.406-11.656-34.787-22.69-82.864-32.686-137.47-32.686zM234.687 41.25l-15.72 23c19.23 13.107 38.792 25.095 58.126 34.72l13.437-19.25c-12.406-18.774-34.986-32.363-55.842-38.47zm239.375 21.375c-16.886 31.464-37.035 52.625-59.72 64.875a108.541 108.541 0 0 1-20.593 8.53c6.67 44.027-11.746 87.505-41.5 119.564-27.275 29.387-64.424 49.947-102.53 52.844-4.482 31.48-23.408 62.858-59.75 90.312 40.743 9.164 78.742 9.05 113.436 1.906l7.72-49.03 2.937-18.595 13.03 13.595L359 379.875c27.795-16.753 64.71-44.308 83.22-67.906L413.31 262l-11.468-19.78 22.03 6.093 47.938 13.25c13.232-23.865 21.327-60.527 21.47-98.875.13-34.855-6.22-70.88-19.22-100.063zM146.092 170.97 20.564 354.75l.812 110.625 175.53-251.5c-13.78-15.612-31.054-30.19-50.81-42.906z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M27.47 15.344c62.946 25.422 108.824 61.313 115.843 132.03v.188c52.31 30.132 92.605 72.538 104.28 119.938a109.714 109.714 0 0 1 3.126 22.03c31.737-3.283 64-20.935 87.843-46.624 26.42-28.467 42.056-65.91 36.843-103.03-15.205 1.917-30.855.922-46.5-2.314-50.282-10.398-101.7-42.974-148.562-77.875-4.79-4.21-9.93-8.084-15.406-11.656-34.787-22.69-82.864-32.686-137.47-32.686zM234.687 41.25l-15.72 23c19.23 13.107 38.792 25.095 58.126 34.72l13.437-19.25c-12.406-18.774-34.986-32.363-55.842-38.47zm239.375 21.375c-16.886 31.464-37.035 52.625-59.72 64.875a108.541 108.541 0 0 1-20.593 8.53c6.67 44.027-11.746 87.505-41.5 119.564-27.275 29.387-64.424 49.947-102.53 52.844-4.482 31.48-23.408 62.858-59.75 90.312 40.743 9.164 78.742 9.05 113.436 1.906l7.72-49.03 2.937-18.595 13.03 13.595L359 379.875c27.795-16.753 64.71-44.308 83.22-67.906L413.31 262l-11.468-19.78 22.03 6.093 47.938 13.25c13.232-23.865 21.327-60.527 21.47-98.875.13-34.855-6.22-70.88-19.22-100.063zM146.092 170.97 20.564 354.75l.812 110.625 175.53-251.5c-13.78-15.612-31.054-30.19-50.81-42.906z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M272.824 24.318c-14.929.312-25.66 3.246-32.767 8.446L142.898 84.91l-54.105 73.514C77.42 175.98 85.517 210 121.111 188.197l38.9-51.351c49.476-42.711 150.485-23.032 102.587 62.591-23.53 49.582-12.457 73.79 17.76 83.95l13.812-46.381c23.949-53.825 68.502-63.51 66.684-106.904l107.302 7.724-.865-112.045-194.467-1.463zm-54.09 103.338c-17.41-.3-34.486 6.898-46.92 17.375l-39.044 51.33c10.713 8.506 21.413 3.96 32.125-6.363 12.626 6.394 22.365-3.522 30.365-23.297 3.317-13.489 8.21-23.037 23.474-39.045zm-32.617 88.324a13.49 13.49 0 0 0-5.232 1.235L51.72 276.725c-6.784 3.13-9.763 11.202-6.633 17.992l85.27 185.08c3.131 6.783 11.204 9.779 18 6.635l129.15-59.504c6.796-3.137 9.776-11.198 6.646-18L198.871 223.86c-2.344-5.097-7.474-8.043-12.754-7.88z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M272.824 24.318c-14.929.312-25.66 3.246-32.767 8.446L142.898 84.91l-54.105 73.514C77.42 175.98 85.517 210 121.111 188.197l38.9-51.351c49.476-42.711 150.485-23.032 102.587 62.591-23.53 49.582-12.457 73.79 17.76 83.95l13.812-46.381c23.949-53.825 68.502-63.51 66.684-106.904l107.302 7.724-.865-112.045-194.467-1.463zm-54.09 103.338c-17.41-.3-34.486 6.898-46.92 17.375l-39.044 51.33c10.713 8.506 21.413 3.96 32.125-6.363 12.626 6.394 22.365-3.522 30.365-23.297 3.317-13.489 8.21-23.037 23.474-39.045zm-32.617 88.324a13.49 13.49 0 0 0-5.232 1.235L51.72 276.725c-6.784 3.13-9.763 11.202-6.633 17.992l85.27 185.08c3.131 6.783 11.204 9.779 18 6.635l129.15-59.504c6.796-3.137 9.776-11.198 6.646-18L198.871 223.86c-2.344-5.097-7.474-8.043-12.754-7.88z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 945 B After Width: | Height: | Size: 933 B |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M156.7 25.83 89 39.38c-.1 58.57-1.74 119.32-43.49 167.22C104.4 246.5 189 260.7 247 248.8v-99L108.3 88.22l7.4-16.44L256 134.2l140.3-62.42 7.4 16.44L265 149.8v99c58 11.9 142.6-2.3 201.5-42.2-41.8-47.9-43.4-108.65-43.5-167.22l-67.7-13.55c-12.9 13.88-20.6 28.15-32.9 40.53C308.9 79.78 289.5 89 256 89c-33.5 0-52.9-9.22-66.4-22.64-12.3-12.38-20-26.65-32.9-40.53zM53.88 232.9C75.96 281 96.07 336.6 102.7 392.8l65 22.8c4.2-52.7 28.2-104 63.7-146.1-55.1 6.3-122.7-5.8-177.52-36.6zm404.22 0c-54.8 30.8-122.4 42.9-177.5 36.6 35.5 42.1 59.5 93.4 63.7 146.1l65.2-22.9c6.6-56.8 26.6-111.8 48.6-159.8zM256 269c-40.5 43.1-67.7 97.9-70.7 152.7l61.7 21.6V336h18v107.3l61.7-21.6c-3.1-54.8-30.2-109.6-70.7-152.7zm151.7 143.4L297 451.1v18.8l110.2-44.1c.1-4.5.3-8.9.5-13.4zm-303.3.1c.3 4.5.4 8.9.5 13.4l110.1 44v-18.7l-110.6-38.7zM279 457.4l-23 8.1-23-8v19.6l23 9.2 23-9.2v-19.7z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M156.7 25.83 89 39.38c-.1 58.57-1.74 119.32-43.49 167.22C104.4 246.5 189 260.7 247 248.8v-99L108.3 88.22l7.4-16.44L256 134.2l140.3-62.42 7.4 16.44L265 149.8v99c58 11.9 142.6-2.3 201.5-42.2-41.8-47.9-43.4-108.65-43.5-167.22l-67.7-13.55c-12.9 13.88-20.6 28.15-32.9 40.53C308.9 79.78 289.5 89 256 89c-33.5 0-52.9-9.22-66.4-22.64-12.3-12.38-20-26.65-32.9-40.53zM53.88 232.9C75.96 281 96.07 336.6 102.7 392.8l65 22.8c4.2-52.7 28.2-104 63.7-146.1-55.1 6.3-122.7-5.8-177.52-36.6zm404.22 0c-54.8 30.8-122.4 42.9-177.5 36.6 35.5 42.1 59.5 93.4 63.7 146.1l65.2-22.9c6.6-56.8 26.6-111.8 48.6-159.8zM256 269c-40.5 43.1-67.7 97.9-70.7 152.7l61.7 21.6V336h18v107.3l61.7-21.6c-3.1-54.8-30.2-109.6-70.7-152.7zm151.7 143.4L297 451.1v18.8l110.2-44.1c.1-4.5.3-8.9.5-13.4zm-303.3.1c.3 4.5.4 8.9.5 13.4l110.1 44v-18.7l-110.6-38.7zM279 457.4l-23 8.1-23-8v19.6l23 9.2 23-9.2v-19.7z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M25.01 49v46H103V49zM153 49v46h78V49zm128 0v46h78V49zm128 0v46h78V49zM55.01 113v64H119v46h18v-46h64v-64h-18v46H73.01v-46zM311 113v64h64v46h18v-46h64v-64h-18v46H329v-46zM89.01 241v46H167v-46zM345 241v46h78v-46zm-226 64v48h128v46h18v-46h128v-48h-18v30H137v-30zm98 112v46h78v-46z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M25.01 49v46H103V49zM153 49v46h78V49zm128 0v46h78V49zm128 0v46h78V49zM55.01 113v64H119v46h18v-46h64v-64h-18v46H73.01v-46zM311 113v64h64v46h18v-46h64v-64h-18v46H329v-46zM89.01 241v46H167v-46zM345 241v46h78v-46zm-226 64v48h128v46h18v-46h128v-48h-18v30H137v-30zm98 112v46h78v-46z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 480 B After Width: | Height: | Size: 468 B |
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M234.7 18.05c-21 .2-38.8 2.5-62 10.2-4.1 2-8.2 4.1-12.2 6.2.8 5.26 3.2 10.77 5.5 14.7-4.9 4.2-9.6 8.4-14.1 12.8-3.7-5.5-6.6-11.4-8.3-17.4-14.2 9.2-27.7 19.6-40.1 31.4 1.9 9.5 9.2 18.21 15.2 24.15-3.7 5.2-7.2 10.4-10.5 15.7-8.22-7.2-15.12-15.5-19.32-24.65C74.97 108.1 61.92 126 53.08 142.3c5.29 13 19.01 22.7 29.8 28.4-2 6.1-3.7 12.2-5.1 18.4-13.5-6.4-26.3-15.7-34.5-26.6-8.7 20.1-14.7 40.7-18.2 61.4 9.63 15.5 30.57 22.9 46 25.9.1 6.4.4 12.8.9 19.2-17.79-2.7-37.26-9.6-49.9-20.4-1.6 22.3-.5 44.5 3.4 66.2 15.25 13.7 41.14 15.3 58.6 13.7 2 6.1 4.1 12.2 6.5 18.1-18.61 4.5-43.29 1.1-59.3-6.2 6.6 23.7 16.4 46.4 29.2 67.4 19.33 8.6 44.52 3.6 61.72-2.5 3.7 5.3 7.6 10.5 11.6 15.5-17.8 9.5-39.9 11.5-57.52 10.1 12.3 16.3 26.62 31.2 42.72 44.4 4.9 1.1 10.5 1.1 16.7.3 11.7-1.7 25.2-7 37.9-14.7 16.7 13.5 34.9 24.7 54.1 33.1l7.5-17.2c-16-6.9-31.3-16.2-45.6-27.3 13.3-10.9 24.3-24 30.2-36.5 4.7-9.7 6.3-18.4 4.5-26.3-10.7-5.7-20.6-12.5-29.5-20.3-7.8 20.8-26.4 36.1-43.5 46-4-4.9-7.9-9.9-11.6-15 16.8-9.8 39.9-27.5 39.1-47.1-8.9-10.3-16.6-21.8-22.9-34.1-12 14-30.7 22.5-46.5 26.7-2.4-5.8-4.6-11.6-6.6-17.6 16.8-5.2 37.9-13 44.1-29.7-4.3-11.5-7.5-23.6-9.7-36-13.8 8.4-32 11.1-46.32 10.9-.6-6.2-1-12.4-1.2-18.7 15.52-.6 33.92-2.5 44.92-14.3-.8-12.6-.5-25.5.9-38.5-13.4 2.8-29 .3-40.42-3.2 1.3-6 2.9-12.1 4.8-18.1 12.82 3.2 27.12 6.7 38.82.8 2.7-13.6 6.7-27.3 12-40.8-9.9-1.8-20.2-6.3-27.7-10.7 3.3-5.3 6.8-10.5 10.5-15.7 8.1 4.2 16.3 8.8 25.2 8.4 5.7-11.6 12.3-22.65 19.5-32.75-5.1-2.7-10-6.4-14.4-10.6 4.4-4.3 9.1-8.5 13.9-12.7 3.8 3.54 8 6.18 12.3 8.2 15.9-18.6 35.9-36.23 49-53.8zm38.4 0c15.4 20.75 33.8 35.63 48.9 53.7 4.6-1.76 9.1-5.23 12.3-8.1 4.9 4.2 9.5 8.4 13.9 12.7-4.4 4.2-9.2 7.9-14.4 10.6 7.3 10.1 13.9 21.05 19.6 32.65 9-.1 18.4-4.4 25.2-8.4 3.7 5.2 7.2 10.4 10.4 15.7-8.8 5.9-18.2 9.6-27.6 10.7 5.3 13.5 9.3 27.2 12 40.8 12.3 5.4 27.3 2.7 38.7-.8 1.9 6 3.5 12.1 4.9 18.1-14.2 3.4-27.3 6.2-40.4 3.3 1.4 12.9 1.6 25.8.8 38.5 11.4 12.3 30.2 14.4 44.9 14.2-.2 6.3-.5 12.5-1.2 18.7-17.1-.5-32.8-2.5-46.3-10.9-2.1 12.4-5.3 24.5-9.6 36.1 8.2 17.4 27.8 25.3 44.1 29.6-2 6-4.2 11.8-6.6 17.6-18.5-5.6-34.9-13-46.6-26.7-6.3 12.4-13.9 23.8-22.9 34.1 1.5 22.4 22.4 37.8 39.2 47.1-3.7 5.1-7.6 10.1-11.6 15-19-11.8-36.6-25.8-43.5-46-9 7.8-18.8 14.6-29.6 20.3-1.8 7.9-.1 16.6 4.5 26.3 6 12.5 17 25.6 30.3 36.5-14.3 11.1-29.6 20.4-45.6 27.3l7.4 17.2c19.3-8.4 37.4-19.6 54.1-33.2 12.7 7.8 26.2 13.1 38 14.8 6.2.8 11.8.8 16.7-.3 16.1-13.2 30.4-28.1 42.7-44.4-18 1.7-37.9-2.3-56.5-9.7-.3-.1-.7-.3-1.1-.4 4.1-5 7.9-10.2 11.7-15.5 18.2 7.8 43.7 11.7 61.6 2.5 12.8-21 22.6-43.7 29.2-67.4-.4.2-.8.4-1.2.5-20.5 6.4-40.1 7.6-58.1 5.7 2.4-5.9 4.5-12 6.5-18 19.1 1.7 45.2.1 58.6-13.8 3.9-21.7 5.1-43.9 3.4-66.2-14.4 10.7-34.9 17.9-49.9 20.4.5-6.4.9-12.8 1-19.2 16.8-4.8 37.9-10 45.9-25.9-3.5-20.7-9.5-41.3-18.2-61.4-9.4 11.6-23.1 21-34.4 26.5-1.5-6.1-3.2-12.2-5.2-18.3 12-7.4 25.1-15.3 29.9-28.4-10.1-18.7-22.2-35.8-35.9-51.05-4.2 9.05-11.1 17.45-19.2 24.65-3.3-5.3-6.8-10.5-10.6-15.7 6.2-7.17 14.2-14.71 15.2-24.15-12.4-11.8-25.8-22.2-40-31.4-1.8 6-4.7 11.9-8.3 17.4-4.5-4.4-9.2-8.6-14.1-12.8 2.7-4.82 4.7-9.62 5.4-14.7-4-2.1-8.1-4.2-12.2-6.2-24.7-8.2-43.3-10.3-66.2-10.2z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M234.7 18.05c-21 .2-38.8 2.5-62 10.2-4.1 2-8.2 4.1-12.2 6.2.8 5.26 3.2 10.77 5.5 14.7-4.9 4.2-9.6 8.4-14.1 12.8-3.7-5.5-6.6-11.4-8.3-17.4-14.2 9.2-27.7 19.6-40.1 31.4 1.9 9.5 9.2 18.21 15.2 24.15-3.7 5.2-7.2 10.4-10.5 15.7-8.22-7.2-15.12-15.5-19.32-24.65C74.97 108.1 61.92 126 53.08 142.3c5.29 13 19.01 22.7 29.8 28.4-2 6.1-3.7 12.2-5.1 18.4-13.5-6.4-26.3-15.7-34.5-26.6-8.7 20.1-14.7 40.7-18.2 61.4 9.63 15.5 30.57 22.9 46 25.9.1 6.4.4 12.8.9 19.2-17.79-2.7-37.26-9.6-49.9-20.4-1.6 22.3-.5 44.5 3.4 66.2 15.25 13.7 41.14 15.3 58.6 13.7 2 6.1 4.1 12.2 6.5 18.1-18.61 4.5-43.29 1.1-59.3-6.2 6.6 23.7 16.4 46.4 29.2 67.4 19.33 8.6 44.52 3.6 61.72-2.5 3.7 5.3 7.6 10.5 11.6 15.5-17.8 9.5-39.9 11.5-57.52 10.1 12.3 16.3 26.62 31.2 42.72 44.4 4.9 1.1 10.5 1.1 16.7.3 11.7-1.7 25.2-7 37.9-14.7 16.7 13.5 34.9 24.7 54.1 33.1l7.5-17.2c-16-6.9-31.3-16.2-45.6-27.3 13.3-10.9 24.3-24 30.2-36.5 4.7-9.7 6.3-18.4 4.5-26.3-10.7-5.7-20.6-12.5-29.5-20.3-7.8 20.8-26.4 36.1-43.5 46-4-4.9-7.9-9.9-11.6-15 16.8-9.8 39.9-27.5 39.1-47.1-8.9-10.3-16.6-21.8-22.9-34.1-12 14-30.7 22.5-46.5 26.7-2.4-5.8-4.6-11.6-6.6-17.6 16.8-5.2 37.9-13 44.1-29.7-4.3-11.5-7.5-23.6-9.7-36-13.8 8.4-32 11.1-46.32 10.9-.6-6.2-1-12.4-1.2-18.7 15.52-.6 33.92-2.5 44.92-14.3-.8-12.6-.5-25.5.9-38.5-13.4 2.8-29 .3-40.42-3.2 1.3-6 2.9-12.1 4.8-18.1 12.82 3.2 27.12 6.7 38.82.8 2.7-13.6 6.7-27.3 12-40.8-9.9-1.8-20.2-6.3-27.7-10.7 3.3-5.3 6.8-10.5 10.5-15.7 8.1 4.2 16.3 8.8 25.2 8.4 5.7-11.6 12.3-22.65 19.5-32.75-5.1-2.7-10-6.4-14.4-10.6 4.4-4.3 9.1-8.5 13.9-12.7 3.8 3.54 8 6.18 12.3 8.2 15.9-18.6 35.9-36.23 49-53.8zm38.4 0c15.4 20.75 33.8 35.63 48.9 53.7 4.6-1.76 9.1-5.23 12.3-8.1 4.9 4.2 9.5 8.4 13.9 12.7-4.4 4.2-9.2 7.9-14.4 10.6 7.3 10.1 13.9 21.05 19.6 32.65 9-.1 18.4-4.4 25.2-8.4 3.7 5.2 7.2 10.4 10.4 15.7-8.8 5.9-18.2 9.6-27.6 10.7 5.3 13.5 9.3 27.2 12 40.8 12.3 5.4 27.3 2.7 38.7-.8 1.9 6 3.5 12.1 4.9 18.1-14.2 3.4-27.3 6.2-40.4 3.3 1.4 12.9 1.6 25.8.8 38.5 11.4 12.3 30.2 14.4 44.9 14.2-.2 6.3-.5 12.5-1.2 18.7-17.1-.5-32.8-2.5-46.3-10.9-2.1 12.4-5.3 24.5-9.6 36.1 8.2 17.4 27.8 25.3 44.1 29.6-2 6-4.2 11.8-6.6 17.6-18.5-5.6-34.9-13-46.6-26.7-6.3 12.4-13.9 23.8-22.9 34.1 1.5 22.4 22.4 37.8 39.2 47.1-3.7 5.1-7.6 10.1-11.6 15-19-11.8-36.6-25.8-43.5-46-9 7.8-18.8 14.6-29.6 20.3-1.8 7.9-.1 16.6 4.5 26.3 6 12.5 17 25.6 30.3 36.5-14.3 11.1-29.6 20.4-45.6 27.3l7.4 17.2c19.3-8.4 37.4-19.6 54.1-33.2 12.7 7.8 26.2 13.1 38 14.8 6.2.8 11.8.8 16.7-.3 16.1-13.2 30.4-28.1 42.7-44.4-18 1.7-37.9-2.3-56.5-9.7-.3-.1-.7-.3-1.1-.4 4.1-5 7.9-10.2 11.7-15.5 18.2 7.8 43.7 11.7 61.6 2.5 12.8-21 22.6-43.7 29.2-67.4-.4.2-.8.4-1.2.5-20.5 6.4-40.1 7.6-58.1 5.7 2.4-5.9 4.5-12 6.5-18 19.1 1.7 45.2.1 58.6-13.8 3.9-21.7 5.1-43.9 3.4-66.2-14.4 10.7-34.9 17.9-49.9 20.4.5-6.4.9-12.8 1-19.2 16.8-4.8 37.9-10 45.9-25.9-3.5-20.7-9.5-41.3-18.2-61.4-9.4 11.6-23.1 21-34.4 26.5-1.5-6.1-3.2-12.2-5.2-18.3 12-7.4 25.1-15.3 29.9-28.4-10.1-18.7-22.2-35.8-35.9-51.05-4.2 9.05-11.1 17.45-19.2 24.65-3.3-5.3-6.8-10.5-10.6-15.7 6.2-7.17 14.2-14.71 15.2-24.15-12.4-11.8-25.8-22.2-40-31.4-1.8 6-4.7 11.9-8.3 17.4-4.5-4.4-9.2-8.6-14.1-12.8 2.7-4.82 4.7-9.62 5.4-14.7-4-2.1-8.1-4.2-12.2-6.2-24.7-8.2-43.3-10.3-66.2-10.2z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M410.365 101.005c8.21-22.26 16.21-31.12 20.33-34.45 3.06-2.48 5.73-3.42 7.92-2.81 4 1.13 8.49 7.45 11.88 16.89 10.89 30.34 10 84.28-.93 129.51zm-286 72.92c7.52-31 10.28-66.13 7.77-94.92l-43.6-4.86zm289.46-113-301.2-33.53c-2.5-.28-5.24 1.46-7.11 3-3.67 3-10.42 10.32-17.66 27.64l308.68 34.34c5.16-13.25 11.02-23.89 17.31-31.43zm-228.78 298.71v-70.72l10.76 1.19 42.24 5.18v70.51zm16-40.34a13 13 0 0 0 5.34 10.29l-2.34 24.42 17 1.74-4-25a9.54 9.54 0 0 0 5-9.15 13.64 13.64 0 0 0-11.06-12.59s.17.1.13.1c-5.95-.68-11.07 3.9-10.07 10.1zm53 64.45-85-9.84v-86.72l-1.05-.09a8.14 8.14 0 0 1-7.27 6.71 8 8 0 0 1 5.23 8.9 8 8 0 0 1-8 6.66c8.453 4.004 4.341 16.778-4.86 15.1a8 8 0 0 1-8 13.8 8.01 8.01 0 0 1-12.28 10.29v.09a8 8 0 0 1-3.86 8.37l9.13 5.35v14.25l-12 7.13-12-7.12v-14.26l8.15-4.82a8.21 8.21 0 0 1-5.07-5.92.418.418 0 0 1 0-.1 8 8 0 0 1-15.18-5c-6.851 7.214-18.094-2.065-12.31-10.16-8.346 4.519-16.217-6.676-9.14-13-9.17 2.661-14.453-10.083-6.09-14.69a8 8 0 0 1-3.21-15.67c-9.294-1.047-9.548-14.463-.3-15.86-.669-.164-1.264-.473-1.83-.76l-17.24-1.86.6 167.11 309.18 34.49-.6-165.83-107-13.05zm140.06-164 4.72 1.91.91.58 38.72 4.31-23.26-64.77-12.82 37c-.16.46-3.41 9.8-8.27 20.99zm-208.54-39.74 5 5.49 12.75-11.15 21.45-2.28 16.61 15.35 10.51 8.73 18.54-9.29 3.44.5c.12-.67.25-1.34.38-2 3.08-16.1 7.35-30.16 7.53-30.75l13.39-43.91 16.88 42.71 8.42 21.42 10.66-12.39 22.14-25.73 5.78 33.45 3.29 19.1 17.1-9.64 35.09-19.79-18.48-51.4-247.86-27.61c2.51 34.94-1.85 77.32-12.39 112h2.32l7-12.86h40.46zm-111.29 97.39c7.6 2.1 7.9 12.766.43 15.29 7.737.867 9.802 11.153 3 14.94 7.653-.548 11.614 8.947 5.84 14 7.313-2.115 13.168 6.216 8.7 12.38 6.288-3.518 13.657 2.417 11.56 9.31 4.53-4.723 12.506-2.304 13.65 4.14 2.057-5.713 9.48-7.141 13.51-2.6-1.285-6.404 5.23-11.566 11.17-8.85-4.564-5.77.425-14.123 7.67-12.84-6.419-4.541-3.122-14.648 4.74-14.53-7.316-3.503-5.375-14.415 2.7-15.18a8 8 0 0 1-5.38-8l-76.43-8.26c-.41.19-.746.15-1.16.2zm367.54 139.08-.59-163.86-8.67 7-55.51 46.79.58 162zm-26.23-165.2-24.11-15.27-4.18-1.69c-5.91 11.52-13.39 23-22.66 27.88-5.44 2.88-12.22 4.34-20.16 4.34-11.13 0-24.75-2.91-37.35-8-10-4-23.3-11-30.26-21.34-4.9-7.29-6.64-17.77-5.31-32.92l-21.78 10.93-19-15.8-11.42-10.53-9.16 1-20.45 17.83-11-11.7h-24.21l-17.61 32-5.7-7.2-4.42 4.85-10.76 16.35-12.29 4.91L97.611 256h-12.2l-2.776 6.005 76.9 8.21a8.15 8.15 0 0 1 2-2.9 8 8 0 0 1 10.31-.46 1.657 1.657 0 0 1-.14-.24c-4.955-8.368 6.459-16.62 12.87-9.375 6.412 7.245-3.167 17.571-10.87 11.635a8 8 0 0 1 1.12 2.89l22.62 2.44 168.54 20.57 51.49-43.38zm-28.34-57.73-36.88 20.79-7.14-41.47-28 32.51-18.13-46.11s-16.65 54.58-7 69c7.69 11.45 35.42 22.25 54.33 22.25 5 0 9.43-.76 12.67-2.48 13.8-7.31 30.15-54.49 30.15-54.49zm-317.08 270.8v-.2c0-3.77-8.21-6.83-18.33-6.83-10.12 0-18.33 3.06-18.33 6.83 0 3.21 6 5.9 14 6.63v.2c0 3.77 8.21 6.83 18.33 6.83 10.12 0 18.33-3.06 18.33-6.83-.01-3.21-5.98-5.9-14-6.63zm350 6.63c-10.13 0-18.33 3.06-18.33 6.83s8.21 6.83 18.33 6.83c10.12 0 18.33-3.06 18.33-6.83s-8.25-6.8-18.38-6.8zm40-16.28c-10.13 0-18.33 3.06-18.33 6.83s8.21 6.83 18.33 6.83c10.12 0 18.33-3.06 18.33-6.83s-8.22-6.83-18.34-6.83z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M410.365 101.005c8.21-22.26 16.21-31.12 20.33-34.45 3.06-2.48 5.73-3.42 7.92-2.81 4 1.13 8.49 7.45 11.88 16.89 10.89 30.34 10 84.28-.93 129.51zm-286 72.92c7.52-31 10.28-66.13 7.77-94.92l-43.6-4.86zm289.46-113-301.2-33.53c-2.5-.28-5.24 1.46-7.11 3-3.67 3-10.42 10.32-17.66 27.64l308.68 34.34c5.16-13.25 11.02-23.89 17.31-31.43zm-228.78 298.71v-70.72l10.76 1.19 42.24 5.18v70.51zm16-40.34a13 13 0 0 0 5.34 10.29l-2.34 24.42 17 1.74-4-25a9.54 9.54 0 0 0 5-9.15 13.64 13.64 0 0 0-11.06-12.59s.17.1.13.1c-5.95-.68-11.07 3.9-10.07 10.1zm53 64.45-85-9.84v-86.72l-1.05-.09a8.14 8.14 0 0 1-7.27 6.71 8 8 0 0 1 5.23 8.9 8 8 0 0 1-8 6.66c8.453 4.004 4.341 16.778-4.86 15.1a8 8 0 0 1-8 13.8 8.01 8.01 0 0 1-12.28 10.29v.09a8 8 0 0 1-3.86 8.37l9.13 5.35v14.25l-12 7.13-12-7.12v-14.26l8.15-4.82a8.21 8.21 0 0 1-5.07-5.92.418.418 0 0 1 0-.1 8 8 0 0 1-15.18-5c-6.851 7.214-18.094-2.065-12.31-10.16-8.346 4.519-16.217-6.676-9.14-13-9.17 2.661-14.453-10.083-6.09-14.69a8 8 0 0 1-3.21-15.67c-9.294-1.047-9.548-14.463-.3-15.86-.669-.164-1.264-.473-1.83-.76l-17.24-1.86.6 167.11 309.18 34.49-.6-165.83-107-13.05zm140.06-164 4.72 1.91.91.58 38.72 4.31-23.26-64.77-12.82 37c-.16.46-3.41 9.8-8.27 20.99zm-208.54-39.74 5 5.49 12.75-11.15 21.45-2.28 16.61 15.35 10.51 8.73 18.54-9.29 3.44.5c.12-.67.25-1.34.38-2 3.08-16.1 7.35-30.16 7.53-30.75l13.39-43.91 16.88 42.71 8.42 21.42 10.66-12.39 22.14-25.73 5.78 33.45 3.29 19.1 17.1-9.64 35.09-19.79-18.48-51.4-247.86-27.61c2.51 34.94-1.85 77.32-12.39 112h2.32l7-12.86h40.46zm-111.29 97.39c7.6 2.1 7.9 12.766.43 15.29 7.737.867 9.802 11.153 3 14.94 7.653-.548 11.614 8.947 5.84 14 7.313-2.115 13.168 6.216 8.7 12.38 6.288-3.518 13.657 2.417 11.56 9.31 4.53-4.723 12.506-2.304 13.65 4.14 2.057-5.713 9.48-7.141 13.51-2.6-1.285-6.404 5.23-11.566 11.17-8.85-4.564-5.77.425-14.123 7.67-12.84-6.419-4.541-3.122-14.648 4.74-14.53-7.316-3.503-5.375-14.415 2.7-15.18a8 8 0 0 1-5.38-8l-76.43-8.26c-.41.19-.746.15-1.16.2zm367.54 139.08-.59-163.86-8.67 7-55.51 46.79.58 162zm-26.23-165.2-24.11-15.27-4.18-1.69c-5.91 11.52-13.39 23-22.66 27.88-5.44 2.88-12.22 4.34-20.16 4.34-11.13 0-24.75-2.91-37.35-8-10-4-23.3-11-30.26-21.34-4.9-7.29-6.64-17.77-5.31-32.92l-21.78 10.93-19-15.8-11.42-10.53-9.16 1-20.45 17.83-11-11.7h-24.21l-17.61 32-5.7-7.2-4.42 4.85-10.76 16.35-12.29 4.91L97.611 256h-12.2l-2.776 6.005 76.9 8.21a8.15 8.15 0 0 1 2-2.9 8 8 0 0 1 10.31-.46 1.657 1.657 0 0 1-.14-.24c-4.955-8.368 6.459-16.62 12.87-9.375 6.412 7.245-3.167 17.571-10.87 11.635a8 8 0 0 1 1.12 2.89l22.62 2.44 168.54 20.57 51.49-43.38zm-28.34-57.73-36.88 20.79-7.14-41.47-28 32.51-18.13-46.11s-16.65 54.58-7 69c7.69 11.45 35.42 22.25 54.33 22.25 5 0 9.43-.76 12.67-2.48 13.8-7.31 30.15-54.49 30.15-54.49zm-317.08 270.8v-.2c0-3.77-8.21-6.83-18.33-6.83-10.12 0-18.33 3.06-18.33 6.83 0 3.21 6 5.9 14 6.63v.2c0 3.77 8.21 6.83 18.33 6.83 10.12 0 18.33-3.06 18.33-6.83-.01-3.21-5.98-5.9-14-6.63zm350 6.63c-10.13 0-18.33 3.06-18.33 6.83s8.21 6.83 18.33 6.83c10.12 0 18.33-3.06 18.33-6.83s-8.25-6.8-18.38-6.8zm40-16.28c-10.13 0-18.33 3.06-18.33 6.83s8.21 6.83 18.33 6.83c10.12 0 18.33-3.06 18.33-6.83s-8.22-6.83-18.34-6.83z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="m381.7 27-14.5 20.4 49.5 35.1 14.5-20.3L381.7 27zm-57.4 12.3L310.2 60l111.3 76.2 14.1-20.7-111.3-76.2zM317 92.7l-69.9 82.8c-10.3-2.1-20.9-3.2-31.8-3.2-86.8 0-157.25 70.5-157.25 157.3C58.05 416 128.5 487 215.3 487s157.3-71 157.3-157.4c0-37.8-13.4-72.5-35.6-99.6l51.4-86.9L317 92.7zm7.4 39 29.5 19.5-46.5 78c26.1 23.9 42.5 58.2 42.5 96.4 0 72-58.5 130.4-130.6 130.4-72 0-130.55-58.4-130.55-130.4 0-72.1 58.55-130.6 130.55-130.6 22.6 0 43.9 5.8 62.5 15.9l42.6-79.2zm-31.5 180.5c-47.3-.7-126.2 58.3-178.3 13.5.1 57.7 47 104.3 104.7 104.3 56.1 0 102-44 104.6-99.5-7-13.2-17.8-18.1-31-18.3zm-11.5 23.3c5.1-.1 9.7 1.5 12.7 5 6.9 7.9 3.2 22.4-8.3 32.4-11.4 10-26.3 11.7-33.2 3.8-6.9-7.9-3.2-22.4 8.2-32.4 6.5-5.6 14-8.6 20.6-8.8zm-56.5 49.1c1.2 0 2.4.1 3.7.3 9.9 1.5 17.2 8.2 16.2 15.1-1 7-9.8 11-19.8 10-9.9-2-17.2-8-16.2-15.3.9-6 7.7-10.1 16.1-10.1z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="m381.7 27-14.5 20.4 49.5 35.1 14.5-20.3L381.7 27zm-57.4 12.3L310.2 60l111.3 76.2 14.1-20.7-111.3-76.2zM317 92.7l-69.9 82.8c-10.3-2.1-20.9-3.2-31.8-3.2-86.8 0-157.25 70.5-157.25 157.3C58.05 416 128.5 487 215.3 487s157.3-71 157.3-157.4c0-37.8-13.4-72.5-35.6-99.6l51.4-86.9L317 92.7zm7.4 39 29.5 19.5-46.5 78c26.1 23.9 42.5 58.2 42.5 96.4 0 72-58.5 130.4-130.6 130.4-72 0-130.55-58.4-130.55-130.4 0-72.1 58.55-130.6 130.55-130.6 22.6 0 43.9 5.8 62.5 15.9l42.6-79.2zm-31.5 180.5c-47.3-.7-126.2 58.3-178.3 13.5.1 57.7 47 104.3 104.7 104.3 56.1 0 102-44 104.6-99.5-7-13.2-17.8-18.1-31-18.3zm-11.5 23.3c5.1-.1 9.7 1.5 12.7 5 6.9 7.9 3.2 22.4-8.3 32.4-11.4 10-26.3 11.7-33.2 3.8-6.9-7.9-3.2-22.4 8.2-32.4 6.5-5.6 14-8.6 20.6-8.8zm-56.5 49.1c1.2 0 2.4.1 3.7.3 9.9 1.5 17.2 8.2 16.2 15.1-1 7-9.8 11-19.8 10-9.9-2-17.2-8-16.2-15.3.9-6 7.7-10.1 16.1-10.1z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 1 KiB |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="m256.65 38.984-49.697 100.702-111.13 16.146 80.413 78.385-18.982 110.68 99.396-52.256 99.397 52.256-18.983-110.68 80.413-78.384-111.127-16.146-49.7-100.702zM112 308.826l-26.674 54.05-59.646 8.665 43.16 42.073-10.188 59.403L112 444.97l53.348 28.046-10.188-59.403 43.16-42.072-59.646-8.665L112 308.825zm288 0-26.674 54.05-59.646 8.665 43.16 42.073-10.188 59.403L400 444.97l53.348 28.046-10.188-59.403 43.16-42.072-59.646-8.665L400 308.825z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="m256.65 38.984-49.697 100.702-111.13 16.146 80.413 78.385-18.982 110.68 99.396-52.256 99.397 52.256-18.983-110.68 80.413-78.384-111.127-16.146-49.7-100.702zM112 308.826l-26.674 54.05-59.646 8.665 43.16 42.073-10.188 59.403L112 444.97l53.348 28.046-10.188-59.403 43.16-42.072-59.646-8.665L112 308.825zm288 0-26.674 54.05-59.646 8.665 43.16 42.073-10.188 59.403L400 444.97l53.348 28.046-10.188-59.403 43.16-42.072-59.646-8.665L400 308.825z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 641 B After Width: | Height: | Size: 629 B |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="m109.902 35.87-71.14 59.284h142.28l-71.14-59.285zm288 32-71.14 59.284h142.28l-71.14-59.285zM228.73 84.403l-108.9 90.75h217.8l-108.9-90.75zm-173.828 28.75v62h36.81l73.19-60.992v-1.008h-110zm23 14h16v18h-16v-18zm265 18v10.963l23 19.166v-16.13h16v18h-13.756l.104.087 19.098 15.914h-44.446v14h78v-39h18v39h14v-62h-110zm-194.345 48v20.08l24.095-20.08h-24.095zm28.158 0 105.1 87.582 27.087-22.574v-65.008H176.715zm74.683 14h35.735v34h-35.735v-34zm-76.714 7.74L30.37 335.153H319l-144.314-120.26zm198.046 13.51-76.857 64.047 32.043 26.704H481.63l-108.9-90.75zm-23.214 108.75.103.086 19.095 15.914h-72.248v77.467h60.435v-63.466h50v63.467h46v-93.466H349.516zm-278.614 16V476.13h126v-76.976h50v76.977h31.565V353.155H70.902zm30 30h50v50h-50v-50z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="m109.902 35.87-71.14 59.284h142.28l-71.14-59.285zm288 32-71.14 59.284h142.28l-71.14-59.285zM228.73 84.403l-108.9 90.75h217.8l-108.9-90.75zm-173.828 28.75v62h36.81l73.19-60.992v-1.008h-110zm23 14h16v18h-16v-18zm265 18v10.963l23 19.166v-16.13h16v18h-13.756l.104.087 19.098 15.914h-44.446v14h78v-39h18v39h14v-62h-110zm-194.345 48v20.08l24.095-20.08h-24.095zm28.158 0 105.1 87.582 27.087-22.574v-65.008H176.715zm74.683 14h35.735v34h-35.735v-34zm-76.714 7.74L30.37 335.153H319l-144.314-120.26zm198.046 13.51-76.857 64.047 32.043 26.704H481.63l-108.9-90.75zm-23.214 108.75.103.086 19.095 15.914h-72.248v77.467h60.435v-63.466h50v63.467h46v-93.466H349.516zm-278.614 16V476.13h126v-76.976h50v76.977h31.565V353.155H70.902zm30 30h50v50h-50v-50z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 937 B After Width: | Height: | Size: 925 B |
|
|
@ -1 +1 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 512px; width: 512px;"><g class="" transform="translate(0,0)" style=""><path d="M179.3 38.94C154.7 77.7 142.7 139.7 168.4 185.9l-16.3 9.2c-6.7-11.9-11.2-24.4-13.9-37.2-34.5-6.3-69.42-7.5-104.98-2.1 34.07 10.1 52.77 23.7 76.68 46.7-26.82 9.7-60.25 30.2-92.93 70.2 35.47-8.8 64.83-11.5 89.43-6.3-36.94 22.5-64.06 56.1-88.34 114.1 35.9-17.2 64.89-18.8 102.94-18.8-23.07 32.7-35.27 77.2-36.31 112.8 24.51-26 57.61-60.2 87.21-79 3 29.9 15 58.3 35.9 85.3-.2-43.9 10.3-88.3 31.6-133.4-18.8 9-32.4 18.1-49.9 29.3 6.2-27.9 12.4-55.8 18.7-83.7-23.3 2.4-39 10-60.5 18.5 16.3-33.1 32.7-66.1 49.1-99.2l16.8 8.3-28.4 57.4c18.4-4.4 28.7-4.1 45.7-1.3-4.5 20.4-9 40.7-13.6 61 65.3-36.2 148.3-45.9 226.7-50 7.6-12.9 13.8-24.2 18.8-34.8l-6.3-24.4-24.4 30.8-7.8-27.5-22.5 29.2-7.5-26.1-23.9 31.5-7.7-28.2-23.8 31.4 1.2-41.1 22.6-42.7 7.6 28.3 23.9-31.5 7.6 28.2 23.5-30 6.5 26.9 24.5-30.8 7.8 27.5 24.6-32c2.3-10.8 4.6-22.4 7.4-35.7-55.5-3.7-106.3 4.8-154 9.8-38-20.8-80.8-26.8-121.9-18.5-13.6-29.69-27.2-59.38-40.9-89.06zM325.5 158.3c-4.5 14.2-13 18.3-24.7 20.6-16.1-4.4-28.3-15.5-34.4-30.2 20.4-3.8 42.4 3.4 59.1 9.6z" fill="#fff" fill-opacity="1"></path></g></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512"><g class="" transform="translate(0,0)" style=""><path d="M179.3 38.94C154.7 77.7 142.7 139.7 168.4 185.9l-16.3 9.2c-6.7-11.9-11.2-24.4-13.9-37.2-34.5-6.3-69.42-7.5-104.98-2.1 34.07 10.1 52.77 23.7 76.68 46.7-26.82 9.7-60.25 30.2-92.93 70.2 35.47-8.8 64.83-11.5 89.43-6.3-36.94 22.5-64.06 56.1-88.34 114.1 35.9-17.2 64.89-18.8 102.94-18.8-23.07 32.7-35.27 77.2-36.31 112.8 24.51-26 57.61-60.2 87.21-79 3 29.9 15 58.3 35.9 85.3-.2-43.9 10.3-88.3 31.6-133.4-18.8 9-32.4 18.1-49.9 29.3 6.2-27.9 12.4-55.8 18.7-83.7-23.3 2.4-39 10-60.5 18.5 16.3-33.1 32.7-66.1 49.1-99.2l16.8 8.3-28.4 57.4c18.4-4.4 28.7-4.1 45.7-1.3-4.5 20.4-9 40.7-13.6 61 65.3-36.2 148.3-45.9 226.7-50 7.6-12.9 13.8-24.2 18.8-34.8l-6.3-24.4-24.4 30.8-7.8-27.5-22.5 29.2-7.5-26.1-23.9 31.5-7.7-28.2-23.8 31.4 1.2-41.1 22.6-42.7 7.6 28.3 23.9-31.5 7.6 28.2 23.5-30 6.5 26.9 24.5-30.8 7.8 27.5 24.6-32c2.3-10.8 4.6-22.4 7.4-35.7-55.5-3.7-106.3 4.8-154 9.8-38-20.8-80.8-26.8-121.9-18.5-13.6-29.69-27.2-59.38-40.9-89.06zM325.5 158.3c-4.5 14.2-13 18.3-24.7 20.6-16.1-4.4-28.3-15.5-34.4-30.2 20.4-3.8 42.4 3.4 59.1 9.6z" fill="#fff" fill-opacity="1"></path></g></svg>
|
||||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
64
daggerheart.d.ts
vendored
|
|
@ -1,8 +1,12 @@
|
||||||
import '@client/global.mjs';
|
import '@client/global.mjs';
|
||||||
|
import '@common/global.mjs';
|
||||||
|
import '@common/primitives/global.mjs';
|
||||||
import Canvas from '@client/canvas/board.mjs';
|
import Canvas from '@client/canvas/board.mjs';
|
||||||
|
import { ResourceUpdateMap } from './module/data/action/baseAction.mjs';
|
||||||
|
|
||||||
// Foundry's use of `Object.assign(globalThis) means many globally available objects are not read as such
|
// Foundry's use of `Object.assign(globalThis) means many globally available objects are not read as such
|
||||||
// This declare global hopefully fixes that
|
// This declare global hopefully fixes that
|
||||||
|
// Note: eslint is not aware of these, whatever is added here should go in the eslint's globals list
|
||||||
declare global {
|
declare global {
|
||||||
/**
|
/**
|
||||||
* A simple event framework used throughout Foundry Virtual Tabletop.
|
* A simple event framework used throughout Foundry Virtual Tabletop.
|
||||||
|
|
@ -12,9 +16,67 @@ declare global {
|
||||||
class Hooks extends foundry.helpers.Hooks {}
|
class Hooks extends foundry.helpers.Hooks {}
|
||||||
const fromUuid = foundry.utils.fromUuid;
|
const fromUuid = foundry.utils.fromUuid;
|
||||||
const fromUuidSync = foundry.utils.fromUuidSync;
|
const fromUuidSync = foundry.utils.fromUuidSync;
|
||||||
|
/**
|
||||||
|
* A representation of a color in hexadecimal format.
|
||||||
|
* This class provides methods for transformations and manipulations of colors.
|
||||||
|
*/
|
||||||
|
class Color extends foundry.utils.Color {}
|
||||||
/**
|
/**
|
||||||
* The singleton game canvas
|
* The singleton game canvas
|
||||||
*/
|
*/
|
||||||
const canvas: Canvas;
|
const canvas: Canvas;
|
||||||
|
|
||||||
|
const ActiveEffect: foundry.documents.ActiveEffect;
|
||||||
|
const Actor: foundry.documents.Actor;
|
||||||
|
const BaseScene: foundry.documents.BaseScene;
|
||||||
|
const ChatMessage: foundry.documents.ChatMessage;
|
||||||
|
const Combat: foundry.documents.Combat;
|
||||||
|
const Combatant: foundry.documents.Combatant;
|
||||||
|
const Item: foundry.documents.Item;
|
||||||
|
const Macro: foundry.documents.Macro;
|
||||||
|
const Scene: foundry.documents.Scene;
|
||||||
|
const TokenDocument: foundry.documents.TokenDocument;
|
||||||
|
|
||||||
|
const Collection: foundry.utils.Collection;
|
||||||
|
const FormDataExtended: foundry.applications.ux.FormDataExtended;
|
||||||
|
const TextEditor: foundry.applications.ux.TextEditor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data used to build rolls such as duality rolls. The definition is incomplete and likely incorrect.
|
||||||
|
* Objects will often accept a Partial<RollConfig> and spit out a non-partial. Those that are not guaranteed should be marked optional.
|
||||||
|
*/
|
||||||
|
interface RollConfig {
|
||||||
|
// unverified, check which ones are used and optional/not optional
|
||||||
|
event: Event;
|
||||||
|
title: string;
|
||||||
|
roll: {
|
||||||
|
modifier: number;
|
||||||
|
simple: boolean;
|
||||||
|
type: string;
|
||||||
|
difficulty: number;
|
||||||
|
};
|
||||||
|
hasDamage: boolean;
|
||||||
|
hasEffect: boolean;
|
||||||
|
hasRoll: boolean;
|
||||||
|
chatMessage: {
|
||||||
|
template: string;
|
||||||
|
mute: boolean;
|
||||||
|
};
|
||||||
|
targets: object;
|
||||||
|
costs: object;
|
||||||
|
|
||||||
|
// verified
|
||||||
|
source?: {
|
||||||
|
/** uuid of the actor this roll is coming from */
|
||||||
|
actor: string;
|
||||||
|
};
|
||||||
|
/** Roll data associated with the actor or item */
|
||||||
|
data: object;
|
||||||
|
resourceUpdates: ResourceUpdateMap;
|
||||||
|
hooks: string[];
|
||||||
|
dialog: {
|
||||||
|
configure: boolean;
|
||||||
|
};
|
||||||
|
damageOptions: object;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,20 @@ CONFIG.Token.prototypeSheetClass = applications.sheetConfigs.DhPrototypeTokenCon
|
||||||
CONFIG.Token.objectClass = placeables.DhTokenPlaceable;
|
CONFIG.Token.objectClass = placeables.DhTokenPlaceable;
|
||||||
CONFIG.Token.rulerClass = placeables.DhTokenRuler;
|
CONFIG.Token.rulerClass = placeables.DhTokenRuler;
|
||||||
CONFIG.Token.hudClass = applications.hud.DHTokenHUD;
|
CONFIG.Token.hudClass = applications.hud.DHTokenHUD;
|
||||||
|
CONFIG.Token.barConfig = {
|
||||||
|
bar1: {
|
||||||
|
colors: {
|
||||||
|
full: Color.fromRGB([1, 0, 0]),
|
||||||
|
empty: Color.fromRGB([0, 0, 0])
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bar2: {
|
||||||
|
colors: {
|
||||||
|
full: Color.fromString('#0032b1'),
|
||||||
|
empty: Color.fromRGB([0, 0, 0])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CONFIG.ui.combat = applications.ui.DhCombatTracker;
|
CONFIG.ui.combat = applications.ui.DhCombatTracker;
|
||||||
CONFIG.ui.nav = applications.ui.DhSceneNavigation;
|
CONFIG.ui.nav = applications.ui.DhSceneNavigation;
|
||||||
|
|
@ -88,6 +102,7 @@ CONFIG.ui.actors = applications.sidebar.DhActorDirectory;
|
||||||
CONFIG.ui.daggerheartMenu = applications.sidebar.DaggerheartMenu;
|
CONFIG.ui.daggerheartMenu = applications.sidebar.DaggerheartMenu;
|
||||||
CONFIG.ui.resources = applications.ui.DhFearTracker;
|
CONFIG.ui.resources = applications.ui.DhFearTracker;
|
||||||
CONFIG.ui.countdowns = applications.ui.DhCountdowns;
|
CONFIG.ui.countdowns = applications.ui.DhCountdowns;
|
||||||
|
CONFIG.ui.pause = applications.ui.DhGamePause;
|
||||||
CONFIG.ux.ContextMenu = applications.ux.DHContextMenu;
|
CONFIG.ux.ContextMenu = applications.ux.DHContextMenu;
|
||||||
CONFIG.ux.TooltipManager = documents.DhTooltipManager;
|
CONFIG.ux.TooltipManager = documents.DhTooltipManager;
|
||||||
CONFIG.ux.TokenManager = new TokenManager();
|
CONFIG.ux.TokenManager = new TokenManager();
|
||||||
|
|
@ -453,8 +468,8 @@ Hooks.on('renderDialogV2', (_dialog, html) => {
|
||||||
const cls = html.classList.contains('item-create')
|
const cls = html.classList.contains('item-create')
|
||||||
? documents.DHItem.implementation
|
? documents.DHItem.implementation
|
||||||
: html.classList.contains('actor-create')
|
: html.classList.contains('actor-create')
|
||||||
? documents.DhpActor.implementation
|
? documents.DhpActor.implementation
|
||||||
: null;
|
: null;
|
||||||
if (!cls) return;
|
if (!cls) return;
|
||||||
|
|
||||||
const form = html.querySelector('form');
|
const form = html.querySelector('form');
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,115 @@
|
||||||
import globals from 'globals';
|
import globals from 'globals';
|
||||||
import { defineConfig } from 'eslint/config';
|
import { defineConfig, globalIgnores } from 'eslint/config';
|
||||||
import prettier from 'eslint-plugin-prettier';
|
import tseslint from 'typescript-eslint';
|
||||||
|
import js from '@eslint/js';
|
||||||
|
import stylistic from '@stylistic/eslint-plugin';
|
||||||
|
|
||||||
|
/** @type {Partial<RulesConfig>} */
|
||||||
|
export const stylisticRules = {
|
||||||
|
'@stylistic/indent': [
|
||||||
|
'error',
|
||||||
|
4,
|
||||||
|
{
|
||||||
|
SwitchCase: 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'@stylistic/max-len': ['error', {
|
||||||
|
code: 120,
|
||||||
|
ignoreComments: true,
|
||||||
|
ignoreStrings: true,
|
||||||
|
ignoreTemplateLiterals: true,
|
||||||
|
ignoreRegExpLiterals: true
|
||||||
|
}],
|
||||||
|
'@stylistic/quotes': ['error', 'single', { allowTemplateLiterals: 'always' }],
|
||||||
|
'@stylistic/arrow-parens': ['error', 'as-needed'],
|
||||||
|
'@stylistic/quote-props': ['error', 'as-needed'],
|
||||||
|
'@stylistic/array-bracket-newline': ['error', 'consistent'],
|
||||||
|
'@stylistic/key-spacing': 'error',
|
||||||
|
'@stylistic/comma-dangle': ['error', 'never'],
|
||||||
|
'@stylistic/space-in-parens': ['error', 'never'],
|
||||||
|
'@stylistic/space-infix-ops': 2,
|
||||||
|
'@stylistic/keyword-spacing': 2,
|
||||||
|
'@stylistic/semi-spacing': 2,
|
||||||
|
'@stylistic/no-multi-spaces': 2,
|
||||||
|
'@stylistic/no-extra-semi': 2,
|
||||||
|
'@stylistic/no-whitespace-before-property': 2,
|
||||||
|
'@stylistic/space-unary-ops': 2
|
||||||
|
};
|
||||||
|
|
||||||
export default defineConfig([
|
export default defineConfig([
|
||||||
{ files: ['**/*.{js,mjs,cjs}'], languageOptions: { globals: globals.browser } },
|
globalIgnores(['foundry/**/*', 'build/**/*']),
|
||||||
{ plugins: { prettier } },
|
{
|
||||||
|
files: ['gulpfile.js', 'postcss.config.js'],
|
||||||
|
languageOptions: { globals: globals.node }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
files: ['**/*.{js,mjs,cjs}'],
|
files: ['**/*.{js,mjs,cjs}'],
|
||||||
|
plugins: {
|
||||||
|
'@stylistic': stylistic
|
||||||
|
},
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.browser,
|
||||||
|
CONFIG: 'readonly',
|
||||||
|
CONST: 'readonly',
|
||||||
|
// Global classes
|
||||||
|
Color: 'readonly',
|
||||||
|
Handlebars: 'readonly',
|
||||||
|
Hooks: 'readonly',
|
||||||
|
PIXI: 'readonly',
|
||||||
|
ProseMirror: 'readonly',
|
||||||
|
Roll: 'readonly',
|
||||||
|
// global namespaces
|
||||||
|
canvas: 'readonly',
|
||||||
|
foundry: 'readonly',
|
||||||
|
game: 'readonly',
|
||||||
|
ui: 'readonly',
|
||||||
|
// global functions
|
||||||
|
fromUuid: 'readonly',
|
||||||
|
fromUuidSync: 'readonly',
|
||||||
|
getDocumentClass: 'readonly',
|
||||||
|
_del: 'readonly',
|
||||||
|
_replace: 'readonly',
|
||||||
|
_loc: 'readonly',
|
||||||
|
// Documents
|
||||||
|
ActiveEffect: 'readonly',
|
||||||
|
Actor: 'readonly',
|
||||||
|
BaseScene: 'readonly',
|
||||||
|
ChatMessage: 'readonly',
|
||||||
|
Combat: 'readonly',
|
||||||
|
Combatant: 'readonly',
|
||||||
|
Item: 'readonly',
|
||||||
|
Macro: 'readonly',
|
||||||
|
Scene: 'readonly',
|
||||||
|
TokenDocument: 'readonly',
|
||||||
|
// Other
|
||||||
|
Collection: 'readonly',
|
||||||
|
FormDataExtended: 'readonly',
|
||||||
|
TextEditor: 'readonly'
|
||||||
|
}
|
||||||
|
},
|
||||||
rules: {
|
rules: {
|
||||||
'prettier/prettier': 'error'
|
'no-undef': 'error',
|
||||||
|
'no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
args: 'none',
|
||||||
|
destructuredArrayIgnorePattern: '^_',
|
||||||
|
varsIgnorePattern: '^_[A-Z]',
|
||||||
|
ignoreRestSiblings: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
...stylisticRules
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['**/*.ts'],
|
||||||
|
extends: [js.configs.recommended, tseslint.configs.recommended],
|
||||||
|
plugins: {
|
||||||
|
'@stylistic': stylistic
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
...stylisticRules
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "ES6",
|
"module": "es2022",
|
||||||
"target": "ES6",
|
"target": "es2022",
|
||||||
"paths": {
|
"paths": {
|
||||||
"@client/*": ["./foundry/client/*"],
|
"@client/*": ["./foundry/client/*"],
|
||||||
"@common/*": ["./foundry/common/*"]
|
"@common/*": ["./foundry/common/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exclude": ["node_modules", "**/node_modules/*"],
|
"exclude": ["node_modules", "**/node_modules/*"],
|
||||||
"include": ["daggerheart.mjs", "foundry/client/client.mjs", "daggerheart.d.ts"],
|
"include": ["daggerheart.mjs", "foundry/client/client.mjs", "daggerheart.d.ts", "module/**/*.d.ts"],
|
||||||
"typeAcquisition": {
|
"typeAcquisition": {
|
||||||
"include": ["jquery"]
|
"include": ["jquery"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
16
lang/en.json
|
|
@ -484,7 +484,6 @@
|
||||||
"startFormula": "Randomized Start Value Formula",
|
"startFormula": "Randomized Start Value Formula",
|
||||||
"currentCountdownCurrent": "Current: {value}",
|
"currentCountdownCurrent": "Current: {value}",
|
||||||
"currentCountdownStart": "Start: {value}",
|
"currentCountdownStart": "Start: {value}",
|
||||||
"category": "Category",
|
|
||||||
"progressionType": "Progression",
|
"progressionType": "Progression",
|
||||||
"decreasing": "Decreasing",
|
"decreasing": "Decreasing",
|
||||||
"looping": "Looping",
|
"looping": "Looping",
|
||||||
|
|
@ -1162,7 +1161,7 @@
|
||||||
"autoAppliedByLabel": "Max Stress"
|
"autoAppliedByLabel": "Max Stress"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"CountdownType": {
|
"CountdownProgressType": {
|
||||||
"actionRoll": "Action Roll",
|
"actionRoll": "Action Roll",
|
||||||
"characterAttack": "Character Attack",
|
"characterAttack": "Character Attack",
|
||||||
"characterSpotlight": "Character Spotlight",
|
"characterSpotlight": "Character Spotlight",
|
||||||
|
|
@ -1170,6 +1169,10 @@
|
||||||
"fear": "Fear",
|
"fear": "Fear",
|
||||||
"spotlight": "Spotlight"
|
"spotlight": "Spotlight"
|
||||||
},
|
},
|
||||||
|
"CountdownType": {
|
||||||
|
"encounter": { "label": "Short Term", "shortLabel": "Short" },
|
||||||
|
"narrative": { "label": "Long Term", "shortLabel": "Long" }
|
||||||
|
},
|
||||||
"DaggerheartDiceAnimationEvents": {
|
"DaggerheartDiceAnimationEvents": {
|
||||||
"critical": { "name": "Critical" },
|
"critical": { "name": "Critical" },
|
||||||
"higher": { "name": "Highest Roll" }
|
"higher": { "name": "Highest Roll" }
|
||||||
|
|
@ -1455,7 +1458,7 @@
|
||||||
},
|
},
|
||||||
"triggerType": "Trigger Type",
|
"triggerType": "Trigger Type",
|
||||||
"triggeringActorType": "Triggering Actor Type",
|
"triggeringActorType": "Triggering Actor Type",
|
||||||
"triggerError": "{trigger} trigger failed for {actor}. It's probably configured wrong."
|
"triggerError": "{trigger} trigger on {item}({itemUuid}) failed for {actor}. It's probably configured wrong."
|
||||||
},
|
},
|
||||||
"WeaponFeature": {
|
"WeaponFeature": {
|
||||||
"barrier": {
|
"barrier": {
|
||||||
|
|
@ -2014,7 +2017,8 @@
|
||||||
"Attachments": {
|
"Attachments": {
|
||||||
"attachHint": "Drop items here to attach them",
|
"attachHint": "Drop items here to attach them",
|
||||||
"transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one."
|
"transferHint": "If checked, this effect will be applied to any actor that owns this Effect's parent Item. The effect is always applied if this Item is attached to another one."
|
||||||
}
|
},
|
||||||
|
"OriginTag": "Origin: {name}"
|
||||||
},
|
},
|
||||||
"GENERAL": {
|
"GENERAL": {
|
||||||
"Ability": {
|
"Ability": {
|
||||||
|
|
@ -2896,7 +2900,9 @@
|
||||||
"iconName": "Icon Name",
|
"iconName": "Icon Name",
|
||||||
"iconNameHint": "Icons are from fontawesome",
|
"iconNameHint": "Icons are from fontawesome",
|
||||||
"bagName": "Bag Name",
|
"bagName": "Bag Name",
|
||||||
"chestName": "Chest Name"
|
"chestName": "Chest Name",
|
||||||
|
"denomination": "Denomination",
|
||||||
|
"initialAmount": "Starting Amount"
|
||||||
},
|
},
|
||||||
"domains": {
|
"domains": {
|
||||||
"domainsTitle": "Base Domains",
|
"domainsTitle": "Base Domains",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { abilities } from '../../config/actorConfig.mjs';
|
import { abilities } from '../../config/actorConfig.mjs';
|
||||||
import { burden } from '../../config/generalConfig.mjs';
|
import { burden } from '../../config/generalConfig.mjs';
|
||||||
import { createEmbeddedItemsWithEffects, createEmbeddedItemWithEffects } from '../../helpers/utils.mjs';
|
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
|
|
@ -154,8 +153,8 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
v.active = this.tabGroups[v.group]
|
v.active = this.tabGroups[v.group]
|
||||||
? this.tabGroups[v.group] === v.id
|
? this.tabGroups[v.group] === v.id
|
||||||
: this.tabGroups.primary !== 'equipment'
|
: this.tabGroups.primary !== 'equipment'
|
||||||
? v.active
|
? v.active
|
||||||
: false;
|
: false;
|
||||||
v.cssClass = v.active ? 'active' : '';
|
v.cssClass = v.active ? 'active' : '';
|
||||||
|
|
||||||
switch (v.id) {
|
switch (v.id) {
|
||||||
|
|
@ -211,9 +210,9 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
|
|
||||||
context.suggestedTraits = this.setup.class.system
|
context.suggestedTraits = this.setup.class.system
|
||||||
? Object.keys(this.setup.class.system.characterGuide.suggestedTraits).map(traitKey => {
|
? Object.keys(this.setup.class.system.characterGuide.suggestedTraits).map(traitKey => {
|
||||||
const trait = this.setup.class.system.characterGuide.suggestedTraits[traitKey];
|
const trait = this.setup.class.system.characterGuide.suggestedTraits[traitKey];
|
||||||
return `${game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${traitKey}.short`)} ${trait > 0 ? `+${trait}` : trait}`;
|
return `${game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${traitKey}.short`)} ${trait > 0 ? `+${trait}` : trait}`;
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
context.traits = {
|
context.traits = {
|
||||||
values: Object.keys(this.setup.traits).map(traitKey => {
|
values: Object.keys(this.setup.traits).map(traitKey => {
|
||||||
|
|
@ -441,16 +440,15 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
|
|
||||||
if (type === 'subclasses') {
|
if (type === 'subclasses') {
|
||||||
const classItem = this.setup.class;
|
const classItem = this.setup.class;
|
||||||
const uuid = classItem?._stats.compendiumSource ?? classItem?.uuid;
|
|
||||||
presets.filter = {
|
presets.filter = {
|
||||||
'system.linkedClass': { key: 'system.linkedClass', value: uuid }
|
'system.linkedClass': { key: 'system.linkedClass', value: classItem?.sourceUuid }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (equipment.includes(type))
|
if (equipment.includes(type))
|
||||||
presets.filter = {
|
presets.filter = {
|
||||||
'system.tier': { key: 'system.tier', value: 1 },
|
'system.tier': { key: 'system.tier', value: 1 },
|
||||||
'type': { key: 'type', value: type }
|
type: { key: 'type', value: type }
|
||||||
};
|
};
|
||||||
|
|
||||||
ui.compendiumBrowser.open(presets);
|
ui.compendiumBrowser.open(presets);
|
||||||
|
|
@ -524,37 +522,52 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
await createEmbeddedItemWithEffects(this.character, ancestry);
|
// Inner function to create the base item data
|
||||||
await createEmbeddedItemWithEffects(this.character, this.setup.community);
|
async function createEmbeddedItemData(baseData) {
|
||||||
await createEmbeddedItemWithEffects(this.character, this.setup.class);
|
const uuid = baseData.uuid ?? baseData._uuid
|
||||||
await createEmbeddedItemWithEffects(this.character, this.setup.subclass);
|
const data = baseData instanceof Item ? baseData : await foundry.utils.fromUuid(baseData.uuid) ?? baseData;
|
||||||
await createEmbeddedItemsWithEffects(this.character, Object.values(this.setup.domainCards));
|
return {
|
||||||
|
...baseData,
|
||||||
|
id: data.id,
|
||||||
|
uuid: uuid,
|
||||||
|
_uuid: uuid,
|
||||||
|
effects: data.effects?.map(effect => effect.toObject()),
|
||||||
|
flags: baseData.flags ?? data.flags,
|
||||||
|
_stats: {
|
||||||
|
...data._stats,
|
||||||
|
compendiumSource: uuid.startsWith('Compendium.') ? uuid : null,
|
||||||
|
duplicateSource: uuid && !uuid.startsWith('Compendium.') ? uuid : null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the class first. All other items validate it during pre creation
|
||||||
|
await this.character.createEmbeddedDocuments('Item', [await createEmbeddedItemData(this.setup.class)]);
|
||||||
|
|
||||||
|
// Add the remaining items
|
||||||
|
const newItems = [
|
||||||
|
await createEmbeddedItemData(ancestry),
|
||||||
|
await createEmbeddedItemData(this.setup.community),
|
||||||
|
await createEmbeddedItemData(this.setup.subclass),
|
||||||
|
...(await Promise.all(
|
||||||
|
Object.values(this.setup.domainCards).map(d => createEmbeddedItemData(d))
|
||||||
|
))
|
||||||
|
];
|
||||||
if (this.equipment.armor.uuid)
|
if (this.equipment.armor.uuid)
|
||||||
await createEmbeddedItemWithEffects(this.character, this.equipment.armor, {
|
newItems.push(await createEmbeddedItemData(this.equipment.armor));
|
||||||
...this.equipment.armor,
|
|
||||||
system: { ...this.equipment.armor.system, equipped: true }
|
|
||||||
});
|
|
||||||
if (this.equipment.primaryWeapon.uuid)
|
if (this.equipment.primaryWeapon.uuid)
|
||||||
await createEmbeddedItemWithEffects(this.character, this.equipment.primaryWeapon, {
|
newItems.push(await createEmbeddedItemData(this.equipment.primaryWeapon));
|
||||||
...this.equipment.primaryWeapon,
|
|
||||||
system: { ...this.equipment.primaryWeapon.system, equipped: true }
|
|
||||||
});
|
|
||||||
if (this.equipment.secondaryWeapon.uuid)
|
if (this.equipment.secondaryWeapon.uuid)
|
||||||
await createEmbeddedItemWithEffects(this.character, this.equipment.secondaryWeapon, {
|
newItems.push(await createEmbeddedItemData(this.equipment.secondaryWeapon));
|
||||||
...this.equipment.secondaryWeapon,
|
|
||||||
system: { ...this.equipment.secondaryWeapon.system, equipped: true }
|
|
||||||
});
|
|
||||||
if (this.equipment.inventory.choiceA.uuid)
|
if (this.equipment.inventory.choiceA.uuid)
|
||||||
await createEmbeddedItemWithEffects(this.character, this.equipment.inventory.choiceA);
|
newItems.push(await createEmbeddedItemData(this.equipment.inventory.choiceA));
|
||||||
if (this.equipment.inventory.choiceB.uuid)
|
if (this.equipment.inventory.choiceB.uuid)
|
||||||
await createEmbeddedItemWithEffects(this.character, this.equipment.inventory.choiceB);
|
newItems.push(await createEmbeddedItemData(this.equipment.inventory.choiceB));
|
||||||
|
for (const item of this.setup.class.system.inventory.take.filter(x => x)) {
|
||||||
await createEmbeddedItemsWithEffects(
|
newItems.push(await createEmbeddedItemData(item));
|
||||||
this.character,
|
}
|
||||||
this.setup.class.system.inventory.take.filter(x => x)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
await this.character.createEmbeddedDocuments('Item', newItems);
|
||||||
await this.character.update(
|
await this.character.update(
|
||||||
{
|
{
|
||||||
system: {
|
system: {
|
||||||
|
|
@ -587,26 +600,14 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
const item = await foundry.utils.fromUuid(data.uuid);
|
const item = await foundry.utils.fromUuid(data.uuid);
|
||||||
if (item.type === 'ancestry' && event.target.closest('.primary-ancestry-card')) {
|
if (item.type === 'ancestry' && event.target.closest('.primary-ancestry-card')) {
|
||||||
this.setup.ancestryName.primary = item.name;
|
this.setup.ancestryName.primary = item.name;
|
||||||
this.setup.primaryAncestry = {
|
this.setup.primaryAncestry = item;
|
||||||
...item,
|
|
||||||
effects: Array.from(item.effects).map(x => x.toObject()),
|
|
||||||
uuid: item.uuid
|
|
||||||
};
|
|
||||||
} else if (item.type === 'ancestry' && event.target.closest('.secondary-ancestry-card')) {
|
} else if (item.type === 'ancestry' && event.target.closest('.secondary-ancestry-card')) {
|
||||||
this.setup.ancestryName.secondary = item.name;
|
this.setup.ancestryName.secondary = item.name;
|
||||||
this.setup.secondaryAncestry = {
|
this.setup.secondaryAncestry = item;
|
||||||
...item,
|
|
||||||
effects: Array.from(item.effects).map(x => x.toObject()),
|
|
||||||
uuid: item.uuid
|
|
||||||
};
|
|
||||||
} else if (item.type === 'community' && event.target.closest('.community-card')) {
|
} else if (item.type === 'community' && event.target.closest('.community-card')) {
|
||||||
this.setup.community = {
|
this.setup.community = item;
|
||||||
...item,
|
|
||||||
effects: Array.from(item.effects).map(x => x.toObject()),
|
|
||||||
uuid: item.uuid
|
|
||||||
};
|
|
||||||
} else if (item.type === 'class' && event.target.closest('.class-card')) {
|
} else if (item.type === 'class' && event.target.closest('.class-card')) {
|
||||||
this.setup.class = { ...item, effects: Array.from(item.effects).map(x => x.toObject()), uuid: item.uuid };
|
this.setup.class = item;
|
||||||
this.setup.subclass = {};
|
this.setup.subclass = {};
|
||||||
this.setup.domainCards = {
|
this.setup.domainCards = {
|
||||||
[foundry.utils.randomID()]: {},
|
[foundry.utils.randomID()]: {},
|
||||||
|
|
@ -619,11 +620,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setup.subclass = {
|
this.setup.subclass = item;
|
||||||
...item,
|
|
||||||
effects: Array.from(item.effects).map(x => x.toObject()),
|
|
||||||
uuid: item.uuid
|
|
||||||
};
|
|
||||||
} else if (item.type === 'domainCard' && event.target.closest('.domain-card')) {
|
} else if (item.type === 'domainCard' && event.target.closest('.domain-card')) {
|
||||||
if (!this.setup.class.uuid) {
|
if (!this.setup.class.uuid) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.missingClass'));
|
||||||
|
|
@ -645,14 +642,14 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setup.domainCards[event.target.closest('.domain-card').dataset.card] = { ...item, uuid: item.uuid };
|
this.setup.domainCards[event.target.closest('.domain-card').dataset.card] = item;
|
||||||
} else if (item.type === 'armor' && event.target.closest('.armor-card')) {
|
} else if (item.type === 'armor' && event.target.closest('.armor-card')) {
|
||||||
if (item.system.tier > 1) {
|
if (item.system.tier > 1) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.itemTooHighTier'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.itemTooHighTier'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.equipment.armor = { ...item, uuid: item.uuid };
|
this.equipment.armor = item;
|
||||||
} else if (item.type === 'weapon' && event.target.closest('.primary-weapon-card')) {
|
} else if (item.type === 'weapon' && event.target.closest('.primary-weapon-card')) {
|
||||||
if (item.system.secondary) {
|
if (item.system.secondary) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.notPrimary'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.notPrimary'));
|
||||||
|
|
@ -668,7 +665,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
this.equipment.secondaryWeapon = {};
|
this.equipment.secondaryWeapon = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.equipment.primaryWeapon = { ...item, uuid: item.uuid };
|
this.equipment.primaryWeapon = item;
|
||||||
} else if (item.type === 'weapon' && event.target.closest('.secondary-weapon-card')) {
|
} else if (item.type === 'weapon' && event.target.closest('.secondary-weapon-card')) {
|
||||||
if (this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value) {
|
if (this.equipment.primaryWeapon?.system?.burden === burden.twoHanded.value) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.primaryIsTwoHanded'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.primaryIsTwoHanded'));
|
||||||
|
|
@ -685,7 +682,7 @@ export default class DhCharacterCreation extends HandlebarsApplicationMixin(Appl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.equipment.secondaryWeapon = { ...item, uuid: item.uuid };
|
this.equipment.secondaryWeapon = item;
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
}
|
}
|
||||||
if (rest.hasOwnProperty('trait')) {
|
if (rest.hasOwnProperty('trait')) {
|
||||||
this.config.roll.trait = rest.trait;
|
this.config.roll.trait = rest.trait;
|
||||||
if (!this.config.source.item)
|
if (!this.config.source.item && this.config.roll.trait)
|
||||||
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
this.config.title = game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
ability: game.i18n.localize(abilities[this.config.roll.trait]?.label)
|
||||||
});
|
});
|
||||||
|
|
@ -196,14 +196,14 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1
|
this.config.costs.indexOf(this.config.costs.find(c => c.extKey === button.dataset.key)) > -1
|
||||||
? this.config.costs.filter(x => x.extKey !== button.dataset.key)
|
? this.config.costs.filter(x => x.extKey !== button.dataset.key)
|
||||||
: [
|
: [
|
||||||
...this.config.costs,
|
...this.config.costs,
|
||||||
{
|
{
|
||||||
extKey: button.dataset.key,
|
extKey: button.dataset.key,
|
||||||
key: this.config?.data?.parent?.isNPC ? 'fear' : 'hope',
|
key: this.config?.data?.parent?.isNPC ? 'fear' : 'hope',
|
||||||
value: 1,
|
value: 1,
|
||||||
name: this.config.data?.system.experiences?.[button.dataset.key]?.name
|
name: this.config.data?.system.experiences?.[button.dataset.key]?.name
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -213,8 +213,8 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.config.actionType = this.reactionOverride
|
this.config.actionType = this.reactionOverride
|
||||||
? 'reaction'
|
? 'reaction'
|
||||||
: this.config.actionType === 'reaction'
|
: this.config.actionType === 'reaction'
|
||||||
? 'action'
|
? 'action'
|
||||||
: this.config.actionType;
|
: this.config.actionType;
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -224,7 +224,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async submitRoll() {
|
static async submitRoll(event) {
|
||||||
await this.close({ submitted: true });
|
await this.close({ submitted: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -138,13 +138,13 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
|
||||||
const stressReductionStress = this.availableStressReductions
|
const stressReductionStress = this.availableStressReductions
|
||||||
? stressReductions.reduce((acc, red) => acc + red.cost, 0)
|
? stressReductions.reduce((acc, red) => acc + red.cost, 0)
|
||||||
: 0;
|
: 0;
|
||||||
|
const stress = this.actor.system.resources.stress;
|
||||||
context.stress =
|
context.stress =
|
||||||
selectedStressMarks.length > 0 || this.availableStressReductions
|
selectedStressMarks.length > 0 || this.availableStressReductions
|
||||||
? {
|
? {
|
||||||
value:
|
value: stress.value + selectedStressMarks.length + stressReductionStress,
|
||||||
this.actor.system.resources.stress.value + selectedStressMarks.length + stressReductionStress,
|
max: stress.max
|
||||||
max: this.actor.system.resources.stress.max
|
}
|
||||||
}
|
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
context.maxArmorUsed = maxArmorUsed;
|
context.maxArmorUsed = maxArmorUsed;
|
||||||
|
|
@ -176,7 +176,6 @@ export default class DamageReductionDialog extends HandlebarsApplicationMixin(Ap
|
||||||
}
|
}
|
||||||
|
|
||||||
static updateData(event, _, formData) {
|
static updateData(event, _, formData) {
|
||||||
const form = foundry.utils.expandObject(formData.object);
|
|
||||||
this.render(true);
|
this.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -259,10 +259,10 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV
|
||||||
const resetValue = increasing
|
const resetValue = increasing
|
||||||
? 0
|
? 0
|
||||||
: feature.system.resource.max
|
: feature.system.resource.max
|
||||||
? new Roll(
|
? new Roll(
|
||||||
Roll.replaceFormulaData(feature.system.resource.max, this.actor.getRollData())
|
Roll.replaceFormulaData(feature.system.resource.max, this.actor.getRollData())
|
||||||
).evaluateSync().total
|
).evaluateSync().total
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
await feature.update({ 'system.resource.value': resetValue });
|
await feature.update({ 'system.resource.value': resetValue });
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
||||||
|
import { shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
||||||
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||||
import Party from '../sheets/actors/party.mjs';
|
import Party from '../sheets/actors/party.mjs';
|
||||||
|
|
||||||
|
|
@ -167,8 +168,8 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
partContext.groupRoll = {
|
partContext.groupRoll = {
|
||||||
totalLabel: leader?.rollData
|
totalLabel: leader?.rollData
|
||||||
? game.i18n.format('DAGGERHEART.GENERAL.withThing', {
|
? game.i18n.format('DAGGERHEART.GENERAL.withThing', {
|
||||||
thing: leader.roll.totalLabel
|
thing: leader.roll.totalLabel
|
||||||
})
|
})
|
||||||
: null,
|
: null,
|
||||||
totalDualityClass: leader?.roll?.isCritical ? 'critical' : leader?.roll?.withHope ? 'hope' : 'fear',
|
totalDualityClass: leader?.roll?.isCritical ? 'critical' : leader?.roll?.withHope ? 'hope' : 'fear',
|
||||||
total: leaderTotal + modifierTotal,
|
total: leaderTotal + modifierTotal,
|
||||||
|
|
@ -480,19 +481,22 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat
|
||||||
|
|
||||||
await cls.create(msgData);
|
await cls.create(msgData);
|
||||||
|
|
||||||
const resourceMap = new ResourceUpdateMap(actor);
|
/* Handle resource updates for the finished GroupRoll */
|
||||||
if (totalRoll.isCritical) {
|
if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) {
|
||||||
resourceMap.addResources([
|
const resourceMap = new ResourceUpdateMap(actor);
|
||||||
{ key: 'stress', value: -1, total: 1 },
|
if (totalRoll.isCritical) {
|
||||||
{ key: 'hope', value: 1, total: 1 }
|
resourceMap.addResources([
|
||||||
]);
|
{ key: 'stress', value: -1 },
|
||||||
} else if (totalRoll.withHope) {
|
{ key: 'hope', value: 1 }
|
||||||
resourceMap.addResources([{ key: 'hope', value: 1, total: 1 }]);
|
]);
|
||||||
} else {
|
} else if (totalRoll.withHope) {
|
||||||
resourceMap.addResources([{ key: 'fear', value: 1, total: 1 }]);
|
resourceMap.addResources([{ key: 'hope', value: 1 }]);
|
||||||
}
|
} else {
|
||||||
|
resourceMap.addResources([{ key: 'fear', value: 1 }]);
|
||||||
|
}
|
||||||
|
|
||||||
resourceMap.updateResources();
|
resourceMap.updateResources();
|
||||||
|
}
|
||||||
|
|
||||||
/* Fin */
|
/* Fin */
|
||||||
this.cancelRoll({ confirm: false });
|
this.cancelRoll({ confirm: false });
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ export default class ItemTransferDialog extends HandlebarsApplicationMixin(Appli
|
||||||
const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew;
|
const homebrewKey = CONFIG.DH.SETTINGS.gameSettings.Homebrew;
|
||||||
const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null;
|
const currencySetting = game.settings.get(CONFIG.DH.id, homebrewKey).currency?.[currency] ?? null;
|
||||||
const max = item?.system.quantity ?? originActor.system.gold[currency] ?? 0;
|
const max = item?.system.quantity ?? originActor.system.gold[currency] ?? 0;
|
||||||
|
const isQuantifiable = targetActor.system.metadata.quantifiable?.includes(item?.type);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
originActor,
|
originActor,
|
||||||
|
|
@ -46,7 +47,7 @@ export default class ItemTransferDialog extends HandlebarsApplicationMixin(Appli
|
||||||
itemImage: item?.img,
|
itemImage: item?.img,
|
||||||
currencyIcon: currencySetting?.icon,
|
currencyIcon: currencySetting?.icon,
|
||||||
max,
|
max,
|
||||||
initial: targetActor.system.metadata.quantifiable?.includes(item.type) ? max : 1,
|
initial: isQuantifiable || !!currencySetting ? max : 1,
|
||||||
title: item?.name ?? currencySetting?.label
|
title: item?.name ?? currencySetting?.label
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
|
import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
|
||||||
import { MemberData } from '../../data/tagTeamData.mjs';
|
import { MemberData } from '../../data/tagTeamData.mjs';
|
||||||
import { getCritDamageBonus } from '../../helpers/utils.mjs';
|
import { getCritDamageBonus, shouldUseHopeFearAutomation } from '../../helpers/utils.mjs';
|
||||||
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
import { emitGMUpdate, GMUpdateEvent, RefreshType, socketEvent } from '../../systemRegistration/socket.mjs';
|
||||||
import Party from '../sheets/actors/party.mjs';
|
import Party from '../sheets/actors/party.mjs';
|
||||||
|
|
||||||
|
|
@ -9,6 +10,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
constructor(party) {
|
constructor(party) {
|
||||||
super({ id: `TagTeamDialog-${party.id}` });
|
super({ id: `TagTeamDialog-${party.id}` });
|
||||||
|
|
||||||
|
this.usesTagTeamHopeCost = true;
|
||||||
this.party = party;
|
this.party = party;
|
||||||
this.partyMembers = party.system.partyMembers
|
this.partyMembers = party.system.partyMembers
|
||||||
.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
.filter(x => Party.DICE_ROLL_ACTOR_TYPES.includes(x.type))
|
||||||
|
|
@ -20,7 +22,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
owned: member.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.initiator = { cost: 3 };
|
this.initiator = { cost:
|
||||||
|
this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial
|
||||||
|
};
|
||||||
this.openForAllPlayers = true;
|
this.openForAllPlayers = true;
|
||||||
|
|
||||||
this.tabGroups.application = Object.keys(party.system.tagTeam.members).length
|
this.tabGroups.application = Object.keys(party.system.tagTeam.members).length
|
||||||
|
|
@ -94,9 +98,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
?.addEventListener('input', this.updateInitiatorMemberField.bind(this));
|
?.addEventListener('input', this.updateInitiatorMemberField.bind(this));
|
||||||
|
|
||||||
htmlElement
|
htmlElement
|
||||||
.querySelector('.initiator-cost-field')
|
.querySelector('.initiator-cost-input')
|
||||||
?.addEventListener('input', this.updateInitiatorCostField.bind(this));
|
?.addEventListener('input', this.updateInitiatorCostField.bind(this));
|
||||||
|
|
||||||
|
htmlElement
|
||||||
|
.querySelector('.initiator-cost-enabled-checkbox')
|
||||||
|
?.addEventListener('change', this.toggleInitiatorCostEnabled.bind(this));
|
||||||
|
|
||||||
htmlElement
|
htmlElement
|
||||||
.querySelector('.openforall-field')
|
.querySelector('.openforall-field')
|
||||||
?.addEventListener('change', this.updateOpenForAllField.bind(this));
|
?.addEventListener('change', this.updateOpenForAllField.bind(this));
|
||||||
|
|
@ -156,6 +164,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
.map(x => ({ value: x.id, label: x.name }));
|
.map(x => ({ value: x.id, label: x.name }));
|
||||||
partContext.initiatorDisabled = !selectedMembers.length;
|
partContext.initiatorDisabled = !selectedMembers.length;
|
||||||
partContext.openForAllPlayers = this.openForAllPlayers;
|
partContext.openForAllPlayers = this.openForAllPlayers;
|
||||||
|
partContext.usesTagTeamHopeCost = this.usesTagTeamHopeCost;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'tagTeamRoll':
|
case 'tagTeamRoll':
|
||||||
|
|
@ -397,6 +406,13 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toggleInitiatorCostEnabled(_event) {
|
||||||
|
this.usesTagTeamHopeCost = !this.usesTagTeamHopeCost;
|
||||||
|
this.initiator.cost = this.usesTagTeamHopeCost ?
|
||||||
|
this.party.system.schema.fields.tagTeam.fields.initiator.fields.cost.initial : 0;
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
updateOpenForAllField(event) {
|
updateOpenForAllField(event) {
|
||||||
this.openForAllPlayers = event.target.checked;
|
this.openForAllPlayers = event.target.checked;
|
||||||
this.render();
|
this.render();
|
||||||
|
|
@ -653,8 +669,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
const baseSecondaryRoll = selectedRoll
|
const baseSecondaryRoll = selectedRoll
|
||||||
? memberValues.find(x => !x.selected)
|
? memberValues.find(x => !x.selected)
|
||||||
: memberValues.length > 1
|
: memberValues.length > 1
|
||||||
? memberValues[1]
|
? memberValues[1]
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (!baseMainRoll?.rollData || !baseSecondaryRoll) return null;
|
if (!baseMainRoll?.rollData || !baseSecondaryRoll) return null;
|
||||||
|
|
||||||
|
|
@ -752,32 +768,37 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio
|
||||||
|
|
||||||
/* Handle resource updates from the finished TagTeamRoll */
|
/* Handle resource updates from the finished TagTeamRoll */
|
||||||
const tagTeamData = this.party.system.tagTeam;
|
const tagTeamData = this.party.system.tagTeam;
|
||||||
const fearUpdate = { key: 'fear', value: null, total: null, enabled: true };
|
|
||||||
for (let memberId in tagTeamData.members) {
|
|
||||||
const resourceUpdates = [];
|
|
||||||
const rollGivesHope = finalRoll.isCritical || finalRoll.withHope;
|
|
||||||
if (memberId === tagTeamData.initiator.memberId) {
|
|
||||||
const value = tagTeamData.initiator.cost
|
|
||||||
? rollGivesHope
|
|
||||||
? 1 - tagTeamData.initiator.cost
|
|
||||||
: -tagTeamData.initiator.cost
|
|
||||||
: 1;
|
|
||||||
resourceUpdates.push({ key: 'hope', value: value, total: -value, enabled: true });
|
|
||||||
} else if (rollGivesHope) {
|
|
||||||
resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
|
||||||
}
|
|
||||||
if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
|
||||||
if (finalRoll.withFear) {
|
|
||||||
fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1;
|
|
||||||
fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
game.actors.get(memberId).modifyResource(resourceUpdates);
|
const actorResourceMaps = Object.keys(tagTeamData.members).reduce((acc, key) => {
|
||||||
|
acc[key] = new ResourceUpdateMap(game.actors.get(key));
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
if (shouldUseHopeFearAutomation({ gmAsPlayer: true })) {
|
||||||
|
const fearResourceMap = actorResourceMaps[tagTeamData.initiator.memberId];
|
||||||
|
for (const memberId in tagTeamData.members) {
|
||||||
|
const resourceMap = actorResourceMaps[memberId];
|
||||||
|
if (finalRoll.isCritical) {
|
||||||
|
resourceMap.addResources([
|
||||||
|
{ key: 'stress', value: -1, enabled: true },
|
||||||
|
{ key: 'hope', value: 1, enabled: true }
|
||||||
|
]);
|
||||||
|
} else if (finalRoll.withHope) {
|
||||||
|
resourceMap.addResources([{ key: 'hope', value: 1, enabled: true }]);
|
||||||
|
} else if (finalRoll.withFear) {
|
||||||
|
fearResourceMap.addResources([{ key: 'fear', value: 1, enabled: true }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Even with Hope/Fear automation off, the hope cost of performing the TagTeamRoll can still optionally be subtracted */
|
||||||
|
if (tagTeamData.initiator.cost) {
|
||||||
|
const resourceMap = actorResourceMaps[tagTeamData.initiator.memberId];
|
||||||
|
resourceMap.addResources([{ key: 'hope', value: -tagTeamData.initiator.cost, enabled: true }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fearUpdate.value) {
|
for (const resourceMap of Object.values(actorResourceMaps))
|
||||||
mainActor.modifyResource([fearUpdate]);
|
resourceMap.updateResources();
|
||||||
}
|
|
||||||
|
|
||||||
/* Fin */
|
/* Fin */
|
||||||
this.cancelRoll({ confirm: false });
|
this.cancelRoll({ confirm: false });
|
||||||
|
|
|
||||||
|
|
@ -50,11 +50,11 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
).showGenericStatusEffects;
|
).showGenericStatusEffects;
|
||||||
context.genericStatusEffects = useGeneric
|
context.genericStatusEffects = useGeneric
|
||||||
? Object.keys(context.statusEffects).reduce((acc, key) => {
|
? Object.keys(context.statusEffects).reduce((acc, key) => {
|
||||||
const effect = context.statusEffects[key];
|
const effect = context.statusEffects[key];
|
||||||
if (!effect.systemEffect) acc[key] = effect;
|
if (!effect.systemEffect) acc[key] = effect;
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
context.hasCompanion = this.actor.system.companion;
|
context.hasCompanion = this.actor.system.companion;
|
||||||
|
|
@ -68,11 +68,11 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
const warning =
|
const warning =
|
||||||
tokensWithoutActors.length === 1
|
tokensWithoutActors.length === 1
|
||||||
? game.i18n.format('DAGGERHEART.UI.Notifications.tokenActorMissing', {
|
? game.i18n.format('DAGGERHEART.UI.Notifications.tokenActorMissing', {
|
||||||
name: tokensWithoutActors[0].name
|
name: tokensWithoutActors[0].name
|
||||||
})
|
})
|
||||||
: game.i18n.format('DAGGERHEART.UI.Notifications.tokenActorsMissing', {
|
: game.i18n.format('DAGGERHEART.UI.Notifications.tokenActorsMissing', {
|
||||||
names: tokensWithoutActors.map(x => x.name).join(', ')
|
names: tokensWithoutActors.map(x => x.name).join(', ')
|
||||||
});
|
});
|
||||||
|
|
||||||
const tokens = canvas.tokens.controlled
|
const tokens = canvas.tokens.controlled
|
||||||
.filter(t => t.actor && !DHTokenHUD.#nonCombatTypes.includes(t.actor.type))
|
.filter(t => t.actor && !DHTokenHUD.#nonCombatTypes.includes(t.actor.type))
|
||||||
|
|
@ -174,8 +174,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
nonZeroIndex === sideMiddle
|
nonZeroIndex === sideMiddle
|
||||||
? 0
|
? 0
|
||||||
: nonZeroIndex < sideMiddle
|
: nonZeroIndex < sideMiddle
|
||||||
? -nonZeroIndex
|
? -nonZeroIndex
|
||||||
: nonZeroIndex - sideMiddle;
|
: nonZeroIndex - sideMiddle;
|
||||||
return { x: actorX - sizeX * distance, y: actorY - sizeY * distanceCoefficient };
|
return { x: actorX - sizeX * distance, y: actorY - sizeY * distanceCoefficient };
|
||||||
} else if (index < side + inbetween) {
|
} else if (index < side + inbetween) {
|
||||||
const inbetweenIndex = nonZeroIndex - side;
|
const inbetweenIndex = nonZeroIndex - side;
|
||||||
|
|
@ -183,8 +183,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
inbetweenIndex === inbetweenMiddle
|
inbetweenIndex === inbetweenMiddle
|
||||||
? 0
|
? 0
|
||||||
: inbetweenIndex < inbetweenMiddle
|
: inbetweenIndex < inbetweenMiddle
|
||||||
? -inbetweenIndex
|
? -inbetweenIndex
|
||||||
: inbetweenIndex - inbetweenMiddle;
|
: inbetweenIndex - inbetweenMiddle;
|
||||||
return { x: actorX + sizeX * distanceCoefficient, y: actorY + sizeY * distance };
|
return { x: actorX + sizeX * distanceCoefficient, y: actorY + sizeY * distance };
|
||||||
} else if (index < 2 * side + inbetween) {
|
} else if (index < 2 * side + inbetween) {
|
||||||
const sideIndex = nonZeroIndex - side - inbetween;
|
const sideIndex = nonZeroIndex - side - inbetween;
|
||||||
|
|
@ -192,8 +192,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
sideIndex === sideMiddle
|
sideIndex === sideMiddle
|
||||||
? 0
|
? 0
|
||||||
: sideIndex < sideMiddle
|
: sideIndex < sideMiddle
|
||||||
? sideIndex
|
? sideIndex
|
||||||
: -(sideIndex - sideMiddle);
|
: -(sideIndex - sideMiddle);
|
||||||
return { x: actorX + sizeX * distance, y: actorY + sizeY * distanceCoefficient };
|
return { x: actorX + sizeX * distance, y: actorY + sizeY * distanceCoefficient };
|
||||||
} else {
|
} else {
|
||||||
const inbetweenIndex = nonZeroIndex - 2 * side - inbetween;
|
const inbetweenIndex = nonZeroIndex - 2 * side - inbetween;
|
||||||
|
|
@ -201,8 +201,8 @@ export default class DHTokenHUD extends foundry.applications.hud.TokenHUD {
|
||||||
inbetweenIndex === inbetweenMiddle
|
inbetweenIndex === inbetweenMiddle
|
||||||
? 0
|
? 0
|
||||||
: inbetweenIndex < inbetweenMiddle
|
: inbetweenIndex < inbetweenMiddle
|
||||||
? inbetweenIndex
|
? inbetweenIndex
|
||||||
: -(inbetweenIndex - inbetweenMiddle);
|
: -(inbetweenIndex - inbetweenMiddle);
|
||||||
return { x: actorX - sizeX * distanceCoefficient, y: actorY + sizeY * distance };
|
return { x: actorX - sizeX * distanceCoefficient, y: actorY + sizeY * distance };
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -210,9 +210,9 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
||||||
|
|
||||||
achievementExperiences = level.achievements.experiences
|
achievementExperiences = level.achievements.experiences
|
||||||
? Object.values(level.achievements.experiences).reduce((acc, experience) => {
|
? Object.values(level.achievements.experiences).reduce((acc, experience) => {
|
||||||
if (experience.name) acc.push(experience);
|
if (experience.name) acc.push(experience);
|
||||||
return acc;
|
return acc;
|
||||||
}, [])
|
}, [])
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,15 +315,15 @@ export default class DhCharacterLevelUp extends LevelUpBase {
|
||||||
: null;
|
: null;
|
||||||
advancement[choiceKey] = multiclassItem
|
advancement[choiceKey] = multiclassItem
|
||||||
? {
|
? {
|
||||||
...multiclassItem.toObject(),
|
...multiclassItem.toObject(),
|
||||||
domain: checkbox.secondaryData.domain
|
domain: checkbox.secondaryData.domain
|
||||||
? game.i18n.localize(
|
? game.i18n.localize(
|
||||||
CONFIG.DH.DOMAIN.allDomains()[checkbox.secondaryData.domain]
|
CONFIG.DH.DOMAIN.allDomains()[checkbox.secondaryData.domain]
|
||||||
.label
|
.label
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
subclass: subclass ? subclass.name : null
|
subclass: subclass ? subclass.name : null
|
||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,9 @@ export default class DhCompanionLevelUp extends BaseLevelUp {
|
||||||
|
|
||||||
achievementExperiences = level.achievements.experiences
|
achievementExperiences = level.achievements.experiences
|
||||||
? Object.values(level.achievements.experiences).reduce((acc, experience) => {
|
? Object.values(level.achievements.experiences).reduce((acc, experience) => {
|
||||||
if (experience.name) acc.push(experience);
|
if (experience.name) acc.push(experience);
|
||||||
return acc;
|
return acc;
|
||||||
}, [])
|
}, [])
|
||||||
: [];
|
: [];
|
||||||
}
|
}
|
||||||
context.achievements = {
|
context.achievements = {
|
||||||
|
|
@ -155,15 +155,15 @@ export default class DhCompanionLevelUp extends BaseLevelUp {
|
||||||
vicious: {
|
vicious: {
|
||||||
damage: advancement.vicious?.damage
|
damage: advancement.vicious?.damage
|
||||||
? {
|
? {
|
||||||
old: actorDamageDice,
|
old: actorDamageDice,
|
||||||
new: advancement.vicious.damage
|
new: advancement.vicious.damage
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
range: advancement.vicious?.range
|
range: advancement.vicious?.range
|
||||||
? {
|
? {
|
||||||
old: game.i18n.localize(`DAGGERHEART.CONFIG.Range.${actorRange}.name`),
|
old: game.i18n.localize(`DAGGERHEART.CONFIG.Range.${actorRange}.name`),
|
||||||
new: game.i18n.localize(advancement.vicious.range.label)
|
new: game.i18n.localize(advancement.vicious.range.label)
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
},
|
},
|
||||||
simple: advancement.simple ?? {}
|
simple: advancement.simple ?? {}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { abilities, subclassFeatureLabels } from '../../config/actorConfig.mjs';
|
|
||||||
import { getDeleteKeys, tagifyElement } from '../../helpers/utils.mjs';
|
import { getDeleteKeys, tagifyElement } from '../../helpers/utils.mjs';
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
@ -135,192 +134,6 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
context.tabs.advancements.progress = { selected: selections, max: currentLevel.maxSelections };
|
context.tabs.advancements.progress = { selected: selections, max: currentLevel.maxSelections };
|
||||||
context.showTabs = this.tabGroups.primary !== 'summary';
|
context.showTabs = this.tabGroups.primary !== 'summary';
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const actorArmor = this.actor.system.armor;
|
|
||||||
const levelKeys = Object.keys(this.levelup.levels);
|
|
||||||
let achivementProficiency = 0;
|
|
||||||
const achievementCards = [];
|
|
||||||
let achievementExperiences = [];
|
|
||||||
for (var levelKey of levelKeys) {
|
|
||||||
const level = this.levelup.levels[levelKey];
|
|
||||||
if (Number(levelKey) < this.levelup.startLevel) continue;
|
|
||||||
|
|
||||||
achivementProficiency += level.achievements.proficiency ?? 0;
|
|
||||||
const cards = level.achievements.domainCards ? Object.values(level.achievements.domainCards) : null;
|
|
||||||
if (cards) {
|
|
||||||
for (var card of cards) {
|
|
||||||
const itemCard = await foundry.utils.fromUuid(card.uuid);
|
|
||||||
achievementCards.push(itemCard);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
achievementExperiences = level.achievements.experiences
|
|
||||||
? Object.values(level.achievements.experiences).reduce((acc, experience) => {
|
|
||||||
if (experience.name) acc.push(experience);
|
|
||||||
return acc;
|
|
||||||
}, [])
|
|
||||||
: [];
|
|
||||||
}
|
|
||||||
|
|
||||||
context.achievements = {
|
|
||||||
proficiency: {
|
|
||||||
old: this.actor.system.proficiency,
|
|
||||||
new: this.actor.system.proficiency + achivementProficiency,
|
|
||||||
shown: achivementProficiency > 0
|
|
||||||
},
|
|
||||||
damageThresholds: {
|
|
||||||
major: {
|
|
||||||
old: this.actor.system.damageThresholds.major,
|
|
||||||
new: this.actor.system.damageThresholds.major + changedActorLevel - currentActorLevel
|
|
||||||
},
|
|
||||||
severe: {
|
|
||||||
old: this.actor.system.damageThresholds.severe,
|
|
||||||
new:
|
|
||||||
this.actor.system.damageThresholds.severe +
|
|
||||||
(actorArmor
|
|
||||||
? changedActorLevel - currentActorLevel
|
|
||||||
: (changedActorLevel - currentActorLevel) * 2)
|
|
||||||
},
|
|
||||||
unarmored: !actorArmor
|
|
||||||
},
|
|
||||||
domainCards: {
|
|
||||||
values: achievementCards,
|
|
||||||
shown: achievementCards.length > 0
|
|
||||||
},
|
|
||||||
experiences: {
|
|
||||||
values: achievementExperiences
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const advancement = {};
|
|
||||||
for (var levelKey of levelKeys) {
|
|
||||||
const level = this.levelup.levels[levelKey];
|
|
||||||
if (Number(levelKey) < this.levelup.startLevel) continue;
|
|
||||||
|
|
||||||
for (var choiceKey of Object.keys(level.choices)) {
|
|
||||||
const choice = level.choices[choiceKey];
|
|
||||||
for (var checkbox of Object.values(choice)) {
|
|
||||||
switch (choiceKey) {
|
|
||||||
case 'proficiency':
|
|
||||||
case 'hitPoint':
|
|
||||||
case 'stress':
|
|
||||||
case 'evasion':
|
|
||||||
advancement[choiceKey] = advancement[choiceKey]
|
|
||||||
? advancement[choiceKey] + Number(checkbox.value)
|
|
||||||
: Number(checkbox.value);
|
|
||||||
break;
|
|
||||||
case 'trait':
|
|
||||||
if (!advancement[choiceKey]) advancement[choiceKey] = {};
|
|
||||||
for (var traitKey of checkbox.data) {
|
|
||||||
if (!advancement[choiceKey][traitKey]) advancement[choiceKey][traitKey] = 0;
|
|
||||||
advancement[choiceKey][traitKey] += 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'domainCard':
|
|
||||||
if (!advancement[choiceKey]) advancement[choiceKey] = [];
|
|
||||||
if (checkbox.data.length === 1) {
|
|
||||||
const choiceItem = await foundry.utils.fromUuid(checkbox.data[0]);
|
|
||||||
advancement[choiceKey].push(choiceItem.toObject());
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'experience':
|
|
||||||
if (!advancement[choiceKey]) advancement[choiceKey] = [];
|
|
||||||
const data = checkbox.data.map(data => {
|
|
||||||
const experience = Object.keys(this.actor.system.experiences).find(
|
|
||||||
x => x === data
|
|
||||||
);
|
|
||||||
return this.actor.system.experiences[experience]?.description ?? '';
|
|
||||||
});
|
|
||||||
advancement[choiceKey].push({ data: data, value: checkbox.value });
|
|
||||||
break;
|
|
||||||
case 'subclass':
|
|
||||||
if (checkbox.data[0]) {
|
|
||||||
const subclassItem = await foundry.utils.fromUuid(checkbox.data[0]);
|
|
||||||
if (!advancement[choiceKey]) advancement[choiceKey] = [];
|
|
||||||
advancement[choiceKey].push({
|
|
||||||
...subclassItem.toObject(),
|
|
||||||
featureLabel: game.i18n.localize(
|
|
||||||
subclassFeatureLabels[Number(checkbox.secondaryData.featureState)]
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'multiclass':
|
|
||||||
const multiclassItem = await foundry.utils.fromUuid(checkbox.data[0]);
|
|
||||||
const subclass = multiclassItem
|
|
||||||
? await foundry.utils.fromUuid(checkbox.secondaryData.subclass)
|
|
||||||
: null;
|
|
||||||
advancement[choiceKey] = multiclassItem
|
|
||||||
? {
|
|
||||||
...multiclassItem.toObject(),
|
|
||||||
domain: checkbox.secondaryData.domain
|
|
||||||
? game.i18n.localize(
|
|
||||||
CONFIG.DH.DOMAIN.allDomains()[checkbox.secondaryData.domain]
|
|
||||||
.label
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
subclass: subclass ? subclass.name : null
|
|
||||||
}
|
|
||||||
: {};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
context.advancements = {
|
|
||||||
statistics: {
|
|
||||||
proficiency: {
|
|
||||||
old: context.achievements.proficiency.new,
|
|
||||||
new: context.achievements.proficiency.new + (advancement.proficiency ?? 0)
|
|
||||||
},
|
|
||||||
hitPoints: {
|
|
||||||
old: this.actor.system.resources.hitPoints.max,
|
|
||||||
new: this.actor.system.resources.hitPoints.max + (advancement.hitPoint ?? 0)
|
|
||||||
},
|
|
||||||
stress: {
|
|
||||||
old: this.actor.system.resources.stress.max,
|
|
||||||
new: this.actor.system.resources.stress.max + (advancement.stress ?? 0)
|
|
||||||
},
|
|
||||||
evasion: {
|
|
||||||
old: this.actor.system.evasion,
|
|
||||||
new: this.actor.system.evasion + (advancement.evasion ?? 0)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
traits: Object.keys(this.actor.system.traits).reduce((acc, traitKey) => {
|
|
||||||
if (advancement.trait?.[traitKey]) {
|
|
||||||
if (!acc) acc = {};
|
|
||||||
acc[traitKey] = {
|
|
||||||
label: game.i18n.localize(abilities[traitKey].label),
|
|
||||||
old: this.actor.system.traits[traitKey].value,
|
|
||||||
new: this.actor.system.traits[traitKey].value + advancement.trait[traitKey]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return acc;
|
|
||||||
}, null),
|
|
||||||
domainCards: advancement.domainCard ?? [],
|
|
||||||
experiences:
|
|
||||||
advancement.experience?.flatMap(x => x.data.map(data => ({ name: data, modifier: x.value }))) ??
|
|
||||||
[],
|
|
||||||
multiclass: advancement.multiclass,
|
|
||||||
subclass: advancement.subclass
|
|
||||||
};
|
|
||||||
|
|
||||||
context.advancements.statistics.proficiency.shown =
|
|
||||||
context.advancements.statistics.proficiency.new > context.advancements.statistics.proficiency.old;
|
|
||||||
context.advancements.statistics.hitPoints.shown =
|
|
||||||
context.advancements.statistics.hitPoints.new > context.advancements.statistics.hitPoints.old;
|
|
||||||
context.advancements.statistics.stress.shown =
|
|
||||||
context.advancements.statistics.stress.new > context.advancements.statistics.stress.old;
|
|
||||||
context.advancements.statistics.evasion.shown =
|
|
||||||
context.advancements.statistics.evasion.new > context.advancements.statistics.evasion.old;
|
|
||||||
context.advancements.statistics.shown =
|
|
||||||
context.advancements.statistics.proficiency.shown ||
|
|
||||||
context.advancements.statistics.hitPoints.shown ||
|
|
||||||
context.advancements.statistics.stress.shown ||
|
|
||||||
context.advancements.statistics.evasion.shown;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
|
|
@ -358,14 +171,14 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
const experienceIncreaseTagify = htmlElement.querySelector('.levelup-experience-increases');
|
const experienceIncreaseTagify = htmlElement.querySelector('.levelup-experience-increases');
|
||||||
if (experienceIncreaseTagify) {
|
if (experienceIncreaseTagify) {
|
||||||
const allExperiences = {
|
const allExperiences = {
|
||||||
...this.actor.system.experiences,
|
|
||||||
...Object.values(this.levelup.levels).reduce((acc, level) => {
|
...Object.values(this.levelup.levels).reduce((acc, level) => {
|
||||||
for (const key of Object.keys(level.achievements.experiences)) {
|
for (const key of Object.keys(level.achievements.experiences)) {
|
||||||
acc[key] = level.achievements.experiences[key];
|
acc[key] = level.achievements.experiences[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {}),
|
||||||
|
...this.actor.system.experiences
|
||||||
};
|
};
|
||||||
tagifyElement(
|
tagifyElement(
|
||||||
experienceIncreaseTagify,
|
experienceIncreaseTagify,
|
||||||
|
|
@ -384,37 +197,35 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
this._dragDrop.forEach(d => d.bind(htmlElement));
|
this._dragDrop.forEach(d => d.bind(htmlElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
tagifyUpdate =
|
tagifyUpdate = type => async (_, { option, removed }) => {
|
||||||
type =>
|
const updatePath = Object.keys(this.levelup.levels[this.levelup.currentLevel].choices).reduce(
|
||||||
async (_, { option, removed }) => {
|
(acc, choiceKey) => {
|
||||||
const updatePath = Object.keys(this.levelup.levels[this.levelup.currentLevel].choices).reduce(
|
const choice = this.levelup.levels[this.levelup.currentLevel].choices[choiceKey];
|
||||||
(acc, choiceKey) => {
|
Object.keys(choice).forEach(checkboxNr => {
|
||||||
const choice = this.levelup.levels[this.levelup.currentLevel].choices[choiceKey];
|
const checkbox = choice[checkboxNr];
|
||||||
Object.keys(choice).forEach(checkboxNr => {
|
if (
|
||||||
const checkbox = choice[checkboxNr];
|
choiceKey === type &&
|
||||||
if (
|
(removed ? checkbox.data.includes(option) : checkbox.data.length < checkbox.amount)
|
||||||
choiceKey === type &&
|
) {
|
||||||
(removed ? checkbox.data.includes(option) : checkbox.data.length < checkbox.amount)
|
acc = `levels.${this.levelup.currentLevel}.choices.${choiceKey}.${checkboxNr}.data`;
|
||||||
) {
|
}
|
||||||
acc = `levels.${this.levelup.currentLevel}.choices.${choiceKey}.${checkboxNr}.data`;
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!updatePath) {
|
if (!updatePath) {
|
||||||
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noSelectionsLeft'));
|
ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.noSelectionsLeft'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentData = foundry.utils.getProperty(this.levelup, updatePath);
|
const currentData = foundry.utils.getProperty(this.levelup, updatePath);
|
||||||
const updatedData = removed ? currentData.filter(x => x !== option) : [...currentData, option];
|
const updatedData = removed ? currentData.filter(x => x !== option) : [...currentData, option];
|
||||||
await this.levelup.updateSource({ [updatePath]: updatedData });
|
await this.levelup.updateSource({ [updatePath]: updatedData });
|
||||||
this.render();
|
this.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
static async updateForm(event, _, formData) {
|
static async updateForm(event, _, formData) {
|
||||||
const { levelup } = foundry.utils.expandObject(formData.object);
|
const { levelup } = foundry.utils.expandObject(formData.object);
|
||||||
|
|
@ -593,10 +404,10 @@ export default class DhlevelUp extends HandlebarsApplicationMixin(ApplicationV2)
|
||||||
const domainCards = this.levelup.levels[this.levelup.currentLevel].achievements.domainCards;
|
const domainCards = this.levelup.levels[this.levelup.currentLevel].achievements.domainCards;
|
||||||
const illegalDomainCards = option.secondaryData.domain
|
const illegalDomainCards = option.secondaryData.domain
|
||||||
? Object.keys(domainCards)
|
? Object.keys(domainCards)
|
||||||
.map(key => ({ ...domainCards[key], key }))
|
.map(key => ({ ...domainCards[key], key }))
|
||||||
.filter(
|
.filter(
|
||||||
x => x.uuid && foundry.utils.fromUuidSync(x.uuid).system.domain === option.secondaryData.domain
|
x => x.uuid && foundry.utils.fromUuidSync(x.uuid).system.domain === option.secondaryData.domain
|
||||||
)
|
)
|
||||||
: [];
|
: [];
|
||||||
illegalDomainCards.forEach(card => {
|
illegalDomainCards.forEach(card => {
|
||||||
update[`levels.${this.levelup.currentLevel}.achievements.domainCards.${card.key}.uuid`] = null;
|
update[`levels.${this.levelup.currentLevel}.achievements.domainCards.${card.key}.uuid`] = null;
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import DhAppearance from '../../data/settings/Appearance.mjs';
|
|
||||||
import { getDiceSoNicePreset } from '../../config/generalConfig.mjs';
|
import { getDiceSoNicePreset } from '../../config/generalConfig.mjs';
|
||||||
|
|
||||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @import DhAppearance from '../../data/settings/Appearance.mjs';
|
||||||
* @import {ApplicationClickAction} from "@client/applications/_types.mjs"
|
* @import {ApplicationClickAction} from "@client/applications/_types.mjs"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** Settings menu for appearance settings */
|
||||||
export default class DHAppearanceSettings extends HandlebarsApplicationMixin(ApplicationV2) {
|
export default class DHAppearanceSettings extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
|
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case 'domains':
|
case 'domains':
|
||||||
const selectedDomain = this.selected.domain ? this.settings.domains[this.selected.domain] : null;
|
const selectedDomain = this.settings.domains[this.selected.domain] ?? null;
|
||||||
const enrichedDescription = selectedDomain
|
const enrichedDescription = selectedDomain
|
||||||
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(selectedDomain.description)
|
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(selectedDomain.description)
|
||||||
: null;
|
: null;
|
||||||
|
|
@ -251,8 +251,8 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
|
||||||
const configTitle = isDowntime
|
const configTitle = isDowntime
|
||||||
? game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.downtimeMove')
|
? game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.downtimeMove')
|
||||||
: type === 'armorFeatures'
|
: type === 'armorFeatures'
|
||||||
? game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.armorFeature')
|
? game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.armorFeature')
|
||||||
: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.weaponFeature');
|
: game.i18n.localize('DAGGERHEART.SETTINGS.Homebrew.weaponFeature');
|
||||||
|
|
||||||
const editedBase = await game.system.api.applications.sheetConfigs.SettingFeatureConfig.configure(
|
const editedBase = await game.system.api.applications.sheetConfigs.SettingFeatureConfig.configure(
|
||||||
configTitle,
|
configTitle,
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.action.parent.metadata.isInventoryItem) {
|
if (this.action.parent.metadata?.isInventoryItem) {
|
||||||
options.quantity = {
|
options.quantity = {
|
||||||
label: 'DAGGERHEART.GENERAL.itemQuantity',
|
label: 'DAGGERHEART.GENERAL.itemQuantity',
|
||||||
group: 'Global'
|
group: 'Global'
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,7 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
actions: {
|
actions: {
|
||||||
addExperience: DHAdversarySettings.#addExperience,
|
addExperience: DHAdversarySettings.#addExperience,
|
||||||
removeExperience: DHAdversarySettings.#removeExperience
|
removeExperience: DHAdversarySettings.#removeExperience
|
||||||
},
|
}
|
||||||
dragDrop: [
|
|
||||||
{ dragSelector: null, dropSelector: '.tab.features' },
|
|
||||||
{ dragSelector: '.feature-item', dropSelector: null }
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**@override */
|
/**@override */
|
||||||
|
|
@ -38,7 +34,8 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
id: 'features',
|
id: 'features',
|
||||||
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs'
|
template: 'systems/daggerheart/templates/sheets-settings/adversary-settings/features.hbs',
|
||||||
|
scrollable: ['']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -54,12 +51,16 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
const featureForms = ['passive', 'action', 'reaction'];
|
// Get feature groups. Uncategorized go to actions
|
||||||
context.features = context.document.system.features.sort((a, b) =>
|
const featureFormsTypes = ['passive', 'action', 'reaction'];
|
||||||
a.system.featureForm !== b.system.featureForm
|
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
const featureGroups = featureFormsTypes.map(t => ({
|
||||||
: a.sort - b.sort
|
featureForm: t,
|
||||||
);
|
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
|
||||||
|
features: features.filter(f => f.system.featureForm === t)
|
||||||
|
}));
|
||||||
|
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
|
||||||
|
context.featureGroups = featureGroups;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -97,32 +98,4 @@ export default class DHAdversarySettings extends DHBaseActorSettings {
|
||||||
|
|
||||||
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
await this.actor.update({ [`system.experiences.${target.dataset.experience}`]: _del });
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDragStart(event) {
|
|
||||||
const featureItem = event.currentTarget.closest('.feature-item');
|
|
||||||
|
|
||||||
if (featureItem) {
|
|
||||||
const feature = this.actor.items.get(featureItem.id);
|
|
||||||
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
|
||||||
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDrop(event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
|
||||||
|
|
||||||
const item = await fromUuid(data.uuid);
|
|
||||||
if (item?.type === 'feature') {
|
|
||||||
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemData = item.toObject();
|
|
||||||
delete itemData._id;
|
|
||||||
|
|
||||||
await this.actor.createEmbeddedDocuments('Item', [itemData]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
dragDrop: [
|
dragDrop: [
|
||||||
{ dragSelector: null, dropSelector: '.category-container' },
|
{ dragSelector: null, dropSelector: '.category-container' },
|
||||||
{ dragSelector: null, dropSelector: '.tab.features' },
|
{ dragSelector: null, dropSelector: '.tab.features' },
|
||||||
{ dragSelector: '.feature-item', dropSelector: null }
|
{ dragSelector: '.feature-item, .inventory-item[data-type="adversary"]', dropSelector: null }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -32,11 +32,13 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
id: 'features',
|
id: 'features',
|
||||||
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs'
|
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/features.hbs',
|
||||||
|
scrollable: ['']
|
||||||
},
|
},
|
||||||
adversaries: {
|
adversaries: {
|
||||||
id: 'adversaries',
|
id: 'adversaries',
|
||||||
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs'
|
template: 'systems/daggerheart/templates/sheets-settings/environment-settings/adversaries.hbs',
|
||||||
|
scrollable: ['']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -52,12 +54,16 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
const featureForms = ['passive', 'action', 'reaction'];
|
// Get feature groups. Uncategorized go to actions
|
||||||
context.features = context.document.system.features.sort((a, b) =>
|
const featureFormsTypes = ['passive', 'action', 'reaction'];
|
||||||
a.system.featureForm !== b.system.featureForm
|
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
const featureGroups = featureFormsTypes.map(t => ({
|
||||||
: a.sort - b.sort
|
featureForm: t,
|
||||||
);
|
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
|
||||||
|
features: features.filter(f => f.system.featureForm === t)
|
||||||
|
}));
|
||||||
|
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
|
||||||
|
context.featureGroups = featureGroups;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -110,33 +116,30 @@ export default class DHEnvironmentSettings extends DHBaseActorSettings {
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDragStart(event) {
|
async _onDragStart(event) {
|
||||||
const featureItem = event.currentTarget.closest('.feature-item');
|
const element = event.currentTarget.closest('.inventory-item[data-type=adversary]');
|
||||||
|
if (element) {
|
||||||
if (featureItem) {
|
const adversaryData = { type: 'Actor', uuid: element.dataset.itemUuid };
|
||||||
const feature = this.actor.items.get(featureItem.id);
|
event.dataTransfer.setData('text/plain', JSON.stringify(adversaryData));
|
||||||
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
event.dataTransfer.setDragImage(element, 60, 0);
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
} else {
|
||||||
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
return super._onDragStart(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
const item = await fromUuid(data.uuid);
|
const doc = await fromUuid(data.uuid);
|
||||||
if (data.fromInternal && item?.parent?.uuid === this.actor.uuid) return;
|
if (doc?.type === 'adversary' && event.target.closest('.category-container')) {
|
||||||
|
|
||||||
if (item.type === 'adversary' && event.target.closest('.category-container')) {
|
|
||||||
const target = event.target.closest('.category-container');
|
const target = event.target.closest('.category-container');
|
||||||
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
|
const path = `system.potentialAdversaries.${target.dataset.potentialAdversary}.adversaries`;
|
||||||
const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid);
|
const current = foundry.utils.getProperty(this.actor, path).map(x => x.uuid);
|
||||||
await this.actor.update({
|
if (!current.includes(doc.uuid)) {
|
||||||
[path]: [...current, item.uuid]
|
await this.actor.update({ [path]: [...current, doc.uuid] });
|
||||||
});
|
}
|
||||||
this.render();
|
return;
|
||||||
} else if (item.type === 'feature' && event.target.closest('.tab.features')) {
|
|
||||||
await this.actor.createEmbeddedDocuments('Item', [item]);
|
|
||||||
this.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return super._onDrop(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@ export default class DHNPCSettings extends DHBaseActorSettings {
|
||||||
},
|
},
|
||||||
features: {
|
features: {
|
||||||
id: 'features',
|
id: 'features',
|
||||||
template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs'
|
template: 'systems/daggerheart/templates/sheets-settings/npc-settings/features.hbs',
|
||||||
|
scrollable: ['']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -43,43 +44,17 @@ export default class DHNPCSettings extends DHBaseActorSettings {
|
||||||
async _prepareContext(options) {
|
async _prepareContext(options) {
|
||||||
const context = await super._prepareContext(options);
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
const featureForms = ['passive', 'action', 'reaction'];
|
// Get feature groups. Uncategorized go to actions
|
||||||
context.features = context.document.system.features.sort((a, b) =>
|
const featureFormsTypes = ['passive', 'action', 'reaction'];
|
||||||
a.system.featureForm !== b.system.featureForm
|
const features = this.document.system.features.sort((a, b) => a.sort - b.sort);
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
const featureGroups = featureFormsTypes.map(t => ({
|
||||||
: a.sort - b.sort
|
featureForm: t,
|
||||||
);
|
label: _loc(CONFIG.DH.ITEM.featureForm[t]),
|
||||||
|
features: features.filter(f => f.system.featureForm === t)
|
||||||
|
}));
|
||||||
|
featureGroups[1].features.push(...features.filter(f => !featureFormsTypes.includes(f.system.featureForm)));
|
||||||
|
context.featureGroups = featureGroups;
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
async _onDragStart(event) {
|
|
||||||
const featureItem = event.currentTarget.closest('.feature-item');
|
|
||||||
|
|
||||||
if (featureItem) {
|
|
||||||
const feature = this.actor.items.get(featureItem.id);
|
|
||||||
const featureData = { type: 'Item', uuid: feature.uuid, fromInternal: true };
|
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
|
||||||
event.dataTransfer.setDragImage(featureItem.querySelector('img'), 60, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDrop(event) {
|
|
||||||
event.stopPropagation();
|
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
|
||||||
|
|
||||||
const item = await fromUuid(data.uuid);
|
|
||||||
if (item?.type === 'feature') {
|
|
||||||
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemData = item.toObject();
|
|
||||||
delete itemData._id;
|
|
||||||
|
|
||||||
await this.actor.createEmbeddedDocuments('Item', [itemData]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,8 +168,8 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
||||||
updatedEffects = deleteEffect
|
updatedEffects = deleteEffect
|
||||||
? currentEffects.filter(x => x.id !== effectData.id)
|
? currentEffects.filter(x => x.id !== effectData.id)
|
||||||
: existingEffectIndex === -1
|
: existingEffectIndex === -1
|
||||||
? [...currentEffects, effectData]
|
? [...currentEffects, effectData]
|
||||||
: currentEffects.with(existingEffectIndex, effectData);
|
: currentEffects.with(existingEffectIndex, effectData);
|
||||||
await this.updateMove({
|
await this.updateMove({
|
||||||
[`${this.movePath}.effects`]: updatedEffects
|
[`${this.movePath}.effects`]: updatedEffects
|
||||||
});
|
});
|
||||||
|
|
@ -235,9 +235,9 @@ export default class SettingFeatureConfig extends HandlebarsApplicationMixin(App
|
||||||
return this.hasEffects
|
return this.hasEffects
|
||||||
? tabs
|
? tabs
|
||||||
: Object.keys(tabs).reduce((acc, key) => {
|
: Object.keys(tabs).reduce((acc, key) => {
|
||||||
if (key !== 'effects') acc[key] = tabs[key];
|
if (key !== 'effects') acc[key] = tabs[key];
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
|
|
|
||||||
8
module/applications/sheets/actors/_types.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import DhCompanion from '../../../data/actor/companion.mjs';
|
||||||
|
import DhpActor from '../../../documents/actor.mjs';
|
||||||
|
|
||||||
|
declare module './companion.mjs' {
|
||||||
|
export default interface DhCompanionSheet {
|
||||||
|
actor: DhpActor<DhCompanion>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -103,7 +103,7 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
context.resources.stress.emptyPips =
|
context.resources.stress.emptyPips =
|
||||||
context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0;
|
context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0;
|
||||||
|
|
||||||
const featureForms = ['passive', 'action', 'reaction'];
|
const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
|
||||||
context.features = this.document.system.features.sort((a, b) =>
|
context.features = this.document.system.features.sort((a, b) =>
|
||||||
a.system.featureForm !== b.system.featureForm
|
a.system.featureForm !== b.system.featureForm
|
||||||
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
? featureForms.indexOf(a.system.featureForm) - featureForms.indexOf(b.system.featureForm)
|
||||||
|
|
@ -131,6 +131,15 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
_prepareTabs(group) {
|
||||||
|
const result = super._prepareTabs(group);
|
||||||
|
if (group === 'primary') {
|
||||||
|
result.notes.empty = !this.document.system.notes?.trim();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
_attachPartListeners(partId, htmlElement, options) {
|
_attachPartListeners(partId, htmlElement, options) {
|
||||||
super._attachPartListeners(partId, htmlElement, options);
|
super._attachPartListeners(partId, htmlElement, options);
|
||||||
|
|
@ -186,15 +195,6 @@ export default class AdversarySheet extends DHBaseActorSheet {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
async _onDragStart(event) {
|
|
||||||
const inventoryItem = event.currentTarget.closest('.inventory-item');
|
|
||||||
if (inventoryItem) {
|
|
||||||
event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0);
|
|
||||||
}
|
|
||||||
super._onDragStart(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Application Clicks Actions */
|
/* Application Clicks Actions */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
|
||||||
|
|
@ -356,7 +356,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
|
|
||||||
const levelups = Object.values(actor.system.levelData?.levelups) ?? [];
|
const levelups = Object.values(actor.system.levelData?.levelups) ?? [];
|
||||||
const uuid = item.uuid;
|
const uuid = item.uuid;
|
||||||
const sourceUuid = item._stats.compendiumSource; // on older characters this may be missing
|
const sourceUuid = item.sourceUuid; // on older characters this may be missing
|
||||||
return levelups.some(data => {
|
return levelups.some(data => {
|
||||||
if (item.type === 'subclass') {
|
if (item.type === 'subclass') {
|
||||||
const selectedSubclasses = data.selections.map(s => s.secondaryData?.subclass).filter(s => !!s);
|
const selectedSubclasses = data.selections.map(s => s.secondaryData?.subclass).filter(s => !!s);
|
||||||
|
|
@ -785,11 +785,11 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
filter:
|
filter:
|
||||||
key === 'subclasses'
|
key === 'subclasses'
|
||||||
? {
|
? {
|
||||||
'system.linkedClass.uuid': {
|
'system.linkedClass.uuid': {
|
||||||
key: 'system.linkedClass.uuid',
|
key: 'system.linkedClass.uuid',
|
||||||
value: this.document.system.class.value?._stats.compendiumSource
|
value: this.document.system.class.value?._stats.compendiumSource
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: undefined,
|
: undefined,
|
||||||
render: {
|
render: {
|
||||||
noFolder: true
|
noFolder: true
|
||||||
|
|
@ -809,7 +809,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
|
|
||||||
/* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */
|
/* This could be avoided by baking config.costs into config.resourceUpdates. Didn't feel like messing with it at the time */
|
||||||
const costResources =
|
const costResources =
|
||||||
result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value, total: -cost.total })) ||
|
result.costs?.filter(x => x.enabled).map(cost => ({ ...cost, value: -cost.value })) ||
|
||||||
{};
|
{};
|
||||||
result.resourceUpdates.addResources(costResources);
|
result.resourceUpdates.addResources(costResources);
|
||||||
await result.resourceUpdates.updateResources();
|
await result.resourceUpdates.updateResources();
|
||||||
|
|
@ -1193,15 +1193,6 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritdoc */
|
|
||||||
async _onDragStart(event) {
|
|
||||||
const inventoryItem = event.currentTarget.closest('.inventory-item');
|
|
||||||
if (inventoryItem) {
|
|
||||||
event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0);
|
|
||||||
}
|
|
||||||
super._onDragStart(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDropItem(event, item) {
|
async _onDropItem(event, item) {
|
||||||
const setupCriticalItemTypes = ['class', 'subclass', 'ancestry', 'community'];
|
const setupCriticalItemTypes = ['class', 'subclass', 'ancestry', 'community'];
|
||||||
if (this.document.system.needsCharacterSetup && setupCriticalItemTypes.includes(item.type)) {
|
if (this.document.system.needsCharacterSetup && setupCriticalItemTypes.includes(item.type)) {
|
||||||
|
|
|
||||||
|
|
@ -62,9 +62,7 @@ export default class DhCompanionSheet extends DHBaseActorSheet {
|
||||||
await this.document.update({ 'system.resources.stress.value': newValue });
|
await this.document.update({ 'system.resources.stress.value': newValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @this {DhCompanionSheet} **/
|
||||||
*
|
|
||||||
*/
|
|
||||||
static async #actionRoll(event) {
|
static async #actionRoll(event) {
|
||||||
const partner = this.actor.system.partner;
|
const partner = this.actor.system.partner;
|
||||||
const config = {
|
const config = {
|
||||||
|
|
@ -80,6 +78,7 @@ export default class DhCompanionSheet extends DHBaseActorSheet {
|
||||||
|
|
||||||
const result = await partner.diceRoll(config);
|
const result = await partner.diceRoll(config);
|
||||||
this.consumeResource(result?.costs);
|
this.consumeResource(result?.costs);
|
||||||
|
result?.resourceUpdates.updateResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove when Action Refactor part #2 done
|
// Remove when Action Refactor part #2 done
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,22 @@ export default class DhpEnvironment extends DHBaseActorSheet {
|
||||||
return applicationOptions;
|
return applicationOptions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
_prepareTabs(group) {
|
||||||
|
const result = super._prepareTabs(group);
|
||||||
|
if (group === 'primary') {
|
||||||
|
result.potentialAdversaries.empty = foundry.utils.isEmpty(this.document.system.potentialAdversaries);
|
||||||
|
result.notes.empty = !this.document.system.notes?.trim();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async _preparePartContext(partId, context, options) {
|
async _preparePartContext(partId, context, options) {
|
||||||
context = await super._preparePartContext(partId, context, options);
|
context = await super._preparePartContext(partId, context, options);
|
||||||
switch (partId) {
|
switch (partId) {
|
||||||
case 'header':
|
case 'header':
|
||||||
await this._prepareHeaderContext(context, options);
|
await this._prepareHeaderContext(context, options);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'features':
|
case 'features':
|
||||||
await this._prepareFeaturesContext(context, options);
|
await this._prepareFeaturesContext(context, options);
|
||||||
|
|
|
||||||
|
|
@ -162,9 +162,9 @@ export default class Party extends DHBaseActorSheet {
|
||||||
difficulty: actor.system.difficulty,
|
difficulty: actor.system.difficulty,
|
||||||
traits: actor.system.traits
|
traits: actor.system.traits
|
||||||
? traits.map(t => ({
|
? traits.map(t => ({
|
||||||
label: game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${t}.short`),
|
label: game.i18n.localize(`DAGGERHEART.CONFIG.Traits.${t}.short`),
|
||||||
value: actor.system.traits[t].value
|
value: actor.system.traits[t].value
|
||||||
}))
|
}))
|
||||||
: null,
|
: null,
|
||||||
weapons
|
weapons
|
||||||
});
|
});
|
||||||
|
|
@ -306,7 +306,7 @@ export default class Party extends DHBaseActorSheet {
|
||||||
|
|
||||||
static async downtimeMoveQuery({ actorId, downtimeType }) {
|
static async downtimeMoveQuery({ actorId, downtimeType }) {
|
||||||
const actor = await foundry.utils.fromUuid(actorId);
|
const actor = await foundry.utils.fromUuid(actorId);
|
||||||
if (!actor || !actor?.isOwner) reject();
|
if (!actor || !actor?.isOwner) return;
|
||||||
new game.system.api.applications.dialogs.Downtime(actor, downtimeType === 'shortRest').render({
|
new game.system.api.applications.dialogs.Downtime(actor, downtimeType === 'shortRest').render({
|
||||||
force: true
|
force: true
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
import DHApplicationMixin from './application-mixin.mjs';
|
import DHApplicationMixin from './application-mixin.mjs';
|
||||||
const { DocumentSheetV2 } = foundry.applications.api;
|
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||||
|
|
||||||
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
/**
|
||||||
|
* @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base settings sheet for Daggerheart actors.
|
* Base settings sheet for Daggerheart actors.
|
||||||
* @extends {DHApplicationMixin<DocumentSheetV2>}
|
* @extends {DHApplicationMixin<ActorSheetV2>}
|
||||||
*/
|
*/
|
||||||
export default class DHBaseActorSettings extends DHApplicationMixin(DocumentSheetV2) {
|
export default class DHBaseActorSettings extends DHApplicationMixin(ActorSheetV2) {
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
classes: ['dialog'],
|
classes: ['dialog'],
|
||||||
|
|
@ -23,7 +25,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee
|
||||||
},
|
},
|
||||||
dragDrop: [
|
dragDrop: [
|
||||||
{ dragSelector: null, dropSelector: '.tab.features' },
|
{ dragSelector: null, dropSelector: '.tab.features' },
|
||||||
{ dragSelector: '.feature-item', dropSelector: null }
|
{ dragSelector: '.feature-item, .inventory-item[data-type="feature"]', dropSelector: null }
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -34,7 +36,7 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**@returns {foundry.documents.Actor} */
|
/** @returns {foundry.documents.Actor} */
|
||||||
get actor() {
|
get actor() {
|
||||||
return this.document;
|
return this.document;
|
||||||
}
|
}
|
||||||
|
|
@ -73,4 +75,32 @@ export default class DHBaseActorSettings extends DHApplicationMixin(DocumentShee
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _onDragStart(event) {
|
||||||
|
const featureItemEl = event.currentTarget.closest('.feature-item, .inventory-item[data-type="feature"]');
|
||||||
|
const feature = this.actor.items.get(featureItemEl?.dataset.itemId);
|
||||||
|
if (feature && event.target.closest('.tab.features')) {
|
||||||
|
const featureData = { ...feature.toDragData(), fromInternal: true };
|
||||||
|
event.dataTransfer.setData('text/plain', JSON.stringify(featureData));
|
||||||
|
event.dataTransfer.setDragImage(featureItemEl.querySelector('img'), 60, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDrop(event) {
|
||||||
|
event.stopPropagation();
|
||||||
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
|
const item = await fromUuid(data.uuid);
|
||||||
|
if (item?.type === 'feature') {
|
||||||
|
if (data.fromInternal && item.parent?.uuid === this.actor.uuid) {
|
||||||
|
return super._onDrop(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemData = item.toObject();
|
||||||
|
delete itemData._id;
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [itemData]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Setting sheets do not auto extend */
|
||||||
|
async _autoExpandDescriptions() {}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import { getDocFromElement, getDocFromElementSync, tagifyElement } from '../../.
|
||||||
const typeSettingsMap = {
|
const typeSettingsMap = {
|
||||||
character: 'extendCharacterDescriptions',
|
character: 'extendCharacterDescriptions',
|
||||||
adversary: 'extendAdversaryDescriptions',
|
adversary: 'extendAdversaryDescriptions',
|
||||||
|
npc: 'extendAdversaryDescriptions',
|
||||||
environment: 'extendEnvironmentDescriptions',
|
environment: 'extendEnvironmentDescriptions',
|
||||||
ancestry: 'extendItemDescriptions',
|
ancestry: 'extendItemDescriptions',
|
||||||
community: 'extendItemDescriptions',
|
community: 'extendItemDescriptions',
|
||||||
|
|
@ -262,7 +263,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
|
|
||||||
if (!!this.options.contextMenus.length) this._createContextMenus();
|
if (!!this.options.contextMenus.length) this._createContextMenus();
|
||||||
|
|
||||||
this.#autoExtendDescriptions(context);
|
this._autoExpandDescriptions(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
@ -361,18 +362,17 @@ export default function DHApplicationMixin(Base) {
|
||||||
*/
|
*/
|
||||||
async _onDragStart(event) {
|
async _onDragStart(event) {
|
||||||
const inventoryItem = event.currentTarget.closest('.inventory-item');
|
const inventoryItem = event.currentTarget.closest('.inventory-item');
|
||||||
if (inventoryItem) {
|
if (!inventoryItem) return;
|
||||||
const { type, itemUuid } = inventoryItem.dataset;
|
|
||||||
if (type === 'effect') {
|
const { type, itemUuid } = inventoryItem.dataset;
|
||||||
const effect = await foundry.utils.fromUuid(itemUuid);
|
const effect = type === 'effect' ? await foundry.utils.fromUuid(itemUuid) : null;
|
||||||
const effectData = {
|
if (effect) {
|
||||||
type: 'ActiveEffect',
|
const effectData = {
|
||||||
data: { ...effect.toObject(), _id: null },
|
...effect.toDragData(),
|
||||||
fromInternal: this.document.uuid
|
fromInternal: this.document.uuid
|
||||||
};
|
};
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(effectData));
|
event.dataTransfer.setData('text/plain', JSON.stringify(effectData));
|
||||||
event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0);
|
event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,14 +382,33 @@ export default function DHApplicationMixin(Base) {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
_onDrop(event) {
|
_onDrop(event) {
|
||||||
|
// Potentially handle subclasses that dont descend from actor/item sheet.
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
return super._onDrop?.(event);
|
||||||
if (data.type === 'ActiveEffect' && data.fromInternal !== this.document.uuid) {
|
}
|
||||||
this.document.createEmbeddedDocuments('ActiveEffect', [data.data]);
|
|
||||||
} else {
|
/** @inheritdoc */
|
||||||
// Fallback to super, but note that item sheets do not have this function
|
_onSortItem(event, item) {
|
||||||
return super._onDrop?.(event);
|
// If we are dragging a feature past its allowed feature form, put it in the front or in the back
|
||||||
|
const doc = this.actor.items.get(item.id);
|
||||||
|
const dropTargetEl = event.target.closest('[data-item-id]');
|
||||||
|
const dropTarget = this.actor.items.get(dropTargetEl?.dataset.itemId);
|
||||||
|
if (doc?.type === 'feature' && dropTarget?.type === 'feature' && doc.system.featureForm !== dropTarget.system.featureForm) {
|
||||||
|
const siblings = this.actor.itemTypes.feature
|
||||||
|
.filter(f => f.system.featureForm === doc.system.featureForm)
|
||||||
|
.sort((a, b) => a.sort - b.sort);
|
||||||
|
if (siblings.length > 1) {
|
||||||
|
const featureForms = Object.keys(CONFIG.DH.ITEM.featureForm);
|
||||||
|
const thisFeatureIdx = featureForms.indexOf(doc.system.featureForm);
|
||||||
|
const targetFeatureIdx = featureForms.indexOf(dropTarget.system.featureForm);
|
||||||
|
const target = targetFeatureIdx < thisFeatureIdx ? siblings[0] : siblings.at(-1);
|
||||||
|
const sortUpdates = foundry.utils.performIntegerSort(doc, { target, siblings });
|
||||||
|
const updateData = sortUpdates.map(u => ({ ...u.update, _id: u.target._id }));
|
||||||
|
return this.actor.updateEmbeddedDocuments('Item', updateData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return super._onSortItem?.(event, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
@ -499,7 +518,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
const doc = await getDocFromElement(target),
|
const doc = await getDocFromElement(target),
|
||||||
action = doc?.system?.attack ?? doc;
|
action = doc?.system?.attack ?? doc;
|
||||||
const config = action.prepareConfig(event);
|
const config = action.prepareConfig(event);
|
||||||
config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(
|
config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(
|
||||||
this.document,
|
this.document,
|
||||||
doc
|
doc
|
||||||
);
|
);
|
||||||
|
|
@ -584,7 +603,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
const doc = await fromUuid(itemUuid);
|
const doc = await fromUuid(itemUuid);
|
||||||
|
|
||||||
//get inventory-item description element
|
//get inventory-item description element
|
||||||
const descriptionElement = el.querySelector('.invetory-description');
|
const descriptionElement = el.querySelector('.inventory-description');
|
||||||
if (!doc || !descriptionElement) continue;
|
if (!doc || !descriptionElement) continue;
|
||||||
|
|
||||||
// localize the description (idk if it's still necessary)
|
// localize the description (idk if it's still necessary)
|
||||||
|
|
@ -612,8 +631,9 @@ export default function DHApplicationMixin(Base) {
|
||||||
/**
|
/**
|
||||||
* Extend inventory description when enabled in settings.
|
* Extend inventory description when enabled in settings.
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
|
* @protected
|
||||||
*/
|
*/
|
||||||
async #autoExtendDescriptions(context) {
|
async _autoExpandDescriptions(context) {
|
||||||
const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]');
|
const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]');
|
||||||
for (const el of inventoryItems) {
|
for (const el of inventoryItems) {
|
||||||
// Get the doc uuid from the element
|
// Get the doc uuid from the element
|
||||||
|
|
@ -716,16 +736,16 @@ export default function DHApplicationMixin(Base) {
|
||||||
* @type {ApplicationClickAction}
|
* @type {ApplicationClickAction}
|
||||||
*/
|
*/
|
||||||
static async #onCreateDoc(event, target) {
|
static async #onCreateDoc(event, target) {
|
||||||
const { documentClass, type, inVault, disabled } = target.dataset;
|
const { documentClass, type, inVault, disabled, featureForm } = target.dataset;
|
||||||
const parentIsItem = this.document.documentName === 'Item';
|
const parentIsItem = this.document.documentName === 'Item';
|
||||||
const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature';
|
const featureOnCharacter = this.document.parent?.type === 'character' && type === 'feature';
|
||||||
const parent = featureOnCharacter
|
const parent = featureOnCharacter
|
||||||
? this.document.parent
|
? this.document.parent
|
||||||
: parentIsItem && documentClass === 'Item'
|
: parentIsItem && documentClass === 'Item'
|
||||||
? type === 'action'
|
? type === 'action'
|
||||||
? this.document.system
|
? this.document.system
|
||||||
: null
|
: null
|
||||||
: this.document;
|
: this.document;
|
||||||
|
|
||||||
let systemData = {};
|
let systemData = {};
|
||||||
if (featureOnCharacter) {
|
if (featureOnCharacter) {
|
||||||
|
|
@ -734,6 +754,7 @@ export default function DHApplicationMixin(Base) {
|
||||||
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
identifier: this.document.system.isMulticlass ? 'multiclass' : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
if (featureForm) systemData.featureForm = featureForm;
|
||||||
|
|
||||||
const cls =
|
const cls =
|
||||||
type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass);
|
type === 'action' ? game.system.api.models.actions.actionsTypes.base : getDocumentClass(documentClass);
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { getDocFromElement, itemIsIdentical } from '../../../helpers/utils.mjs';
|
import { getDocFromElement, itemIsIdentical } from '../../../helpers/utils.mjs';
|
||||||
import DHBaseActorSettings from './actor-setting.mjs';
|
|
||||||
import DHApplicationMixin from './application-mixin.mjs';
|
import DHApplicationMixin from './application-mixin.mjs';
|
||||||
|
|
||||||
const { ActorSheetV2 } = foundry.applications.sheets;
|
const { ActorSheetV2 } = foundry.applications.sheets;
|
||||||
|
|
||||||
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
/**
|
||||||
|
* @import DHBaseActorSettings from './actor-setting.mjs';
|
||||||
|
* @typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base actor sheet extending {@link ActorSheetV2} via {@link DHApplicationMixin}
|
* A base actor sheet extending {@link ActorSheetV2} via {@link DHApplicationMixin}
|
||||||
|
|
@ -210,7 +212,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
const doc = await getDocFromElement(target),
|
const doc = await getDocFromElement(target),
|
||||||
action = doc?.system?.attack ?? doc;
|
action = doc?.system?.attack ?? doc;
|
||||||
const config = action.prepareConfig(event);
|
const config = action.prepareConfig(event);
|
||||||
config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(
|
config.effects = await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(
|
||||||
this.document,
|
this.document,
|
||||||
doc
|
doc
|
||||||
);
|
);
|
||||||
|
|
@ -377,7 +379,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
action: 'update',
|
action: 'update',
|
||||||
documentName: 'Item',
|
documentName: 'Item',
|
||||||
parent: targetActor,
|
parent: targetActor,
|
||||||
updates: [{ '_id': existing.id, 'system.quantity': existing.system.quantity + quantity }]
|
updates: [{ _id: existing.id, 'system.quantity': existing.system.quantity + quantity }]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
const itemsToCreate = [];
|
const itemsToCreate = [];
|
||||||
|
|
@ -410,7 +412,7 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
action: 'update',
|
action: 'update',
|
||||||
documentName: 'Item',
|
documentName: 'Item',
|
||||||
parent: originActor,
|
parent: originActor,
|
||||||
updates: [{ '_id': item.id, 'system.quantity': item.system.quantity - quantity }]
|
updates: [{ _id: item.id, 'system.quantity': item.system.quantity - quantity }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -447,13 +449,15 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) {
|
||||||
|
|
||||||
const item = await getDocFromElement(event.target);
|
const item = await getDocFromElement(event.target);
|
||||||
if (item) {
|
if (item) {
|
||||||
|
const inventoryItem = event.currentTarget.closest('.inventory-item');
|
||||||
const dragData = {
|
const dragData = {
|
||||||
|
...item.toDragData(),
|
||||||
originActor: this.document.uuid,
|
originActor: this.document.uuid,
|
||||||
originId: item.id,
|
originId: item.id
|
||||||
type: item.documentName,
|
|
||||||
uuid: item.uuid
|
|
||||||
};
|
};
|
||||||
event.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
event.dataTransfer.setData('text/plain', JSON.stringify(dragData));
|
||||||
|
if (inventoryItem) event.dataTransfer.setDragImage(inventoryItem.querySelector('img'), 60, 0);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
super._onDragStart(event);
|
super._onDragStart(event);
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,6 @@ export default function ItemAttachmentSheet(Base) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
async _preparePartContext(partId, context) {
|
|
||||||
await super._preparePartContext(partId, context);
|
|
||||||
|
|
||||||
if (partId === 'attachments') {
|
|
||||||
context.attachedItems = await prepareAttachmentContext(this.document);
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ export default class SubclassSheet extends DHBaseItemSheet {
|
||||||
const item = await fromUuid(data.uuid);
|
const item = await fromUuid(data.uuid);
|
||||||
const itemType = data.type === 'ActiveEffect' ? data.type : item.type;
|
const itemType = data.type === 'ActiveEffect' ? data.type : item.type;
|
||||||
if (itemType === 'class') {
|
if (itemType === 'class') {
|
||||||
const uuid = item._stats.compendiumSource ?? item.uuid;
|
const uuid = item.sourceUuid;
|
||||||
if (this.document.system.linkedClass !== uuid) {
|
if (this.document.system.linkedClass !== uuid) {
|
||||||
await this.document.update({ 'system.linkedClass': uuid });
|
await this.document.update({ 'system.linkedClass': uuid });
|
||||||
// Re-render all class sheets for instant feedback
|
// Re-render all class sheets for instant feedback
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
export default class DhActorDirectory extends foundry.applications.sidebar.tabs.ActorDirectory {
|
export default class DhActorDirectory extends foundry.applications.sidebar.tabs.ActorDirectory {
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
renderUpdateKeys: ['system.levelData.level.current', 'system.partner', 'system.tier']
|
renderUpdateKeys: ['system.levelData.level.current', 'system.partner', 'system.tier', 'system.type']
|
||||||
};
|
};
|
||||||
|
|
||||||
static _entryPartial = 'systems/daggerheart/templates/ui/sidebar/actor-document-partial.hbs';
|
static _entryPartial = 'systems/daggerheart/templates/ui/sidebar/actor-document-partial.hbs';
|
||||||
|
|
@ -13,8 +13,8 @@ export default class DhActorDirectory extends foundry.applications.sidebar.tabs.
|
||||||
return document.type === 'adversary'
|
return document.type === 'adversary'
|
||||||
? game.i18n.localize(adversaryTypes[document.system.type]?.label ?? 'TYPES.Actor.adversary')
|
? game.i18n.localize(adversaryTypes[document.system.type]?.label ?? 'TYPES.Actor.adversary')
|
||||||
: document.type === 'environment'
|
: document.type === 'environment'
|
||||||
? game.i18n.localize(environmentTypes[document.system.type]?.label ?? 'TYPES.Actor.environment')
|
? game.i18n.localize(environmentTypes[document.system.type]?.label ?? 'TYPES.Actor.environment')
|
||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,3 +8,4 @@ export { default as DhHotbar } from './hotbar.mjs';
|
||||||
export { default as DhSceneNavigation } from './sceneNavigation.mjs';
|
export { default as DhSceneNavigation } from './sceneNavigation.mjs';
|
||||||
export { ItemBrowser } from './itemBrowser.mjs';
|
export { ItemBrowser } from './itemBrowser.mjs';
|
||||||
export { default as DhProgress } from './progress.mjs';
|
export { default as DhProgress } from './progress.mjs';
|
||||||
|
export { default as DhGamePause } from './gamePause.mjs';
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
const advantage = rollCommand.advantage
|
const advantage = rollCommand.advantage
|
||||||
? CONFIG.DH.ACTIONS.advantageState.advantage.value
|
? CONFIG.DH.ACTIONS.advantageState.advantage.value
|
||||||
: rollCommand.disadvantage
|
: rollCommand.disadvantage
|
||||||
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
|
? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
|
||||||
: undefined;
|
: undefined;
|
||||||
const difficulty = rollCommand.difficulty;
|
const difficulty = rollCommand.difficulty;
|
||||||
const grantResources = rollCommand.grantResources;
|
const grantResources = rollCommand.grantResources;
|
||||||
|
|
||||||
|
|
@ -50,8 +50,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
const title =
|
const title =
|
||||||
(flavor ?? traitValue)
|
(flavor ?? traitValue)
|
||||||
? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label)
|
ability: game.i18n.localize(CONFIG.DH.ACTOR.abilities[traitValue].label)
|
||||||
})
|
})
|
||||||
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
: game.i18n.localize('DAGGERHEART.GENERAL.duality');
|
||||||
|
|
||||||
enrichedDualityRoll({
|
enrichedDualityRoll({
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
||||||
|
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
countdowns: {
|
countdowns: {
|
||||||
template: 'systems/daggerheart/templates/ui/countdown-edit.hbs',
|
template: 'systems/daggerheart/templates/ui/countdowns/countdown-edit.hbs',
|
||||||
scrollable: ['.expanded-view', '.edit-content']
|
scrollable: ['.expanded-view', '.edit-content']
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -45,7 +45,7 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
||||||
context.isGM = game.user.isGM;
|
context.isGM = game.user.isGM;
|
||||||
context.ownershipDefaultOptions = CONFIG.DH.GENERAL.basicOwnershiplevels;
|
context.ownershipDefaultOptions = CONFIG.DH.GENERAL.basicOwnershiplevels;
|
||||||
context.defaultOwnership = this.data.defaultOwnership;
|
context.defaultOwnership = this.data.defaultOwnership;
|
||||||
context.countdownBaseTypes = CONFIG.DH.GENERAL.countdownBaseTypes;
|
context.countdownTypes = CONFIG.DH.GENERAL.countdownTypes;
|
||||||
context.countdownProgressionTypes = CONFIG.DH.GENERAL.countdownProgressionTypes;
|
context.countdownProgressionTypes = CONFIG.DH.GENERAL.countdownProgressionTypes;
|
||||||
context.countdownLoopingTypes = CONFIG.DH.GENERAL.countdownLoopingTypes;
|
context.countdownLoopingTypes = CONFIG.DH.GENERAL.countdownLoopingTypes;
|
||||||
context.hideNewCountdowns = this.hideNewCountdowns;
|
context.hideNewCountdowns = this.hideNewCountdowns;
|
||||||
|
|
@ -56,13 +56,13 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
||||||
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
||||||
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
|
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
|
||||||
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
||||||
? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
|
? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
|
||||||
: 'DAGGERHEART.UI.Countdowns.loop'
|
: 'DAGGERHEART.UI.Countdowns.loop'
|
||||||
: null;
|
: null;
|
||||||
const randomizeValid = !new Roll(countdown.progress.startFormula ?? '').isDeterministic;
|
const randomizeValid = !new Roll(countdown.progress.startFormula ?? '').isDeterministic;
|
||||||
acc[key] = {
|
acc[key] = {
|
||||||
...countdown,
|
...countdown,
|
||||||
typeName: game.i18n.localize(CONFIG.DH.GENERAL.countdownBaseTypes[countdown.type].label),
|
typeName: game.i18n.localize(CONFIG.DH.GENERAL.countdownTypes[countdown.type].label),
|
||||||
progress: {
|
progress: {
|
||||||
...countdown.progress,
|
...countdown.progress,
|
||||||
typeName: game.i18n.localize(
|
typeName: game.i18n.localize(
|
||||||
|
|
@ -148,11 +148,11 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
|
||||||
}
|
}
|
||||||
|
|
||||||
async gmSetSetting(data) {
|
async gmSetSetting(data) {
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data),
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
|
||||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||||
action: socketEvent.Refresh,
|
action: socketEvent.Refresh,
|
||||||
data: { refreshType: RefreshType.Countdown }
|
data: { refreshType: RefreshType.Countdown }
|
||||||
});
|
});
|
||||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,14 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
export default class DhCountdowns extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
|
previousCountdownData = null;
|
||||||
|
changedCountdownsForAnimation = new Set();
|
||||||
|
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
|
this.previousCountdownData =
|
||||||
|
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns).countdowns;
|
||||||
this.setupHooks();
|
this.setupHooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -31,9 +36,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
minimizable: false
|
minimizable: false
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
toggleViewMode: DhCountdowns.#toggleViewMode,
|
toggleViewMode: DhCountdowns.#onToggleViewMode,
|
||||||
editCountdowns: DhCountdowns.#editCountdowns,
|
toggleCountdownTypes: DhCountdowns.#onToggleCountdownTypes,
|
||||||
loopCountdown: DhCountdowns.#loopCountdown,
|
editCountdowns: DhCountdowns.#onEditCountdowns,
|
||||||
|
loopCountdown: DhCountdowns.#onLoopCountdown,
|
||||||
decreaseCountdown: (_, target) => this.editCountdown(false, target),
|
decreaseCountdown: (_, target) => this.editCountdown(false, target),
|
||||||
increaseCountdown: (_, target) => this.editCountdown(true, target)
|
increaseCountdown: (_, target) => this.editCountdown(true, target)
|
||||||
},
|
},
|
||||||
|
|
@ -48,11 +54,20 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
static PARTS = {
|
static PARTS = {
|
||||||
resources: {
|
resources: {
|
||||||
root: true,
|
root: true,
|
||||||
template: 'systems/daggerheart/templates/ui/countdowns.hbs'
|
template: 'systems/daggerheart/templates/ui/countdowns/countdowns-view.hbs'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**
|
||||||
|
* Returns all visible countdown types
|
||||||
|
* @returns {string[]}
|
||||||
|
*/
|
||||||
|
get visibleCountdownTypes() {
|
||||||
|
const { encounter, narrative } = CONFIG.DH.GENERAL.countdownTypes;
|
||||||
|
return game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes)
|
||||||
|
?? [encounter.id, narrative.id];
|
||||||
|
}
|
||||||
|
|
||||||
async _renderFrame(options) {
|
async _renderFrame(options) {
|
||||||
const frame = await super._renderFrame(options);
|
const frame = await super._renderFrame(options);
|
||||||
|
|
||||||
|
|
@ -65,6 +80,57 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options);
|
||||||
|
|
||||||
|
/* Handle rendering/hiding/positioning of the countdown UI */
|
||||||
|
this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0;
|
||||||
|
if (options?.force) {
|
||||||
|
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.previousCountdownData = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns)
|
||||||
|
.countdowns;
|
||||||
|
|
||||||
|
/* Handle animations to draw attention to countdown values changing */
|
||||||
|
const typesToAnimate = new Set();
|
||||||
|
for (const countdownKey of this.changedCountdownsForAnimation) {
|
||||||
|
const shimmerAnimation = [
|
||||||
|
{ backgroundPositionX: '98%' },
|
||||||
|
{ backgroundPositionX: '0%' }
|
||||||
|
];
|
||||||
|
const shimmerTiming = {
|
||||||
|
duration: 1000,
|
||||||
|
iterations: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = this.element.querySelector(`.countdown-container[data-countdown="${countdownKey}"]`);
|
||||||
|
element?.animate(shimmerAnimation, shimmerTiming);
|
||||||
|
|
||||||
|
const countdown = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns)
|
||||||
|
.countdowns[countdownKey];
|
||||||
|
if (!this.visibleCountdownTypes.includes(countdown?.type))
|
||||||
|
typesToAnimate.add(countdown.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const type of typesToAnimate) {
|
||||||
|
const pulseAnimation = [
|
||||||
|
{ boxShadow: '0 0 1px 1px var(--golden)' },
|
||||||
|
{ boxShadow: '0 0 2px 2px var(--golden)' }
|
||||||
|
];
|
||||||
|
const pulseTiming = {
|
||||||
|
duration: 1000,
|
||||||
|
iterations: 3
|
||||||
|
};
|
||||||
|
|
||||||
|
const element = this.element.querySelector(`.header-type-toggles .header-type[data-type="${type}"]`);
|
||||||
|
element?.animate(pulseAnimation, pulseTiming);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.changedCountdownsForAnimation.clear();
|
||||||
|
}
|
||||||
|
|
||||||
/** Returns countdown data filtered by ownership */
|
/** Returns countdown data filtered by ownership */
|
||||||
#getCountdowns() {
|
#getCountdowns() {
|
||||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
|
|
@ -76,16 +142,10 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
return values.filter(v => v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE);
|
return values.filter(v => v.ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
_getCountdownData() {
|
||||||
async _prepareContext(options) {
|
|
||||||
const context = await super._prepareContext(options);
|
|
||||||
context.isGM = game.user.isGM;
|
|
||||||
|
|
||||||
context.iconOnly =
|
|
||||||
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode) ===
|
|
||||||
CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
|
|
||||||
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const setting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
context.countdowns = this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
|
|
||||||
|
return this.#getCountdowns().reduce((acc, { key, countdown, ownership }) => {
|
||||||
const playersWithAccess = game.users.reduce((acc, user) => {
|
const playersWithAccess = game.users.reduce((acc, user) => {
|
||||||
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
const ownership = DhCountdowns.#getPlayerOwnership(user, setting, countdown);
|
||||||
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
if (!user.isGM && ownership && ownership !== CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
|
||||||
|
|
@ -101,14 +161,14 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
||||||
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
|
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
|
||||||
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
||||||
? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
|
? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
|
||||||
: 'DAGGERHEART.UI.Countdowns.loop'
|
: 'DAGGERHEART.UI.Countdowns.loop'
|
||||||
: null;
|
: null;
|
||||||
const loopDisabled =
|
const loopDisabled =
|
||||||
!countdownEditable ||
|
!countdownEditable ||
|
||||||
(isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0'));
|
(isLooping && (countdown.progress.current > 0 || countdown.progress.start === '0'));
|
||||||
|
|
||||||
acc[key] = {
|
acc[countdown.type][key] = {
|
||||||
...countdown,
|
...countdown,
|
||||||
editable: countdownEditable,
|
editable: countdownEditable,
|
||||||
noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0,
|
noPlayerAccess: nonGmPlayers.length && playersWithAccess.length === 0,
|
||||||
|
|
@ -117,7 +177,38 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
loopTooltip: isLooping && game.i18n.localize(loopTooltip)
|
loopTooltip: isLooping && game.i18n.localize(loopTooltip)
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, Object.keys(CONFIG.DH.GENERAL.countdownTypes).reduce((acc, key) => {
|
||||||
|
acc[key] = {};
|
||||||
|
return acc;
|
||||||
|
}, {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext(options) {
|
||||||
|
const context = await super._prepareContext(options);
|
||||||
|
context.isGM = game.user.isGM;
|
||||||
|
|
||||||
|
context.iconOnly =
|
||||||
|
game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode)
|
||||||
|
=== CONFIG.DH.GENERAL.countdownAppMode.iconOnly;
|
||||||
|
|
||||||
|
context.userCountdownTypes = this.visibleCountdownTypes;
|
||||||
|
|
||||||
|
context.typeToggles =
|
||||||
|
Object.values(CONFIG.DH.GENERAL.countdownTypes).map(type => ({
|
||||||
|
type: type.id,
|
||||||
|
label: game.i18n.localize(type.shortLabel),
|
||||||
|
active: context.userCountdownTypes.includes(type.id)
|
||||||
|
}));
|
||||||
|
|
||||||
|
context.countdowns = this._getCountdownData();
|
||||||
|
context.countdownTypesWithVisibleEntries = this.#getCountdowns().reduce((acc, data) => {
|
||||||
|
if (context.userCountdownTypes.includes(data.countdown.type) && !acc.includes(data.countdown.type))
|
||||||
|
acc.push(data.countdown.type);
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
@ -147,7 +238,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #toggleViewMode() {
|
/** @this {DhCountdowns} */
|
||||||
|
static async #onToggleViewMode() {
|
||||||
const currentMode = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode);
|
const currentMode = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode);
|
||||||
const appMode = CONFIG.DH.GENERAL.countdownAppMode;
|
const appMode = CONFIG.DH.GENERAL.countdownAppMode;
|
||||||
const newMode = currentMode === appMode.textIcon ? appMode.iconOnly : appMode.textIcon;
|
const newMode = currentMode === appMode.textIcon ? appMode.iconOnly : appMode.textIcon;
|
||||||
|
|
@ -158,15 +250,30 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #editCountdowns() {
|
/** @this {DhCountdowns} */
|
||||||
|
static async #onToggleCountdownTypes(event, target) {
|
||||||
|
const currentTypes = this.visibleCountdownTypes;
|
||||||
|
const { type } = target.dataset;
|
||||||
|
const newTypes = event.shiftKey ?
|
||||||
|
[type] :
|
||||||
|
currentTypes.includes(type) ? currentTypes.filter(x => x !== type) : [...currentTypes, type];
|
||||||
|
await game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownTypeModes, newTypes);
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @this {DhCountdowns} */
|
||||||
|
static async #onEditCountdowns() {
|
||||||
new game.system.api.applications.ui.CountdownEdit().render(true);
|
new game.system.api.applications.ui.CountdownEdit().render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async #loopCountdown(_, target) {
|
/** @this {DhCountdowns} */
|
||||||
|
static async #onLoopCountdown(_, target) {
|
||||||
if (!DhCountdowns.canPerformEdit()) return;
|
if (!DhCountdowns.canPerformEdit()) return;
|
||||||
|
|
||||||
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
const countdown = settings.countdowns[target.id];
|
const countdownId = target.closest('[data-countdown]').dataset.countdown;
|
||||||
|
const countdown = settings.countdowns[countdownId];
|
||||||
|
|
||||||
let progressMax = countdown.progress.start;
|
let progressMax = countdown.progress.start;
|
||||||
let message = null;
|
let message = null;
|
||||||
|
|
@ -180,12 +287,12 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
|
||||||
? Number(progressMax) + 1
|
? Number(progressMax) + 1
|
||||||
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
|
||||||
? Math.max(Number(progressMax) - 1, 0)
|
? Math.max(Number(progressMax) - 1, 0)
|
||||||
: progressMax;
|
: progressMax;
|
||||||
|
|
||||||
await waitForDiceSoNice(message);
|
await waitForDiceSoNice(message);
|
||||||
await settings.updateSource({
|
await settings.updateSource({
|
||||||
[`countdowns.${target.id}.progress`]: {
|
[`countdowns.${countdownId}.progress`]: {
|
||||||
current: newMax,
|
current: newMax,
|
||||||
start: newMax
|
start: newMax
|
||||||
}
|
}
|
||||||
|
|
@ -199,22 +306,23 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
if (!DhCountdowns.canPerformEdit()) return;
|
if (!DhCountdowns.canPerformEdit()) return;
|
||||||
|
|
||||||
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
const countdown = settings.countdowns[target.id];
|
const countdownId = target.closest('[data-countdown]').dataset.countdown;
|
||||||
|
const countdown = settings.countdowns[countdownId];
|
||||||
const newCurrent = increase
|
const newCurrent = increase
|
||||||
? Math.min(countdown.progress.current + 1, countdown.progress.start)
|
? Math.min(countdown.progress.current + 1, countdown.progress.start)
|
||||||
: Math.max(countdown.progress.current - 1, 0);
|
: Math.max(countdown.progress.current - 1, 0);
|
||||||
await settings.updateSource({ [`countdowns.${target.id}.progress.current`]: newCurrent });
|
await settings.updateSource({ [`countdowns.${countdownId}.progress.current`]: newCurrent });
|
||||||
await emitGMUpdate(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, {
|
await emitGMUpdate(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, {
|
||||||
refreshType: RefreshType.Countdown
|
refreshType: RefreshType.Countdown
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async gmSetSetting(data) {
|
static async gmSetSetting(data) {
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data),
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
|
||||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||||
action: socketEvent.Refresh,
|
action: socketEvent.Refresh,
|
||||||
data: { refreshType: RefreshType.Countdown }
|
data: { refreshType: RefreshType.Countdown }
|
||||||
});
|
});
|
||||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,29 +342,31 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
* Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to
|
* Sends updates of the countdowns to the GM player. Since this is asynchronous, be sure to
|
||||||
* update all the countdowns at the same time.
|
* update all the countdowns at the same time.
|
||||||
*
|
*
|
||||||
* @param {...any} progressTypes Countdowns to be updated
|
* @param {...(string | { type: string; undo?: boolean })} progressTypes Countdowns to be updated
|
||||||
*/
|
*/
|
||||||
static async updateCountdowns(...progressTypes) {
|
static async updateCountdowns(...progressTypes) {
|
||||||
|
progressTypes = progressTypes.map(p => typeof p === 'string' ? { type: p } : p);
|
||||||
const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
|
const { countdownAutomation } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
|
||||||
if (!countdownAutomation) return;
|
if (!countdownAutomation) return;
|
||||||
|
|
||||||
const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
const countdownSetting = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
|
||||||
const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => {
|
const updatedCountdowns = Object.keys(countdownSetting.countdowns).reduce((acc, key) => {
|
||||||
const countdown = countdownSetting.countdowns[key];
|
const countdown = countdownSetting.countdowns[key];
|
||||||
if (progressTypes.indexOf(countdown.progress.type) !== -1 && countdown.progress.current > 0) {
|
const progressData = progressTypes.find(x => x.type === countdown.progress.type);
|
||||||
acc.push(key);
|
if (progressData && countdown.progress.current > 0) {
|
||||||
|
acc[key] = { value: progressData.undo ? 1 : -1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
}, []);
|
}, {});
|
||||||
|
|
||||||
const countdownData = countdownSetting.toObject();
|
const countdownData = countdownSetting.toObject();
|
||||||
const settings = {
|
const settings = {
|
||||||
...countdownData,
|
...countdownData,
|
||||||
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
countdowns: Object.keys(countdownData.countdowns).reduce((acc, key) => {
|
||||||
const countdown = foundry.utils.deepClone(countdownData.countdowns[key]);
|
const countdown = foundry.utils.deepClone(countdownData.countdowns[key]);
|
||||||
if (updatedCountdowns.includes(key)) {
|
if (updatedCountdowns[key]) {
|
||||||
countdown.progress.current -= 1;
|
countdown.progress.current += updatedCountdowns[key].value;
|
||||||
}
|
}
|
||||||
|
|
||||||
acc[key] = countdown;
|
acc[key] = countdown;
|
||||||
|
|
@ -267,12 +377,4 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
|
||||||
refreshType: RefreshType.Countdown
|
refreshType: RefreshType.Countdown
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onRender(context, options) {
|
|
||||||
await super._onRender(context, options);
|
|
||||||
this.element.hidden = !game.user.isGM && this.#getCountdowns().length === 0;
|
|
||||||
if (options?.force) {
|
|
||||||
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,10 +67,10 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica
|
||||||
const actor = token
|
const actor = token
|
||||||
? token.actor
|
? token.actor
|
||||||
: canvas.tokens.controlled.length === 0
|
: canvas.tokens.controlled.length === 0
|
||||||
? !game.user.isGM
|
? !game.user.isGM
|
||||||
? game.user.character
|
? game.user.character
|
||||||
: null
|
: null
|
||||||
: canvas.tokens.controlled[0].actor;
|
: canvas.tokens.controlled[0].actor;
|
||||||
return getIconVisibleActiveEffects(actor?.getActiveEffects() ?? []);
|
return getIconVisibleActiveEffects(actor?.getActiveEffects() ?? []);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
23
module/applications/ui/gamePause.mjs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
export default class DhGamePause extends foundry.applications.ui.GamePause {
|
||||||
|
async _onRender(context, options) {
|
||||||
|
await super._onRender(context, options);
|
||||||
|
|
||||||
|
/* Avoid altering the styling if a module has subscribed to the renderGamePause hook */
|
||||||
|
if (!Hooks.events.renderGamePause?.length) {
|
||||||
|
this.element.classList.add('dh-style');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
async _prepareContext(options) {
|
||||||
|
const context = await super._prepareContext(options);
|
||||||
|
|
||||||
|
/* Avoid altering the gamepause context if a module has subscribed to the renderGamePause hook */
|
||||||
|
if (!Hooks.events.renderGamePause?.length) {
|
||||||
|
context.spin = options.spin ?? false;
|
||||||
|
context.icon = options.icon ?? 'systems/daggerheart/assets/logos/compatible_with_DH_logos-10.png';
|
||||||
|
}
|
||||||
|
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -155,15 +155,15 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const targetEdge = this.#getEdgeBoundary(targetBounds, originPoint, targetPoint);
|
const targetEdge = this.#getEdgeBoundary(targetBounds, originPoint, targetPoint);
|
||||||
const adjustedOriginPoint = originEdge
|
const adjustedOriginPoint = originEdge
|
||||||
? canvas.grid.getTopLeftPoint({
|
? canvas.grid.getTopLeftPoint({
|
||||||
x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
|
x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
|
||||||
y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
|
y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
|
||||||
})
|
})
|
||||||
: originPoint;
|
: originPoint;
|
||||||
const adjustDestinationPoint = targetEdge
|
const adjustDestinationPoint = targetEdge
|
||||||
? canvas.grid.getTopLeftPoint({
|
? canvas.grid.getTopLeftPoint({
|
||||||
x: targetEdge.x + Math.sign(targetPoint.x - targetEdge.x),
|
x: targetEdge.x + Math.sign(targetPoint.x - targetEdge.x),
|
||||||
y: targetEdge.y + Math.sign(targetPoint.y - targetEdge.y)
|
y: targetEdge.y + Math.sign(targetPoint.y - targetEdge.y)
|
||||||
})
|
})
|
||||||
: targetPoint;
|
: targetPoint;
|
||||||
const distance = canvas.grid.measurePath([
|
const distance = canvas.grid.measurePath([
|
||||||
{ ...adjustedOriginPoint, elevation: 0 },
|
{ ...adjustedOriginPoint, elevation: 0 },
|
||||||
|
|
@ -248,7 +248,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
_drawBar(number, bar, data) {
|
_drawBar(index, bar, data) {
|
||||||
// Determine sizing
|
// Determine sizing
|
||||||
const { width, height } = this.document.getSize();
|
const { width, height } = this.document.getSize();
|
||||||
const s = canvas.dimensions.uiScale;
|
const s = canvas.dimensions.uiScale;
|
||||||
|
|
@ -256,9 +256,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const bh = 8 * (this.document.height >= 2 ? 1.5 : 1) * s;
|
const bh = 8 * (this.document.height >= 2 ? 1.5 : 1) * s;
|
||||||
|
|
||||||
// Determine the color to use
|
// Determine the color to use
|
||||||
const Color = foundry.utils.Color;
|
const { full: fullColor, empty: emptyColor } = this._getBarColors(index, data);
|
||||||
const fillColor = number === 0 ? Color.fromRGB([1, 0, 0]) : Color.fromString('#0032b1');
|
|
||||||
const emptyColor = Color.fromRGB([0, 0, 0]);
|
|
||||||
|
|
||||||
// Draw the bar (accounting floating point numbers from bar animations)
|
// Draw the bar (accounting floating point numbers from bar animations)
|
||||||
const widthUnit = bw / Math.ceil(data.max);
|
const widthUnit = bw / Math.ceil(data.max);
|
||||||
|
|
@ -268,7 +266,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
const x = mark * widthUnit;
|
const x = mark * widthUnit;
|
||||||
const marked = mark < Math.ceil(data.value);
|
const marked = mark < Math.ceil(data.value);
|
||||||
const remainder = mark === Math.ceil(data.value) - 1 ? data.value % 1 : 0;
|
const remainder = mark === Math.ceil(data.value) - 1 ? data.value % 1 : 0;
|
||||||
const color = !marked ? emptyColor : remainder ? emptyColor.mix(fillColor, remainder) : fillColor;
|
const color = !marked ? emptyColor : remainder ? emptyColor.mix(fullColor, remainder) : fullColor;
|
||||||
if (mark === 0 || mark === sections.length - 1) {
|
if (mark === 0 || mark === sections.length - 1) {
|
||||||
bar.beginFill(color, marked ? 1.0 : 0.5).drawRect(x, 0, widthUnit, bh, 2 * s); // Would like drawRoundedRect, but it's very troublsome with the corners. Leaving for now.
|
bar.beginFill(color, marked ? 1.0 : 0.5).drawRect(x, 0, widthUnit, bh, 2 * s); // Would like drawRoundedRect, but it's very troublsome with the corners. Leaving for now.
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -277,7 +275,7 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set position
|
// Set position
|
||||||
const posY = number === 0 ? height - bh : 0;
|
const posY = index === 0 ? height - bh : 0;
|
||||||
bar.position.set(0, posY);
|
bar.position.set(0, posY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,8 @@ export const itemAttachmentSource = 'attachmentSource';
|
||||||
|
|
||||||
export const userFlags = {
|
export const userFlags = {
|
||||||
welcomeMessage: 'welcome-message',
|
welcomeMessage: 'welcome-message',
|
||||||
countdownMode: 'countdown-mode'
|
countdownMode: 'countdown-mode',
|
||||||
|
countdownTypeModes: 'countdown-type-modes'
|
||||||
};
|
};
|
||||||
|
|
||||||
export const combatToggle = 'combat-toggle-origin';
|
export const combatToggle = 'combat-toggle-origin';
|
||||||
|
|
|
||||||
|
|
@ -867,27 +867,27 @@ export const abilityCosts = {
|
||||||
export const countdownProgressionTypes = {
|
export const countdownProgressionTypes = {
|
||||||
actionRoll: {
|
actionRoll: {
|
||||||
id: 'actionRoll',
|
id: 'actionRoll',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.actionRoll'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.actionRoll'
|
||||||
},
|
},
|
||||||
characterAttack: {
|
characterAttack: {
|
||||||
id: 'characterAttack',
|
id: 'characterAttack',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.characterAttack'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.characterAttack'
|
||||||
},
|
},
|
||||||
characterSpotlight: {
|
characterSpotlight: {
|
||||||
id: 'characterSpotlight',
|
id: 'characterSpotlight',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.characterSpotlight'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.characterSpotlight'
|
||||||
},
|
},
|
||||||
custom: {
|
custom: {
|
||||||
id: 'custom',
|
id: 'custom',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.custom'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.custom'
|
||||||
},
|
},
|
||||||
fear: {
|
fear: {
|
||||||
id: 'fear',
|
id: 'fear',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.fear'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.fear'
|
||||||
},
|
},
|
||||||
spotlight: {
|
spotlight: {
|
||||||
id: 'spotlight',
|
id: 'spotlight',
|
||||||
label: 'DAGGERHEART.CONFIG.CountdownType.spotlight'
|
label: 'DAGGERHEART.CONFIG.CountdownProgressType.spotlight'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
export const rollTypes = {
|
export const rollTypes = {
|
||||||
|
|
@ -935,17 +935,6 @@ export const simpleOwnershiplevels = {
|
||||||
...basicOwnershiplevels
|
...basicOwnershiplevels
|
||||||
};
|
};
|
||||||
|
|
||||||
export const countdownBaseTypes = {
|
|
||||||
narrative: {
|
|
||||||
id: 'narrative',
|
|
||||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.types.narrative'
|
|
||||||
},
|
|
||||||
encounter: {
|
|
||||||
id: 'encounter',
|
|
||||||
label: 'DAGGERHEART.APPLICATIONS.Countdown.types.encounter'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const countdownLoopingTypes = {
|
export const countdownLoopingTypes = {
|
||||||
noLooping: {
|
noLooping: {
|
||||||
id: 'noLooping',
|
id: 'noLooping',
|
||||||
|
|
@ -970,6 +959,19 @@ export const countdownAppMode = {
|
||||||
iconOnly: 'icon-only'
|
iconOnly: 'icon-only'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const countdownTypes = {
|
||||||
|
encounter: {
|
||||||
|
id: 'encounter',
|
||||||
|
label: 'DAGGERHEART.CONFIG.CountdownType.encounter.label',
|
||||||
|
shortLabel: 'DAGGERHEART.CONFIG.CountdownType.encounter.shortLabel'
|
||||||
|
},
|
||||||
|
narrative: {
|
||||||
|
id: 'narrative',
|
||||||
|
label: 'DAGGERHEART.CONFIG.CountdownType.narrative.label',
|
||||||
|
shortLabel: 'DAGGERHEART.CONFIG.CountdownType.narrative.shortLabel'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const sceneRangeMeasurementSetting = {
|
export const sceneRangeMeasurementSetting = {
|
||||||
disable: {
|
disable: {
|
||||||
id: 'disable',
|
id: 'disable',
|
||||||
|
|
|
||||||
|
|
@ -127,8 +127,8 @@ export const typeConfig = {
|
||||||
isSecondary
|
isSecondary
|
||||||
? 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short'
|
? 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short'
|
||||||
: isSecondary === false
|
: isSecondary === false
|
||||||
? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short'
|
? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short'
|
||||||
: '-'
|
: '-'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'system.tier',
|
key: 'system.tier',
|
||||||
|
|
|
||||||
|
|
@ -79,8 +79,8 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
const str = damageString
|
const str = damageString
|
||||||
? damageString
|
? damageString
|
||||||
: game.i18n.format('DAGGERHEART.GENERAL.missingX', {
|
: game.i18n.format('DAGGERHEART.GENERAL.missingX', {
|
||||||
x: game.i18n.localize('DAGGERHEART.GENERAL.damage')
|
x: game.i18n.localize('DAGGERHEART.GENERAL.damage')
|
||||||
});
|
});
|
||||||
|
|
||||||
const icons = Array.from(type)
|
const icons = Array.from(type)
|
||||||
.map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon)
|
.map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,10 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasDescription() {
|
||||||
|
return Boolean(this.description);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a Map containing each Action step based on fields define in schema. Ordered by Fields order property.
|
* Create a Map containing each Action step based on fields define in schema. Ordered by Fields order property.
|
||||||
*
|
*
|
||||||
|
|
@ -144,8 +148,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
return this.item instanceof DhpActor
|
return this.item instanceof DhpActor
|
||||||
? this.item
|
? this.item
|
||||||
: this.item?.parent instanceof DhpActor
|
: this.item?.parent instanceof DhpActor
|
||||||
? this.item.parent
|
? this.item.parent
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -223,12 +227,13 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
async use(event, configOptions = {}) {
|
async use(event, configOptions = {}) {
|
||||||
if (!this.actor) throw new Error("An Action can't be used outside of an Actor context.");
|
if (!this.actor) throw new Error('An Action can\'t be used outside of an Actor context.');
|
||||||
|
|
||||||
let config = this.prepareConfig(event, configOptions);
|
let config = this.prepareConfig(event, configOptions);
|
||||||
if (!config) return;
|
if (!config) return;
|
||||||
|
|
||||||
config.effects = await game.system.api.data.actions.actionsTypes.base.getEffects(this.actor, this.item);
|
config.effects =
|
||||||
|
await game.system.api.data.actions.actionsTypes.base.getActionRelevantEffects(this.actor, this.item);
|
||||||
|
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.preUseAction`, this, config) === false) return;
|
if (Hooks.call(`${CONFIG.DH.id}.preUseAction`, this, config) === false) return;
|
||||||
|
|
||||||
|
|
@ -300,17 +305,17 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
|
|
||||||
const groupAttackTokens = this.damage.groupAttack
|
const groupAttackTokens = this.damage.groupAttack
|
||||||
? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(
|
? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(
|
||||||
this.actor.id,
|
this.actor.id,
|
||||||
this.damage.groupAttack
|
this.damage.groupAttack
|
||||||
)
|
)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
config.damageOptions = {
|
config.damageOptions = {
|
||||||
groupAttack: this.damage.groupAttack
|
groupAttack: this.damage.groupAttack
|
||||||
? {
|
? {
|
||||||
numAttackers: Math.max(groupAttackTokens.length, 1),
|
numAttackers: Math.max(groupAttackTokens.length, 1),
|
||||||
range: this.damage.groupAttack
|
range: this.damage.groupAttack
|
||||||
}
|
}
|
||||||
: null
|
: null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -333,27 +338,45 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the all potentially applicable effects on the actor
|
* Get the all potentially applicable effects on the actor for the action's RollDialog
|
||||||
* @param {DHActor} actor The actor performing the action
|
* @param {DHActor} actor The actor performing the action
|
||||||
* @param {DHItem|DhActor} effectParent The parent of the effect
|
* @param {DHItem|DhActor} effectParent The parent of the effect
|
||||||
* @returns {DhActiveEffect[]}
|
* @returns {DhActiveEffect[]}
|
||||||
*/
|
*/
|
||||||
static async getEffects(actor, effectParent) {
|
static async getActionRelevantEffects(actor, effectParent) {
|
||||||
if (!actor) return [];
|
if (!actor) return [];
|
||||||
|
|
||||||
return Array.from(await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true })).filter(
|
// Changes on weapon effects are not typically only applicable to show in the roll dialog for the weapon itself
|
||||||
effect => {
|
// The exemptions to this rule are listed below
|
||||||
/* Effects on weapons only ever apply for the weapon itself */
|
const weaponTransferredEffectKeys = [
|
||||||
if (effect.parent.type === 'weapon') {
|
'system.bonuses.roll.spellcast.bonus'
|
||||||
/* Unless they're secondary - then they apply only to other primary weapons */
|
];
|
||||||
if (effect.parent.system.secondary) {
|
|
||||||
if (effectParent?.type !== 'weapon' || effectParent?.system.secondary) return false;
|
|
||||||
} else if (effectParent?.id !== effect.parent.id) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !effect.isSuppressed;
|
const results = [];
|
||||||
|
const applicableEffects = await actor.allApplicableEffects({ noTransferArmor: true, noSelfArmor: true });
|
||||||
|
for (const effect of [...applicableEffects].filter(e => !e.isSuppressed)) {
|
||||||
|
if (effect.parent.type === 'weapon') {
|
||||||
|
// Effects on weapons only ever apply for the weapon itself (with a few exceptions)
|
||||||
|
const restricted =
|
||||||
|
effect.parent.system.secondary
|
||||||
|
// Secondary applies only to other primary weapons
|
||||||
|
? effectParent?.type !== 'weapon' || effectParent?.system.secondary
|
||||||
|
// Primary only applies to itself
|
||||||
|
: effectParent?.id !== effect.parent.id;
|
||||||
|
if (restricted) {
|
||||||
|
const sourceChanges = effect._source.system.changes;
|
||||||
|
const changes = sourceChanges.filter(x => weaponTransferredEffectKeys.includes(x.key));
|
||||||
|
if (changes.length) {
|
||||||
|
results.push(effect.clone({ 'system.changes': changes }));
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
results.push(effect);
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -428,7 +451,15 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
|
|
||||||
static migrateData(source) {
|
static migrateData(source) {
|
||||||
if (source.damage?.parts && Array.isArray(source.damage.parts)) {
|
if (source.damage?.parts && Array.isArray(source.damage.parts)) {
|
||||||
|
let hitPointsExists = source.damage.parts.some(x => x.applyTo === 'hitPoints');
|
||||||
source.damage.parts = source.damage.parts.reduce((acc, part) => {
|
source.damage.parts = source.damage.parts.reduce((acc, part) => {
|
||||||
|
if (!part.applyTo && hitPointsExists) return acc;
|
||||||
|
|
||||||
|
if (!part.applyTo) {
|
||||||
|
hitPointsExists = true;
|
||||||
|
part.applyTo = 'hitPoints';
|
||||||
|
}
|
||||||
|
|
||||||
acc[part.applyTo] = part;
|
acc[part.applyTo] = part;
|
||||||
return acc;
|
return acc;
|
||||||
}, {});
|
}, {});
|
||||||
|
|
@ -459,8 +490,7 @@ export class ResourceUpdateMap extends Map {
|
||||||
} else if (!existing?.clear) {
|
} else if (!existing?.clear) {
|
||||||
this.set(resource.key, {
|
this.set(resource.key, {
|
||||||
...existing,
|
...existing,
|
||||||
value: existing.value + (resource.value ?? 0),
|
value: existing.value + (resource.value ?? 0)
|
||||||
total: existing.total + (resource.total ?? 0)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,13 +90,13 @@ export default class BeastformEffect extends BaseEffect {
|
||||||
...baseUpdate,
|
...baseUpdate,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
'texture': {
|
texture: {
|
||||||
enabled: this.characterTokenData.usesDynamicToken,
|
enabled: this.characterTokenData.usesDynamicToken,
|
||||||
src: token.flags.daggerheart?.beastformTokenImg ?? this.characterTokenData.tokenImg,
|
src: token.flags.daggerheart?.beastformTokenImg ?? this.characterTokenData.tokenImg,
|
||||||
scaleX: this.characterTokenData.tokenSize.scale,
|
scaleX: this.characterTokenData.tokenSize.scale,
|
||||||
scaleY: this.characterTokenData.tokenSize.scale
|
scaleY: this.characterTokenData.tokenSize.scale
|
||||||
},
|
},
|
||||||
'ring': {
|
ring: {
|
||||||
subject: {
|
subject: {
|
||||||
texture:
|
texture:
|
||||||
token.flags.daggerheart?.beastformSubjectTexture ?? this.characterTokenData.tokenRingImg
|
token.flags.daggerheart?.beastformSubjectTexture ?? this.characterTokenData.tokenRingImg
|
||||||
|
|
|
||||||
|
|
@ -166,10 +166,10 @@ export default class ArmorChange extends foundry.abstract.DataModel {
|
||||||
value:
|
value:
|
||||||
change.type === 'armor'
|
change.type === 'armor'
|
||||||
? {
|
? {
|
||||||
...change.value,
|
...change.value,
|
||||||
current: Math.min(change.value.current, newMax),
|
current: Math.min(change.value.current, newMax),
|
||||||
max: newMax
|
max: newMax
|
||||||
}
|
}
|
||||||
: change.value
|
: change.value
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
|
||||||
14
module/data/actor/_types.d.ts
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import DhpActor from '../../documents/actor.mjs'
|
||||||
|
import DhCharacter from './character.mjs';
|
||||||
|
|
||||||
|
declare module './base.mjs' {
|
||||||
|
export default interface BaseDataActor {
|
||||||
|
parent: DhpActor<this>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
declare module './companion.mjs' {
|
||||||
|
export default interface DhCompanion {
|
||||||
|
partner: DhpActor<DhCharacter>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -87,6 +87,7 @@ export default class DhpAdversary extends DhCreature {
|
||||||
parts: {
|
parts: {
|
||||||
hitPoints: {
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
|
applyTo: 'hitPoints',
|
||||||
value: {
|
value: {
|
||||||
multiplier: 'flat'
|
multiplier: 'flat'
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
|
||||||
import DHItem from '../../documents/item.mjs';
|
|
||||||
import { createShallowProxy, getScrollTextData } from '../../helpers/utils.mjs';
|
import { createShallowProxy, getScrollTextData } from '../../helpers/utils.mjs';
|
||||||
|
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @import DHItem from '../../documents/item.mjs';
|
||||||
|
* @import DHBaseActorSettings from '../../applications/sheets/api/actor-setting.mjs';
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Function to generate resistance fields for damage types */
|
||||||
const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) =>
|
const resistanceField = (resistanceLabel, immunityLabel, reductionLabel) =>
|
||||||
new fields.SchemaField({
|
new fields.SchemaField({
|
||||||
resistance: new fields.BooleanField({
|
resistance: new fields.BooleanField({
|
||||||
|
|
@ -96,6 +100,8 @@ export const commonActorRules = (extendedData = { damageReduction: {}, attack: {
|
||||||
* @property {Boolean} isNPC - This data model represents a NPC?
|
* @property {Boolean} isNPC - This data model represents a NPC?
|
||||||
* @property {typeof DHBaseActorSettings} settingSheet - The sheet class used to render the settings UI for this actor type.
|
* @property {typeof DHBaseActorSettings} settingSheet - The sheet class used to render the settings UI for this actor type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** Base actor type data model for all actors in Daggerheart */
|
||||||
export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
export default class BaseDataActor extends foundry.abstract.TypeDataModel {
|
||||||
/** @returns {ActorDataModelMetadata}*/
|
/** @returns {ActorDataModelMetadata}*/
|
||||||
static get metadata() {
|
static get metadata() {
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,18 @@ export default class DhCharacter extends DhCreature {
|
||||||
core: new fields.BooleanField({ initial: false })
|
core: new fields.BooleanField({ initial: false })
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
gold: new GoldField(),
|
gold: new GoldField({
|
||||||
|
initial: () => {
|
||||||
|
const homebrew = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew);
|
||||||
|
const { coins, handfuls, bags, chests } = homebrew.currency;
|
||||||
|
return {
|
||||||
|
coins: coins.enabled ? coins.initialAmount : 0,
|
||||||
|
handfuls: handfuls.enabled ? handfuls.initialAmount : 0,
|
||||||
|
bags: bags.enabled ? bags.initialAmount : 0,
|
||||||
|
chests: chests.enabled ? chests.initialAmount : 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}),
|
||||||
scars: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.scars' }),
|
scars: new fields.NumberField({ initial: 0, integer: true, label: 'DAGGERHEART.GENERAL.scars' }),
|
||||||
biography: new fields.SchemaField({
|
biography: new fields.SchemaField({
|
||||||
background: new fields.HTMLField(),
|
background: new fields.HTMLField(),
|
||||||
|
|
@ -96,6 +107,7 @@ export default class DhCharacter extends DhCreature {
|
||||||
parts: {
|
parts: {
|
||||||
hitPoints: {
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
|
applyTo: 'hitPoints',
|
||||||
value: {
|
value: {
|
||||||
custom: {
|
custom: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
|
@ -304,7 +316,12 @@ export default class DhCharacter extends DhCreature {
|
||||||
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
label: 'DAGGERHEART.ACTORS.Character.defaultDisadvantageDice'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
}),
|
||||||
|
/** Accumulated armor score from all sources */
|
||||||
|
armorScore: new fields.SchemaField({
|
||||||
|
value: new fields.NumberField(),
|
||||||
|
max: new fields.NumberField()
|
||||||
|
}, { persisted: false })
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -315,8 +332,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
return currentLevel === 1
|
return currentLevel === 1
|
||||||
? 1
|
? 1
|
||||||
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
|
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
|
||||||
tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
|
tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
|
||||||
).tier;
|
).tier;
|
||||||
}
|
}
|
||||||
|
|
||||||
get ancestry() {
|
get ancestry() {
|
||||||
|
|
@ -400,8 +417,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
|
|
||||||
get domainCards() {
|
get domainCards() {
|
||||||
const domainCards = this.parent.items.filter(x => x.type === 'domainCard');
|
const domainCards = this.parent.items.filter(x => x.type === 'domainCard');
|
||||||
const loadout = domainCards.filter(x => !x.system.inVault);
|
const loadout = domainCards.filter(x => !x.system.inVault).sort((a, b) => a.sort - b.sort);
|
||||||
const vault = domainCards.filter(x => x.system.inVault);
|
const vault = domainCards.filter(x => x.system.inVault).sort((a, b) => a.sort - b.sort);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
loadout: loadout,
|
loadout: loadout,
|
||||||
|
|
@ -520,20 +537,20 @@ export default class DhCharacter extends DhCreature {
|
||||||
|
|
||||||
if (armorSource.type === 'armor') {
|
if (armorSource.type === 'armor') {
|
||||||
armorUpdates[armorSource.parent.id].updates.push({
|
armorUpdates[armorSource.parent.id].updates.push({
|
||||||
'_id': armorSource.id,
|
_id: armorSource.id,
|
||||||
'system.armor.current': armorSource.system.armor.current + usedArmorChange
|
'system.armor.current': armorSource.system.armor.current + usedArmorChange
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
effectUpdates[armorSource.parent.id].updates.push({
|
effectUpdates[armorSource.parent.id].updates.push({
|
||||||
'_id': armorSource.id,
|
_id: armorSource.id,
|
||||||
'system.changes': armorSource.system.changes.map(change => ({
|
'system.changes': armorSource.system.changes.map(change => ({
|
||||||
...change,
|
...change,
|
||||||
value:
|
value:
|
||||||
change.type === 'armor'
|
change.type === 'armor'
|
||||||
? {
|
? {
|
||||||
...change.value,
|
...change.value,
|
||||||
current: armorSource.system.armorChange.value.current + usedArmorChange
|
current: armorSource.system.armorChange.value.current + usedArmorChange
|
||||||
}
|
}
|
||||||
: change.value
|
: change.value
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
@ -621,21 +638,21 @@ export default class DhCharacter extends DhCreature {
|
||||||
},
|
},
|
||||||
...(multiclassFeatures.length
|
...(multiclassFeatures.length
|
||||||
? {
|
? {
|
||||||
multiclassFeatures: {
|
multiclassFeatures: {
|
||||||
title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} - ${this.multiclass.value?.name}`,
|
title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} - ${this.multiclass.value?.name}`,
|
||||||
type: 'multiclass',
|
type: 'multiclass',
|
||||||
values: multiclassFeatures
|
values: multiclassFeatures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
...(multiclassSubclassFeatures.length
|
...(multiclassSubclassFeatures.length
|
||||||
? {
|
? {
|
||||||
multiclassSubclassFeatures: {
|
multiclassSubclassFeatures: {
|
||||||
title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} ${game.i18n.localize('TYPES.Item.subclass')} - ${this.multiclass.subclass?.name}`,
|
title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} ${game.i18n.localize('TYPES.Item.subclass')} - ${this.multiclass.subclass?.name}`,
|
||||||
type: 'multiclassSubclass',
|
type: 'multiclassSubclass',
|
||||||
values: multiclassSubclassFeatures
|
values: multiclassSubclassFeatures
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
companionFeatures: {
|
companionFeatures: {
|
||||||
title: game.i18n.localize('DAGGERHEART.ACTORS.Character.companionFeatures'),
|
title: game.i18n.localize('DAGGERHEART.ACTORS.Character.companionFeatures'),
|
||||||
|
|
@ -659,8 +676,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
(this.primaryWeapon && this.secondaryWeapon)
|
(this.primaryWeapon && this.secondaryWeapon)
|
||||||
? burden.twoHanded.value
|
? burden.twoHanded.value
|
||||||
: this.primaryWeapon || this.secondaryWeapon
|
: this.primaryWeapon || this.secondaryWeapon
|
||||||
? burden.oneHanded.value
|
? burden.oneHanded.value
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get deathMoveViable() {
|
get deathMoveViable() {
|
||||||
|
|
@ -726,8 +743,8 @@ export default class DhCharacter extends DhCreature {
|
||||||
currentLevel === 1
|
currentLevel === 1
|
||||||
? null
|
? null
|
||||||
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
|
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
|
||||||
tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
|
tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
|
||||||
).tier;
|
).tier;
|
||||||
if (game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto) {
|
if (game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto) {
|
||||||
for (let levelKey in this.levelData.levelups) {
|
for (let levelKey in this.levelData.levelups) {
|
||||||
const level = this.levelData.levelups[levelKey];
|
const level = this.levelData.levelups[levelKey];
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,7 @@ export default class DhCompanion extends DhCreature {
|
||||||
parts: {
|
parts: {
|
||||||
hitPoints: {
|
hitPoints: {
|
||||||
type: ['physical'],
|
type: ['physical'],
|
||||||
|
applyTo: 'hitPoints',
|
||||||
value: {
|
value: {
|
||||||
dice: 'd6',
|
dice: 'd6',
|
||||||
multiplier: 'prof'
|
multiplier: 'prof'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
|
import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
|
||||||
import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
|
import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
|
||||||
|
import { parseInlineParams } from '../../enrichers/parser.mjs';
|
||||||
|
|
||||||
export function getTierAdjustedAdversary(source, tier) {
|
export function getTierAdjustedAdversary(source, tier) {
|
||||||
const currentTier = source.tier ?? 1;
|
const currentTier = source.tier ?? 1;
|
||||||
|
|
@ -60,8 +61,8 @@ export function getTierAdjustedAdversary(source, tier) {
|
||||||
const descriptionFormulas = [];
|
const descriptionFormulas = [];
|
||||||
for (const withDescription of [item.system, ...Object.values(item.system.actions)]) {
|
for (const withDescription of [item.system, ...Object.values(item.system.actions)]) {
|
||||||
withDescription.description = withDescription.description.replace(damageRegex, (match, inner) => {
|
withDescription.description = withDescription.description.replace(damageRegex, (match, inner) => {
|
||||||
const { value: formula } = parseInlineParams(inner);
|
const { value: formula } = parseInlineParams(inner, { first: 'value' });
|
||||||
if (!formula || !type) return match;
|
if (!formula) return match;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula;
|
const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula;
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,12 @@ export class DhCompanionLevelup extends foundry.abstract.DataModel {
|
||||||
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
|
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
|
||||||
const experiences = initialAchievements.experience
|
const experiences = initialAchievements.experience
|
||||||
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
|
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
|
||||||
acc[foundry.utils.randomID()] = {
|
acc[foundry.utils.randomID()] = {
|
||||||
name: '',
|
name: '',
|
||||||
modifier: initialAchievements.experience.modifier
|
modifier: initialAchievements.experience.modifier
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
const currentChoices = pcLevelData.levelups[i]?.selections?.length;
|
const currentChoices = pcLevelData.levelups[i]?.selections?.length;
|
||||||
|
|
@ -302,9 +302,9 @@ export class DhLevelupLevel extends foundry.abstract.DataModel {
|
||||||
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
|
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
|
||||||
domainCards: levelData.achievements?.domainCards
|
domainCards: levelData.achievements?.domainCards
|
||||||
? levelData.achievements.domainCards.reduce((acc, card, index) => {
|
? levelData.achievements.domainCards.reduce((acc, card, index) => {
|
||||||
acc[index] = { ...card };
|
acc[index] = { ...card };
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: (achievements.domainCards ?? {}),
|
: (achievements.domainCards ?? {}),
|
||||||
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
|
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,54 @@ export default class DhCountdowns extends foundry.abstract.DataModel {
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleChange() {
|
||||||
|
const previousCountdowns = foundry.ui.countdowns.previousCountdownData;
|
||||||
|
const changedCountdowns = Object.entries(this.countdowns).reduce((acc, [key, countdown]) => {
|
||||||
|
const previousCountdown = previousCountdowns[key];
|
||||||
|
if (!previousCountdown || (previousCountdown.progress.current !== countdown.progress.current)) {
|
||||||
|
acc.push(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
for (const countdownKey of changedCountdowns)
|
||||||
|
foundry.ui.countdowns.changedCountdownsForAnimation.add(countdownKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static migrateData(source) {
|
||||||
|
const migrateOldCountdowns = (data, type) => {
|
||||||
|
for (const key of Object.keys(data.countdowns)) {
|
||||||
|
const countdown = data.countdowns[key];
|
||||||
|
source.countdowns[key] = {
|
||||||
|
...countdown,
|
||||||
|
type: type,
|
||||||
|
ownership: Object.keys(countdown.ownership.players).reduce((acc, key) => {
|
||||||
|
acc[key] =
|
||||||
|
countdown.ownership.players[key].type === 1 ? 2 : countdown.ownership.players[key].type;
|
||||||
|
return acc;
|
||||||
|
}, {}),
|
||||||
|
progress: {
|
||||||
|
...countdown.progress,
|
||||||
|
type: countdown.progress.type.value
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
source[type] = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (source.narrative) {
|
||||||
|
migrateOldCountdowns(source.narrative, 'narrative');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (source.encounter) {
|
||||||
|
migrateOldCountdowns(source.encounter, 'encounter');
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.migrateData(source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DhCountdown extends foundry.abstract.DataModel {
|
export class DhCountdown extends foundry.abstract.DataModel {
|
||||||
|
|
@ -21,7 +69,8 @@ export class DhCountdown extends foundry.abstract.DataModel {
|
||||||
return {
|
return {
|
||||||
type: new fields.StringField({
|
type: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
choices: CONFIG.DH.GENERAL.countdownBaseTypes,
|
choices: CONFIG.DH.GENERAL.countdownTypes,
|
||||||
|
initial: CONFIG.DH.GENERAL.countdownTypes.encounter.id,
|
||||||
label: 'DAGGERHEART.GENERAL.type'
|
label: 'DAGGERHEART.GENERAL.type'
|
||||||
}),
|
}),
|
||||||
name: new fields.StringField({
|
name: new fields.StringField({
|
||||||
|
|
@ -77,15 +126,15 @@ export class DhCountdown extends foundry.abstract.DataModel {
|
||||||
static defaultCountdown(type, playerHidden) {
|
static defaultCountdown(type, playerHidden) {
|
||||||
const ownership = playerHidden
|
const ownership = playerHidden
|
||||||
? game.users.reduce((acc, user) => {
|
? game.users.reduce((acc, user) => {
|
||||||
if (!user.isGM) {
|
if (!user.isGM) {
|
||||||
acc[user.id] = CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE;
|
acc[user.id] = CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE;
|
||||||
}
|
}
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
type: type ?? CONFIG.DH.GENERAL.countdownBaseTypes.narrative.id,
|
type: type ?? CONFIG.DH.GENERAL.countdownTypes.encounter.id,
|
||||||
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Countdown.newCountdown'),
|
name: game.i18n.localize('DAGGERHEART.APPLICATIONS.Countdown.newCountdown'),
|
||||||
img: 'icons/magic/time/hourglass-yellow-green.webp',
|
img: 'icons/magic/time/hourglass-yellow-green.webp',
|
||||||
ownership: ownership,
|
ownership: ownership,
|
||||||
|
|
@ -102,8 +151,8 @@ export class DhCountdown extends foundry.abstract.DataModel {
|
||||||
value: user.isGM
|
value: user.isGM
|
||||||
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||||
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
|
||||||
? this.ownership.players[user.id].type
|
? this.ownership.players[user.id].type
|
||||||
: this.ownership.default,
|
: this.ownership.default,
|
||||||
isGM: user.isGM
|
isGM: user.isGM
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,8 @@ export default class BeastformField extends fields.SchemaField {
|
||||||
baseSize === 'custom'
|
baseSize === 'custom'
|
||||||
? 'custom'
|
? 'custom'
|
||||||
: (Object.keys(CONFIG.DH.ACTOR.tokenSize).find(
|
: (Object.keys(CONFIG.DH.ACTOR.tokenSize).find(
|
||||||
x => CONFIG.DH.ACTOR.tokenSize[x].value === CONFIG.DH.ACTOR.tokenSize[baseSize].value + 1
|
x => CONFIG.DH.ACTOR.tokenSize[x].value === CONFIG.DH.ACTOR.tokenSize[baseSize].value + 1
|
||||||
) ?? baseSize);
|
) ?? baseSize);
|
||||||
formData.system.tokenSize = {
|
formData.system.tokenSize = {
|
||||||
...evolvedData.form.system.tokenSize,
|
...evolvedData.form.system.tokenSize,
|
||||||
size: evolvedSize
|
size: evolvedSize
|
||||||
|
|
|
||||||
|
|
@ -116,8 +116,8 @@ export default class CostField extends fields.ArrayField {
|
||||||
c.key === 'fear'
|
c.key === 'fear'
|
||||||
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear)
|
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear)
|
||||||
: resources[c.key].isReversed
|
: resources[c.key].isReversed
|
||||||
? resources[c.key].max - resources[c.key].value
|
? resources[c.key].max - resources[c.key].value
|
||||||
: resources[c.key].value;
|
: resources[c.key].value;
|
||||||
if (c.scalable) c.maxStep = Math.floor((c.max - c.value) / c.step);
|
if (c.scalable) c.maxStep = Math.floor((c.max - c.value) / c.step);
|
||||||
return c;
|
return c;
|
||||||
});
|
});
|
||||||
|
|
@ -149,8 +149,8 @@ export default class CostField extends fields.ArrayField {
|
||||||
!resources[c.key]
|
!resources[c.key]
|
||||||
? a
|
? a
|
||||||
: a && resources[c.key].isReversed
|
: a && resources[c.key].isReversed
|
||||||
? resources[c.key].value + (c.total ?? c.value) <= resources[c.key].max
|
? resources[c.key].value + (c.total ?? c.value) <= resources[c.key].max
|
||||||
: resources[c.key]?.value >= (c.total ?? c.value),
|
: resources[c.key]?.value >= (c.total ?? c.value),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ export default class CountdownField extends fields.ArrayField {
|
||||||
...game.system.api.data.countdowns.DhCountdown.defineSchema(),
|
...game.system.api.data.countdowns.DhCountdown.defineSchema(),
|
||||||
type: new fields.StringField({
|
type: new fields.StringField({
|
||||||
required: true,
|
required: true,
|
||||||
choices: CONFIG.DH.GENERAL.countdownBaseTypes,
|
choices: CONFIG.DH.GENERAL.countdownTypes,
|
||||||
initial: CONFIG.DH.GENERAL.countdownBaseTypes.encounter.id,
|
initial: CONFIG.DH.GENERAL.countdownTypes.encounter.id,
|
||||||
label: 'DAGGERHEART.GENERAL.type'
|
label: 'DAGGERHEART.GENERAL.type'
|
||||||
}),
|
}),
|
||||||
name: new fields.StringField({
|
name: new fields.StringField({
|
||||||
|
|
@ -87,11 +87,11 @@ export default class CountdownField extends fields.ArrayField {
|
||||||
CONFIG.DH.id,
|
CONFIG.DH.id,
|
||||||
CONFIG.DH.SETTINGS.gameSettings.Countdowns,
|
CONFIG.DH.SETTINGS.gameSettings.Countdowns,
|
||||||
countdownSetting.toObject()
|
countdownSetting.toObject()
|
||||||
),
|
);
|
||||||
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
game.socket.emit(`system.${CONFIG.DH.id}`, {
|
||||||
action: socketEvent.Refresh,
|
action: socketEvent.Refresh,
|
||||||
data: { refreshType: RefreshType.Countdown }
|
data: { refreshType: RefreshType.Countdown }
|
||||||
});
|
});
|
||||||
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
|
||||||
},
|
},
|
||||||
data,
|
data,
|
||||||
|
|
|
||||||
|
|
@ -61,11 +61,11 @@ export default class EffectsField extends fields.ArrayField {
|
||||||
token: messageToken,
|
token: messageToken,
|
||||||
conditionImmunities: Object.values(conditionImmunities).some(x => x)
|
conditionImmunities: Object.values(conditionImmunities).some(x => x)
|
||||||
? game.i18n.format('DAGGERHEART.UI.Chat.effectSummary.immunityTo', {
|
? game.i18n.format('DAGGERHEART.UI.Chat.effectSummary.immunityTo', {
|
||||||
immunities: Object.keys(conditionImmunities)
|
immunities: Object.keys(conditionImmunities)
|
||||||
.filter(x => conditionImmunities[x])
|
.filter(x => conditionImmunities[x])
|
||||||
.map(x => game.i18n.localize(conditions[x].name))
|
.map(x => game.i18n.localize(conditions[x].name))
|
||||||
.join(', ')
|
.join(', ')
|
||||||
})
|
})
|
||||||
: null
|
: null
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,11 @@ export default class SaveField extends fields.SchemaField {
|
||||||
game.user === actor.owner
|
game.user === actor.owner
|
||||||
? SaveField.rollSave.call(this, actor, event)
|
? SaveField.rollSave.call(this, actor, event)
|
||||||
: actor.owner.query('reactionRoll', {
|
: actor.owner.query('reactionRoll', {
|
||||||
actionId: this.uuid,
|
actionId: this.uuid,
|
||||||
actorId: actor.uuid,
|
actorId: actor.uuid,
|
||||||
event,
|
event,
|
||||||
message
|
message
|
||||||
});
|
});
|
||||||
const result = await rollSave;
|
const result = await rollSave;
|
||||||
await SaveField.updateSaveMessage.call(this, result, message, target.id);
|
await SaveField.updateSaveMessage.call(this, result, message, target.id);
|
||||||
subResolve();
|
subResolve();
|
||||||
|
|
@ -97,8 +97,8 @@ export default class SaveField extends fields.SchemaField {
|
||||||
const title = actor.isNPC
|
const title = actor.isNPC
|
||||||
? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
|
? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
|
||||||
: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
|
||||||
ability: game.i18n.localize(abilities[this.save.trait]?.label)
|
ability: game.i18n.localize(abilities[this.save.trait]?.label)
|
||||||
}),
|
}),
|
||||||
rollConfig = {
|
rollConfig = {
|
||||||
event,
|
event,
|
||||||
title,
|
title,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { itemAbleRollParse, triggerChatRollFx } from '../../../helpers/utils.mjs';
|
import { getWorldActor, itemAbleRollParse, triggerChatRollFx } from '../../../helpers/utils.mjs';
|
||||||
import FormulaField from '../formulaField.mjs';
|
import FormulaField from '../formulaField.mjs';
|
||||||
|
|
||||||
const fields = foundry.data.fields;
|
const fields = foundry.data.fields;
|
||||||
|
|
@ -42,7 +42,7 @@ export default class DHSummonField extends fields.ArrayField {
|
||||||
const count = roll.total;
|
const count = roll.total;
|
||||||
if (!roll.isDeterministic) rolls.push(roll);
|
if (!roll.isDeterministic) rolls.push(roll);
|
||||||
|
|
||||||
const actor = await DHSummonField.getWorldActor(await foundry.utils.fromUuid(summon.actorUUID));
|
const actor = await getWorldActor(await foundry.utils.fromUuid(summon.actorUUID));
|
||||||
/* Extending summon data in memory so it's available in actionField.toChat. Think it's harmless, but ugly. Could maybe find a better way. */
|
/* Extending summon data in memory so it's available in actionField.toChat. Think it's harmless, but ugly. Could maybe find a better way. */
|
||||||
summon.actor = actor.toObject();
|
summon.actor = actor.toObject();
|
||||||
|
|
||||||
|
|
@ -62,19 +62,6 @@ export default class DHSummonField extends fields.ArrayField {
|
||||||
DHSummonField.handleSummon(summonData, this.actor);
|
DHSummonField.handleSummon(summonData, this.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check for any available instances of the actor present in the world if we're missing artwork in the compendium. If none exists, create one. */
|
|
||||||
static async getWorldActor(baseActor) {
|
|
||||||
const dataType = game.system.api.data.actors[`Dh${baseActor.type.capitalize()}`];
|
|
||||||
if (baseActor.inCompendium && dataType && baseActor.img === dataType.DEFAULT_ICON) {
|
|
||||||
const worldActorCopy = game.actors.find(x => x.name === baseActor.name);
|
|
||||||
if (worldActorCopy) return worldActorCopy;
|
|
||||||
|
|
||||||
return await game.system.api.documents.DhpActor.create(baseActor.toObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
return baseActor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async handleSummon(summonData, actionActor) {
|
static async handleSummon(summonData, actionActor) {
|
||||||
await CONFIG.ux.TokenManager.createTokensWithPreview(summonData, { elevation: actionActor.token?.elevation });
|
await CONFIG.ux.TokenManager.createTokensWithPreview(summonData, { elevation: actionActor.token?.elevation });
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,13 +116,16 @@ class ResourcesField extends fields.TypedObjectField {
|
||||||
}
|
}
|
||||||
|
|
||||||
class GoldField extends fields.SchemaField {
|
class GoldField extends fields.SchemaField {
|
||||||
constructor() {
|
constructor(options = {}) {
|
||||||
super({
|
super(
|
||||||
coins: new fields.NumberField({ initial: 0, integer: true }),
|
{
|
||||||
handfuls: new fields.NumberField({ initial: 1, integer: true }),
|
coins: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
bags: new fields.NumberField({ initial: 0, integer: true }),
|
handfuls: new fields.NumberField({ initial: 1, integer: true }),
|
||||||
chests: new fields.NumberField({ initial: 0, integer: true })
|
bags: new fields.NumberField({ initial: 0, integer: true }),
|
||||||
});
|
chests: new fields.NumberField({ initial: 0, integer: true })
|
||||||
|
},
|
||||||
|
options
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ export default class FormulaField extends foundry.data.fields.StringField {
|
||||||
let roll = null;
|
let roll = null;
|
||||||
try {
|
try {
|
||||||
roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, '1'));
|
roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, '1'));
|
||||||
} catch (_) {
|
} catch {
|
||||||
roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, 'd6'));
|
roll = new Roll(value.replace(/@([a-z.0-9_-]+)/gi, 'd6'));
|
||||||
}
|
}
|
||||||
roll.evaluateSync({ strict: false });
|
roll.evaluateSync({ strict: false });
|
||||||
|
|
|
||||||
8
module/data/item/_types.d.ts
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import DHItem from '../../documents/item.mjs';
|
||||||
|
|
||||||
|
declare module './base.mjs' {
|
||||||
|
export default interface BaseDataItem {
|
||||||
|
parent: DHItem<this>;
|
||||||
|
actor: DhpActor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import BaseDataItem from './base.mjs';
|
import BaseDataItem from './base.mjs';
|
||||||
import ItemLinkFields from '../../data/fields/itemLinkFields.mjs';
|
import ItemLinkFields from '../../data/fields/itemLinkFields.mjs';
|
||||||
import { getFeaturesHTMLData } from '../../helpers/utils.mjs';
|
import { fromUuids, getFeaturesHTMLData } from '../../helpers/utils.mjs';
|
||||||
|
|
||||||
export default class DHAncestry extends BaseDataItem {
|
export default class DHAncestry extends BaseDataItem {
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
@ -45,6 +45,10 @@ export default class DHAncestry extends BaseDataItem {
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
|
// Preload all ancestry features for acquisition from the cache
|
||||||
|
// todo: make feature acquisition async and replace feature helpers for methods
|
||||||
|
await fromUuids(this._source.features.map(f => f.item));
|
||||||
|
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
const features = await getFeaturesHTMLData(this.features);
|
const features = await getFeaturesHTMLData(this.features);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,10 @@ export default class DHArmor extends AttachableItem {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get itemFeatures() {
|
||||||
|
return this.armorFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
@ -169,8 +173,4 @@ export default class DHArmor extends AttachableItem {
|
||||||
const labels = [`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armor.max}`];
|
const labels = [`${game.i18n.localize('DAGGERHEART.ITEMS.Armor.baseScore')}: ${this.armor.max}`];
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
get itemFeatures() {
|
|
||||||
return this.armorFeatures;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,8 @@ export default class DHBeastform extends BaseDataItem {
|
||||||
const autoTokenSize =
|
const autoTokenSize =
|
||||||
this.tokenSize.size !== 'custom'
|
this.tokenSize.size !== 'custom'
|
||||||
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes[
|
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes[
|
||||||
this.tokenSize.size
|
this.tokenSize.size
|
||||||
]
|
]
|
||||||
: null;
|
: null;
|
||||||
const width = autoTokenSize ?? this.tokenSize.width;
|
const width = autoTokenSize ?? this.tokenSize.width;
|
||||||
const height = autoTokenSize ?? this.tokenSize.height;
|
const height = autoTokenSize ?? this.tokenSize.height;
|
||||||
|
|
|
||||||
|
|
@ -70,14 +70,14 @@ export default class DHClass extends BaseDataItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
async fetchSubclasses() {
|
async fetchSubclasses() {
|
||||||
const uuids = [this.parent.uuid, this.parent._stats?.compendiumSource].filter(u => !!u);
|
const sourceUuid = this.parent.sourceUuid;
|
||||||
const subclasses = game.items.filter(x => x.type === 'subclass' && uuids.includes(x.system.linkedClass));
|
const subclasses = game.items.filter(x => x.type === 'subclass' && x.system.linkedClass === sourceUuid);
|
||||||
for (const pack of game.packs) {
|
for (const pack of game.packs) {
|
||||||
const packIds = [];
|
const packIds = [];
|
||||||
const indexes = await pack.getIndex({ fields: ['system.linkedClass'] });
|
const indexes = await pack.getIndex({ fields: ['system.linkedClass'] });
|
||||||
for (const index of indexes) {
|
for (const index of indexes) {
|
||||||
if (index.type !== 'subclass') continue;
|
if (index.type !== 'subclass') continue;
|
||||||
if (!uuids.includes(index.system?.linkedClass)) continue;
|
if (index.system?.linkedClass !== sourceUuid) continue;
|
||||||
if (subclasses.find(x => x.uuid === index.uuid)) continue;
|
if (subclasses.find(x => x.uuid === index.uuid)) continue;
|
||||||
packIds.push(index._id);
|
packIds.push(index._id);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { getFeaturesHTMLData } from '../../helpers/utils.mjs';
|
import { fromUuids, getFeaturesHTMLData } from '../../helpers/utils.mjs';
|
||||||
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
|
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
|
||||||
import BaseDataItem from './base.mjs';
|
import BaseDataItem from './base.mjs';
|
||||||
|
|
||||||
|
|
@ -27,6 +27,10 @@ export default class DHCommunity extends BaseDataItem {
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
|
// Preload all community features for acquisition from the cache
|
||||||
|
// todo: make feature acquisition async and replace feature helpers for methods
|
||||||
|
await fromUuids(this._source.features);
|
||||||
|
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
const features = await getFeaturesHTMLData(this.features);
|
const features = await getFeaturesHTMLData(this.features);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,9 +70,7 @@ export default class DHSubclass extends BaseDataItem {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const match = [multiclass, actorClass].find(
|
const match = [multiclass, actorClass].find(c => c && c.sourceUuid === this.linkedClass);
|
||||||
c => c && (c._stats.compendiumSource ?? c.uuid) === this.linkedClass
|
|
||||||
);
|
|
||||||
if (!match) {
|
if (!match) {
|
||||||
const key = multiclass ? 'subclassNotInMulticlass' : 'subclassNotInClass';
|
const key = multiclass ? 'subclassNotInMulticlass' : 'subclassNotInClass';
|
||||||
ui.notifications.warn(`DAGGERHEART.UI.Notifications.${key}`, { localize: true });
|
ui.notifications.warn(`DAGGERHEART.UI.Notifications.${key}`, { localize: true });
|
||||||
|
|
@ -91,7 +89,7 @@ export default class DHSubclass extends BaseDataItem {
|
||||||
? game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.spellcastingTrait].label)
|
? game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.spellcastingTrait].label)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
// Preload all class features for acquisition from the cache
|
// Preload all subclass features for acquisition from the cache
|
||||||
// todo: make feature acquisition async and replace feature helpers for methods
|
// todo: make feature acquisition async and replace feature helpers for methods
|
||||||
await fromUuids(this._source.features.map(f => f.item));
|
await fromUuids(this._source.features.map(f => f.item));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,6 +113,10 @@ export default class DHWeapon extends AttachableItem {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get itemFeatures() {
|
||||||
|
return this.weaponFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
@ -269,8 +273,4 @@ export default class DHWeapon extends AttachableItem {
|
||||||
|
|
||||||
return labels;
|
return labels;
|
||||||
}
|
}
|
||||||
|
|
||||||
get itemFeatures() {
|
|
||||||
return this.weaponFeatures;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@ export class DhLevelup extends foundry.abstract.DataModel {
|
||||||
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
|
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
|
||||||
const experiences = initialAchievements.experience
|
const experiences = initialAchievements.experience
|
||||||
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
|
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
|
||||||
acc[foundry.utils.randomID()] = {
|
acc[foundry.utils.randomID()] = {
|
||||||
name: '',
|
name: '',
|
||||||
modifier: initialAchievements.experience.modifier
|
modifier: initialAchievements.experience.modifier
|
||||||
};
|
};
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: {};
|
: {};
|
||||||
|
|
||||||
const domainCards = [...Array(tier.domainCardByLevel).keys()].reduce((acc, _) => {
|
const domainCards = [...Array(tier.domainCardByLevel).keys()].reduce((acc, _) => {
|
||||||
|
|
@ -298,9 +298,9 @@ export class DhLevelupLevel extends foundry.abstract.DataModel {
|
||||||
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
|
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
|
||||||
domainCards: levelData.achievements?.domainCards
|
domainCards: levelData.achievements?.domainCards
|
||||||
? levelData.achievements.domainCards.reduce((acc, card, index) => {
|
? levelData.achievements.domainCards.reduce((acc, card, index) => {
|
||||||
acc[index] = { ...card };
|
acc[index] = { ...card };
|
||||||
return acc;
|
return acc;
|
||||||
}, {})
|
}, {})
|
||||||
: (achievements.domainCards ?? {}),
|
: (achievements.domainCards ?? {}),
|
||||||
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
|
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -149,12 +149,15 @@ export default class RegisteredTriggers extends Map {
|
||||||
|
|
||||||
const result = await command(...args);
|
const result = await command(...args);
|
||||||
if (result?.updates?.length) updates.push(...result.updates);
|
if (result?.updates?.length) updates.push(...result.updates);
|
||||||
} catch (_) {
|
} catch {
|
||||||
|
const item = await foundry.utils.fromUuid(itemUuid);
|
||||||
const triggerName = game.i18n.localize(triggerData.label);
|
const triggerName = game.i18n.localize(triggerData.label);
|
||||||
ui.notifications.error(
|
console.error(
|
||||||
game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', {
|
game.i18n.format('DAGGERHEART.CONFIG.Triggers.triggerError', {
|
||||||
trigger: triggerName,
|
trigger: triggerName,
|
||||||
actor: currentActor?.name
|
actor: currentActor?.name,
|
||||||
|
item: item?.name ?? '<Missing Item>',
|
||||||
|
itemUuid: item?.uuid ?? '<Missing UUID>'
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { defaultRestOptions } from '../../config/generalConfig.mjs';
|
||||||
import { resetAndRerenderActors } from '../../helpers/utils.mjs';
|
import { resetAndRerenderActors } from '../../helpers/utils.mjs';
|
||||||
import { ActionsField } from '../fields/actionField.mjs';
|
import { ActionsField } from '../fields/actionField.mjs';
|
||||||
|
|
||||||
const currencyField = (initial, label, icon) =>
|
const currencyField = (initial, label, icon, initialAmount = 0) =>
|
||||||
new foundry.data.fields.SchemaField({
|
new foundry.data.fields.SchemaField({
|
||||||
enabled: new foundry.data.fields.BooleanField({ required: true, initial: true }),
|
enabled: new foundry.data.fields.BooleanField({ required: true, initial: true }),
|
||||||
label: new foundry.data.fields.StringField({
|
label: new foundry.data.fields.StringField({
|
||||||
|
|
@ -10,7 +10,14 @@ const currencyField = (initial, label, icon) =>
|
||||||
initial,
|
initial,
|
||||||
label
|
label
|
||||||
}),
|
}),
|
||||||
icon: new foundry.data.fields.StringField({ required: true, nullable: false, blank: true, initial: icon })
|
icon: new foundry.data.fields.StringField({ required: true, nullable: false, blank: true, initial: icon }),
|
||||||
|
initialAmount: new foundry.data.fields.NumberField({
|
||||||
|
required: true,
|
||||||
|
integer: true,
|
||||||
|
min: 0,
|
||||||
|
initial: initialAmount,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Homebrew.currency.initialAmount'
|
||||||
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
const restMoveField = () =>
|
const restMoveField = () =>
|
||||||
|
|
@ -108,7 +115,8 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
||||||
handfuls: currencyField(
|
handfuls: currencyField(
|
||||||
'Handfuls',
|
'Handfuls',
|
||||||
'DAGGERHEART.SETTINGS.Homebrew.currency.handfulName',
|
'DAGGERHEART.SETTINGS.Homebrew.currency.handfulName',
|
||||||
'fa-solid fa-coins'
|
'fa-solid fa-coins',
|
||||||
|
1
|
||||||
),
|
),
|
||||||
bags: currencyField('Bags', 'DAGGERHEART.SETTINGS.Homebrew.currency.bagName', 'fa-solid fa-sack'),
|
bags: currencyField('Bags', 'DAGGERHEART.SETTINGS.Homebrew.currency.bagName', 'fa-solid fa-sack'),
|
||||||
chests: currencyField(
|
chests: currencyField(
|
||||||
|
|
@ -193,6 +201,7 @@ export default class DhHomebrew extends foundry.abstract.DataModel {
|
||||||
for (const type of ['coins', 'handfuls', 'bags', 'chests']) {
|
for (const type of ['coins', 'handfuls', 'bags', 'chests']) {
|
||||||
const initial = this.schema.fields.currency.fields[type].getInitialValue();
|
const initial = this.schema.fields.currency.fields[type].getInitialValue();
|
||||||
source.currency[type] = foundry.utils.mergeObject(initial, source.currency[type], { inplace: false });
|
source.currency[type] = foundry.utils.mergeObject(initial, source.currency[type], { inplace: false });
|
||||||
|
source.currency[type].initialAmount ??= 0;
|
||||||
}
|
}
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,16 +100,19 @@ export default class D20Roll extends DHRoll {
|
||||||
|
|
||||||
this.options.roll.modifiers = this.applyBaseBonus();
|
this.options.roll.modifiers = this.applyBaseBonus();
|
||||||
|
|
||||||
const actorExperiences = this.options.roll.companionRoll
|
let actorExperiences = this.options.data.system?.experiences ?? {};
|
||||||
? (this.options.data?.companion?.system.experiences ?? {})
|
if (this.options.roll.companionRoll) {
|
||||||
: (this.options.data.system?.experiences ?? {});
|
const companion = typeof this.options.data.companion === 'string' ?
|
||||||
this.options.experiences?.forEach(m => {
|
foundry.utils.fromUuidSync(this.options.data.companion) :
|
||||||
if (actorExperiences[m])
|
this.options.data.companion;
|
||||||
this.options.roll.modifiers.push({
|
actorExperiences = companion?.system?.experiences ?? {};
|
||||||
label: actorExperiences[m].name,
|
}
|
||||||
value: actorExperiences[m].value
|
for (const m of this.options.experiences?.filter(m => !!actorExperiences[m]) ?? []) {
|
||||||
});
|
this.options.roll.modifiers.push({
|
||||||
});
|
label: actorExperiences[m].name,
|
||||||
|
value: actorExperiences[m].value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
this.addModifiers();
|
this.addModifiers();
|
||||||
if (this.options.extraFormula) {
|
if (this.options.extraFormula) {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,10 @@ export default class DHRoll extends Roll {
|
||||||
|
|
||||||
static DefaultDialog = D20RollDialog;
|
static DefaultDialog = D20RollDialog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Partial<RollConfig>} config
|
||||||
|
* @returns {Promise<RollConfig>}
|
||||||
|
*/
|
||||||
static async build(config = {}, message = {}) {
|
static async build(config = {}, message = {}) {
|
||||||
const roll = await this.buildConfigure(config, message);
|
const roll = await this.buildConfigure(config, message);
|
||||||
if (!roll) return;
|
if (!roll) return;
|
||||||
|
|
@ -34,9 +38,14 @@ export default class DHRoll extends Roll {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Partial<RollConfig>} config
|
||||||
|
* @returns {Promise<RollConfig>}
|
||||||
|
*/
|
||||||
static async buildConfigure(config = {}, message = {}) {
|
static async buildConfigure(config = {}, message = {}) {
|
||||||
config.hooks = [...this.getHooks(), ''];
|
config.hooks = [...this.getHooks(), ''];
|
||||||
config.dialog ??= {};
|
config.dialog ??= {};
|
||||||
|
config.damageOptions ??= {};
|
||||||
|
|
||||||
for (const hook of config.hooks) {
|
for (const hook of config.hooks) {
|
||||||
if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null;
|
if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null;
|
||||||
|
|
@ -103,9 +112,9 @@ export default class DHRoll extends Roll {
|
||||||
if (action?.chatDisplay) {
|
if (action?.chatDisplay) {
|
||||||
actionDescription = action
|
actionDescription = action
|
||||||
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(action.description, {
|
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(action.description, {
|
||||||
relativeTo: config.data,
|
relativeTo: config.data,
|
||||||
rollData: config.data.getRollData?.() ?? {}
|
rollData: config.data.getRollData?.() ?? {}
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
config.actionChatMessageHandled = true;
|
config.actionChatMessageHandled = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
|
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
|
||||||
import D20Roll from './d20Roll.mjs';
|
import D20Roll from './d20Roll.mjs';
|
||||||
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
|
import { parseRallyDice, setDiceSoNiceForDualityRoll, shouldUseHopeFearAutomation } from '../helpers/utils.mjs';
|
||||||
import { getDiceSoNicePresets } from '../config/generalConfig.mjs';
|
import { getDiceSoNicePresets } from '../config/generalConfig.mjs';
|
||||||
import { updateResourcesForDualityReroll } from './helpers.mjs';
|
import { updateResourcesForDualityReroll } from './helpers.mjs';
|
||||||
|
|
||||||
|
|
@ -109,10 +109,10 @@ export default class DualityRoll extends D20Roll {
|
||||||
const label = this.guaranteedCritical
|
const label = this.guaranteedCritical
|
||||||
? 'DAGGERHEART.GENERAL.guaranteedCriticalSuccess'
|
? 'DAGGERHEART.GENERAL.guaranteedCriticalSuccess'
|
||||||
: this.isCritical
|
: this.isCritical
|
||||||
? 'DAGGERHEART.GENERAL.criticalSuccess'
|
? 'DAGGERHEART.GENERAL.criticalSuccess'
|
||||||
: this.withHope
|
: this.withHope
|
||||||
? 'DAGGERHEART.GENERAL.hope'
|
? 'DAGGERHEART.GENERAL.hope'
|
||||||
: 'DAGGERHEART.GENERAL.fear';
|
: 'DAGGERHEART.GENERAL.fear';
|
||||||
|
|
||||||
return game.i18n.localize(label);
|
return game.i18n.localize(label);
|
||||||
}
|
}
|
||||||
|
|
@ -147,8 +147,8 @@ export default class DualityRoll extends D20Roll {
|
||||||
const advDieClass = this.hasAdvantage
|
const advDieClass = this.hasAdvantage
|
||||||
? game.system.api.dice.diceTypes.AdvantageDie
|
? game.system.api.dice.diceTypes.AdvantageDie
|
||||||
: this.hasDisadvantage
|
: this.hasDisadvantage
|
||||||
? game.system.api.dice.diceTypes.DisadvantageDie
|
? game.system.api.dice.diceTypes.DisadvantageDie
|
||||||
: null;
|
: null;
|
||||||
if (advDieClass) {
|
if (advDieClass) {
|
||||||
const advDie = new advDieClass({ faces: this.advantageFaces, number: this.advantageNumber });
|
const advDie = new advDieClass({ faces: this.advantageFaces, number: this.advantageNumber });
|
||||||
if (this.terms.length < 4) {
|
if (this.terms.length < 4) {
|
||||||
|
|
@ -312,11 +312,9 @@ export default class DualityRoll extends D20Roll {
|
||||||
}
|
}
|
||||||
|
|
||||||
static async addDualityResourceUpdates(config) {
|
static async addDualityResourceUpdates(config) {
|
||||||
const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
|
|
||||||
const hopeFearAutomation = automationSettings.hopeFear;
|
|
||||||
if (
|
if (
|
||||||
!config.source?.actor ||
|
!config.source?.actor ||
|
||||||
(game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) ||
|
!shouldUseHopeFearAutomation() ||
|
||||||
config.actionType === 'reaction' ||
|
config.actionType === 'reaction' ||
|
||||||
config.skips?.resources
|
config.skips?.resources
|
||||||
)
|
)
|
||||||
|
|
@ -334,15 +332,15 @@ export default class DualityRoll extends D20Roll {
|
||||||
const fear =
|
const fear =
|
||||||
(config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0);
|
(config.roll.result.duality === -1 ? 1 : 0) - (config.rerolledRoll.result.duality === -1 ? 1 : 0);
|
||||||
|
|
||||||
if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
|
if (hope !== 0) updates.push({ key: 'hope', value: hope, enabled: true });
|
||||||
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
|
if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, enabled: true });
|
||||||
if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
|
if (fear !== 0) updates.push({ key: 'fear', value: fear, enabled: true });
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (config.roll.isCritical || config.roll.result.duality === 1)
|
if (config.roll.isCritical || config.roll.result.duality === 1)
|
||||||
updates.push({ key: 'hope', value: 1, total: -1, enabled: true });
|
updates.push({ key: 'hope', value: 1, enabled: true });
|
||||||
if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, total: 1, enabled: true });
|
if (config.roll.isCritical) updates.push({ key: 'stress', value: -1, enabled: true });
|
||||||
if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, total: -1, enabled: true });
|
if (config.roll.result.duality === -1) updates.push({ key: 'fear', value: 1, enabled: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updates.length) {
|
if (updates.length) {
|
||||||
|
|
|
||||||