diff --git a/CHANGELOG.md b/CHANGELOG.md index ec21bff..e3e5a32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ ## In development +## 1.1.0 + +- Add contextual menu to actor to PDF Export Characters sheet + ## 1.0.0 ### New features diff --git a/README.md b/README.md index 0464ab2..5578340 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,8 @@ A print buton is added on top of sheet to export as pdf ![Print button](media/actor-sheet-print-button.png) +A Contextual menu is added on Actor menu + +![Actor button](media/actor-sheet-print-actor-button.png) + ## Comming soon - -## Module link - -https://raw.githubusercontent.com/mcailleaux/WFRP4-FoundryVTT-wfrp4e-actor-sheet-print/dist/module.json - -## Module Beta link - -https://raw.githubusercontent.com/mcailleaux/WFRP4-FoundryVTT-wfrp4e-actor-sheet-print/dist-beta/module-beta.json diff --git a/lang/en.json b/lang/en.json index 0967ef4..2b4e6f2 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1 +1,3 @@ -{} +{ + "WFRP4SHEETPRINT.export.pdf": "Export to PDF" +} diff --git a/lang/fr.json b/lang/fr.json index 0967ef4..e0df64e 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -1 +1,3 @@ -{} +{ + "WFRP4SHEETPRINT.export.pdf": "Exporter en PDF" +} diff --git a/local-deploy.sh b/local-deploy.sh new file mode 100644 index 0000000..086ca8b --- /dev/null +++ b/local-deploy.sh @@ -0,0 +1,3 @@ +cp -r ./dist/* $LOCAL_FOUNDRY + + diff --git a/media/actor-sheet-print-actor-button.png b/media/actor-sheet-print-actor-button.png new file mode 100755 index 0000000..55d857f Binary files /dev/null and b/media/actor-sheet-print-actor-button.png differ diff --git a/module.json b/module.json index c5634d0..4c82b23 100644 --- a/module.json +++ b/module.json @@ -4,7 +4,7 @@ "description": "Functions to print actor sheet", "version": "${MODULE_VERSION}", "minimumCoreVersion": "0.8.0", - "compatibleCoreVersion": "0.8.9", + "compatibleCoreVersion": "9", "author": "Skeroujvapluvit", "systems": ["wfrp4e"], "dependencies": [], diff --git a/package-lock.json b/package-lock.json index 41a00eb..9857e97 100644 --- a/package-lock.json +++ b/package-lock.json @@ -90,15 +90,15 @@ } }, "@discoveryjs/json-ext": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.5.tgz", - "integrity": "sha512-6nFkfkmSeV/rqSaS4oWHgmpnYw194f6hmWF5is6b0J1naJZoiD0NTc9AiUwPHvWsowkjuHErCZT1wa0jg+BLIA==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz", + "integrity": "sha512-ws57AidsDvREKrZKYffXddNkyaF14iHNHm8VQnZH6t99E8gczjNN0GpvcGny0imC80yQ0tHz1xVUKk/KFQSUyA==", "dev": true }, "@league-of-foundry-developers/foundry-vtt-types": { - "version": "0.8.8-8", - "resolved": "https://registry.npmjs.org/@league-of-foundry-developers/foundry-vtt-types/-/foundry-vtt-types-0.8.8-8.tgz", - "integrity": "sha512-DjWRdl9PHh5CrnqmQBw19Swe/W1asmD5PjU0arMHL1Ni7Zo91o7eHoHqciOAU0M/Nu1BK0CH/Q+nXpNY9dsr3Q==", + "version": "0.8.9-9", + "resolved": "https://registry.npmjs.org/@league-of-foundry-developers/foundry-vtt-types/-/foundry-vtt-types-0.8.9-9.tgz", + "integrity": "sha512-CLpFu5XY6BnxVNou28MKZcvmjWWzv+UYLZ21QL+9OxFegMr5iE15pqyNHcTuJPhmJwnBD2WYUzl+vsAMjUfLLg==", "dev": true, "requires": { "@types/jquery": "~3.5.6", @@ -107,8 +107,7 @@ "pixi-particles": "4.3.1", "pixi.js": "5.3.4", "socket.io-client": "4.1.2", - "tinymce": "5.8.1", - "typescript": "^4.3.5" + "tinymce": "5.8.1" } }, "@pixi/accessibility": { @@ -489,15 +488,15 @@ } }, "@types/component-emitter": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", - "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==", + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==", "dev": true }, "@types/eslint": { - "version": "7.28.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-7.28.1.tgz", - "integrity": "sha512-XhZKznR3i/W5dXqUhgU9fFdJekufbeBd5DALmkuXoeFcjbQcPk+2cL+WLHf6Q81HWAnM2vrslIHpGVyCAviRwg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.2.1.tgz", + "integrity": "sha512-UP9rzNn/XyGwb5RQ2fok+DzcIRIYwc16qTXse5+Smsy8MOIccCChT15KAwnsgQx4PzJkaMq4myFyZ4CL5TjhIQ==", "dev": true, "requires": { "@types/estree": "*", @@ -505,9 +504,9 @@ } }, "@types/eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.2.tgz", + "integrity": "sha512-TzgYCWoPiTeRg6RQYgtuW7iODtVoKu3RVL72k3WohqhjfaOLK5Mg2T4Tg1o2bSfu0vPkoI48wdQFv5b/Xe04wQ==", "dev": true, "requires": { "@types/eslint": "*", @@ -521,9 +520,9 @@ "dev": true }, "@types/jquery": { - "version": "3.5.7", - "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.7.tgz", - "integrity": "sha512-Why+9t1KuqWtIqYKtbk6wgWbE1PjyXJOyGkpmTUh0RX5p4HL7nnRuBkjAO9P2r9tGQP6bLWxl77jRLew3V5xXg==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.11.tgz", + "integrity": "sha512-lYZGdfOtUa0XFjIATQgiogqeTY5PNNMOmp3Jq48ghmJALL8t/IqABRqlEwdHfuUdA8iIE1uGD1HoI4a7Tiy6OA==", "dev": true, "requires": { "@types/sizzle": "*" @@ -542,9 +541,9 @@ "dev": true }, "@types/node": { - "version": "16.10.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.10.4.tgz", - "integrity": "sha512-EITwVTX5B4nDjXjGeQAfXOrm+Jn+qNjDmyDRtWoD+wZsl/RDPRTFRKivs4Mt74iOFlLOrE5+Kf+p5yjyhm3+cA==", + "version": "17.0.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.5.tgz", + "integrity": "sha512-w3mrvNXLeDYV1GKTZorGJQivK6XLCoGwpnyJFbJVK/aTBQUxOCaa/GlFAAN3OTDFcb7h5tiFG+YXCO2By+riZw==", "dev": true }, "@types/parse-json": { @@ -754,9 +753,9 @@ "dev": true }, "acorn": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.5.0.tgz", - "integrity": "sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q==", + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", "dev": true }, "acorn-import-assertions": { @@ -853,15 +852,15 @@ } }, "browserslist": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.17.4.tgz", - "integrity": "sha512-Zg7RpbZpIJRW3am9Lyckue7PLytvVxxhJj1CaJVlCWENsGEAOlnlt8X0ZxGRPp7Bt9o8tIRM5SEXy4BCPMJjLQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.19.1.tgz", + "integrity": "sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001265", - "electron-to-chromium": "^1.3.867", + "caniuse-lite": "^1.0.30001286", + "electron-to-chromium": "^1.4.17", "escalade": "^3.1.1", - "node-releases": "^2.0.0", + "node-releases": "^2.0.1", "picocolors": "^1.0.0" } }, @@ -883,9 +882,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001267", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001267.tgz", - "integrity": "sha512-r1mjTzAuJ9W8cPBGbbus8E0SKcUP7gn03R14Wk8FlAlqhH9hroy9nLqmpuXlfKEw/oILW+FGz47ipXV2O7x8lg==", + "version": "1.0.30001293", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001293.tgz", + "integrity": "sha512-A4I5fB8Kxo0p/H3aXlaOkBp9mD0GspKmXfWHXOzcl0iHLi07EEVJdJeQPT4Yv3/dffRnrwluYZyXvMjbr6WhIA==", "dev": true }, "canvg": { @@ -1030,9 +1029,9 @@ } }, "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", + "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", "dev": true, "requires": { "ms": "2.1.2" @@ -1051,9 +1050,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.3.868", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.868.tgz", - "integrity": "sha512-kZYCHqwJ1ctGrYDlOcWQH+/AftAm/KD4lEnLDNwS0kKwx1x6dU4zv+GuDjsPPOGn/2TjnKBaZjDyjXaoix0q/A==", + "version": "1.4.28", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.28.tgz", + "integrity": "sha512-Gzbf0wUtKfyPaqf0Plz+Ctinf9eQIzxEqBHwSvbGfeOm9GMNdLxyu1dNiCUfM+x6r4BE0xUJNh3Nmg9gfAtTmg==", "dev": true }, "end-of-stream": { @@ -1160,9 +1159,9 @@ }, "dependencies": { "estraverse": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", - "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true } } @@ -1483,9 +1482,9 @@ "dev": true }, "jest-worker": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.2.5.tgz", - "integrity": "sha512-HTjEPZtcNKZ4LnhSp02NEH4vE+5OpJ0EsOWYvGQpHgUMLngydESAAMH5Wd/asPf29+XUDQZszxpLg1BkIIA2aw==", + "version": "27.4.5", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.4.5.tgz", + "integrity": "sha512-f2s8kEdy15cv9r7q4KkzGXvlY0JTcmCbMHZBfSQDwW77REr45IDWwd0lksDFeVHH2jJ5pqb90T77XscrjeGzzg==", "dev": true, "requires": { "@types/node": "*", @@ -1596,18 +1595,18 @@ } }, "mime-db": { - "version": "1.50.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", - "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", "dev": true }, "mime-types": { - "version": "2.1.33", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", - "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "dev": true, "requires": { - "mime-db": "1.50.0" + "mime-db": "1.51.0" } }, "mimic-fn": { @@ -1669,9 +1668,9 @@ "dev": true }, "node-releases": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.0.tgz", - "integrity": "sha512-aA87l0flFYMzCHpTM3DERFSYxc6lv/BltdbRTOMZuxZ0cwZCD3mejE5n9vLhSJCN++/eOqr77G1IO5uXxlQYWA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz", + "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==", "dev": true }, "npm-run-path": { @@ -2172,9 +2171,9 @@ "dev": true }, "source-map-support": { - "version": "0.5.20", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.20.tgz", - "integrity": "sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "requires": { "buffer-from": "^1.0.0", @@ -2215,9 +2214,9 @@ "dev": true }, "terser": { - "version": "5.9.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.9.0.tgz", - "integrity": "sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ==", + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.10.0.tgz", + "integrity": "sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA==", "dev": true, "requires": { "commander": "^2.20.0", @@ -2234,13 +2233,12 @@ } }, "terser-webpack-plugin": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz", - "integrity": "sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.0.tgz", + "integrity": "sha512-LPIisi3Ol4chwAaPP8toUJ3L4qCM1G0wao7L3qNv57Drezxj6+VEyySpPw4B1HSO2Eg/hDY/MNF5XihCAoqnsQ==", "dev": true, "requires": { - "jest-worker": "^27.0.6", - "p-limit": "^3.1.0", + "jest-worker": "^27.4.1", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.0", "source-map": "^0.6.1", @@ -2284,15 +2282,15 @@ } }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz", + "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==", "dev": true }, "uglify-js": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.2.tgz", - "integrity": "sha512-rtPMlmcO4agTUfz10CbgJ1k6UAoXM2gWb3GoMPPZB/+/Ackf8lNWk11K4rYi2D0apgoFRLtQOZhb+/iGNJq26A==", + "version": "3.14.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.5.tgz", + "integrity": "sha512-qZukoSxOG0urUTvjc2ERMTcAy+BiFh3weWAkeurLwjrCba73poHmG3E36XEjd/JGukMzwTL7uCxZiAexj8ppvQ==", "dev": true, "optional": true }, @@ -2340,16 +2338,10 @@ } } }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, "watchpack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.2.0.tgz", - "integrity": "sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.3.1.tgz", + "integrity": "sha512-x0t0JuydIo8qCNctdDrn1OzH/qDzk2+rdCOC3YzumZ42fiMqmQ7T3xQurykYMhYfHaPHTp4ZxAx2NfUo1K6QaA==", "dev": true, "requires": { "glob-to-regexp": "^0.4.1", @@ -2357,9 +2349,9 @@ } }, "webpack": { - "version": "5.58.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.58.2.tgz", - "integrity": "sha512-3S6e9Vo1W2ijk4F4PPWRIu6D/uGgqaPmqw+av3W3jLDujuNkdxX5h5c+RQ6GkjVR+WwIPOfgY8av+j5j4tMqJw==", + "version": "5.65.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.65.0.tgz", + "integrity": "sha512-Q5or2o6EKs7+oKmJo7LaqZaMOlDWQse9Tm5l1WAfU/ujLGN5Pb0SqGeVkN/4bpPmEqEP5RnVhiqsOtWtUVwGRw==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.0", @@ -2384,14 +2376,14 @@ "schema-utils": "^3.1.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.1.3", - "watchpack": "^2.2.0", - "webpack-sources": "^3.2.0" + "watchpack": "^2.3.1", + "webpack-sources": "^3.2.2" } }, "webpack-cli": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.0.tgz", - "integrity": "sha512-n/jZZBMzVEl4PYIBs+auy2WI0WTQ74EnJDiyD98O2JZY6IVIHJNitkYp/uTXOviIOMfgzrNvC9foKv/8o8KSZw==", + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.9.1.tgz", + "integrity": "sha512-JYRFVuyFpzDxMDB+v/nanUdQYcZtqFPGzmlW4s+UkPMFhSpfRNmf1z4AwYcHJVdvEFAM7FFCQdNTpsBYhDLusQ==", "dev": true, "requires": { "@discoveryjs/json-ext": "^0.5.0", @@ -2405,7 +2397,6 @@ "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", - "v8-compile-cache": "^2.2.0", "webpack-merge": "^5.7.3" }, "dependencies": { @@ -2457,9 +2448,9 @@ } }, "webpack-sources": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.1.tgz", - "integrity": "sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA==", + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.2.tgz", + "integrity": "sha512-cp5qdmHnu5T8wRg2G3vZZHoJPN14aqQ89SyQ11NpGH5zEMDCclt49rzo+MaRazk7/UeILhAI+/sEtcM+7Fr0nw==", "dev": true }, "which": { diff --git a/package.json b/package.json index 2787bb4..276ebaf 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,19 @@ "scripts": { "old-build": "tsc -p tsconfig.json && cp -r ./src ./dist", "package": "sh ./package.sh", - "build": "webpack" + "build": "webpack", + "local-deploy": "npm run package && sh ./local-deploy.sh" }, "version": "1.0.4", "devDependencies": { - "@league-of-foundry-developers/foundry-vtt-types": "0.8.8-8", + "@league-of-foundry-developers/foundry-vtt-types": "0.8.9-9", "husky": "4.3.7", "prettier": "2.2.1", "pretty-quick": "3.1.0", - "typescript": "4.3.5", + "typescript": "4.5.4", "ts-loader": "9.2.6", - "webpack": "5.58.2", - "webpack-cli": "4.9.0" + "webpack": "5.65.0", + "webpack-cli": "4.9.1" }, "husky": { "hooks": { diff --git a/package.sh b/package.sh index 859e47f..433b50b 100644 --- a/package.sh +++ b/package.sh @@ -1,6 +1,5 @@ +rm -fr dist npm run build -mkdir -p ./dist/lang -mkdir -p ./dist/styles -cp ./lang/* ./dist/lang/ -cp ./styles/* ./dist/styles/ -cp module.json ./dist/module.json \ No newline at end of file +cp -r $MODULE_DIRS dist/ +export MODULE_VERSION=$(jq ".version" package.json | sed -r 's/["]+//g') +envsubst '${MODULE_VERSION}' < ./module.json > ./dist/module.json diff --git a/src/constants.ts b/src/constants.ts index 304554a..dd738c1 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,8 @@ export const i18n = () => (game).i18n; export const i18nLocalize = (id: string) => i18n().localize(id); export const i18nFormat = (id: string, data?: any) => i18n().format(id, data); +export const user = () => (game).user; +export const isGM = () => user()?.isGM ?? false; export const TEXT_SIZE = 8; export const LABEL_SIZE = 6; diff --git a/src/main.ts b/src/main.ts index 2b05b6e..4b3cddf 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,7 +4,13 @@ import { Row } from './elements/row'; import { Image } from './elements/image'; import { Box } from './elements/box'; import { Util } from './util'; -import { i18nLocalize, LABEL_SIZE, MARGINS, TEXT_SIZE } from './constants'; +import { + i18nLocalize, + isGM, + LABEL_SIZE, + MARGINS, + TEXT_SIZE, +} from './constants'; import { ItemData } from '@league-of-foundry-developers/foundry-vtt-types/src/foundry/common/data/data.mjs'; import { LabelledValues } from './elements/labelled-values'; import { Text } from './elements/text'; @@ -13,633 +19,27 @@ import { Column } from './elements/column'; import { Separator } from './elements/separator'; import { Blank } from './elements/blank'; +Hooks.on('getActorDirectoryEntryContext', async (_, options) => { + options.push({ + name: i18nLocalize('WFRP4SHEETPRINT.export.pdf'), + condition: isGM(), + icon: '', + callback: async (target) => { + const actor: Actor & any = (game).actors.get( + target.attr('data-document-id') + ); + await generatePdf(actor); + }, + }); +}); + Hooks.on( 'renderActorSheetWfrp4eCharacter', async (app: ActorSheet, html: JQuery) => { const actor: Actor & any = app.actor; - const actorData = actor.data; - // @ts-ignore - const actorDetails = actorData.data.details; - const actorStatus = actorData.data.status; - const actorCharacs = actor.characteristics; - const actorImage = actor.img; - let actorImageData: string | null = null; - if (actorImage != null) { - const texture = await loadTexture(actorImage); - actorImageData = ImageHelper.textureToImage(texture); - } - const currentCareer: Item & any = actor.currentCareer; - const careerData: ItemData = currentCareer?.data; - const careerDetail: any = careerData?.data; - addActorSheetActionButton(html, 'print', () => { - const docBuilder = new PdfBuilder({ - orientation: 'p', - unit: 'mm', - }); - const labelledRowHeight = - Util.getHeightFromPx(docBuilder.doc, TEXT_SIZE + LABEL_SIZE) + 1; - - const skills = new LabelledValues( - 0, - 0, - actor.itemCategories.skill - .map((item) => { - return { - label: `${item.name} (${i18nLocalize( - item.characteristic.abrev - )})`, - value: item.data.data.total.value, - }; - }) - .sort((a, b) => a.label.localeCompare(b.label)) - ); - - const talents = new LabelledValues( - 0, - 0, - actor.itemCategories.talent - .map((item) => { - return { - label: - item.data.data.tests.value.length > 0 - ? `${item.name} : ${item.data.data.tests.value}` - : item.name, - value: item.data.data.advances.value, - }; - }) - .sort((a, b) => a.label.localeCompare(b.label)), - 1, - true - ); - - const traits = new Texts( - 0, - 0, - actor.itemCategories.trait - .map((item) => { - return item.name; - }) - .sort((a, b) => a.localeCompare(b)), - 4 - ); - - const weaponsMelee = new Texts( - 0, - 0, - Util.getActorItems(actor, 'weapon') - .filter((w) => w.isMelee) - .map((item) => { - return `${item.name} : ${item.WeaponGroup}, ${item.Reach}, ${ - item.data.data.damage.meleeValue - } (${item.mountDamage}), ${item.OriginalQualities.concat( - item.OriginalFlaws - ).join(', ')}`; - }) - .sort((a, b) => a.localeCompare(b)), - 1, - true - ); - - const weaponsRanged = new Texts( - 0, - 0, - Util.getActorItems(actor, 'weapon') - .filter((w) => w.isRanged) - .map((item) => { - return `${item.name} : ${item.WeaponGroup}, ${ - item.data.data.range.value - } (${item.Range}), ${item.data.data.damage.rangedValue} (${ - item.Damage - }), ${item.OriginalQualities.concat(item.OriginalFlaws).join( - ', ' - )}`; - }) - .sort((a, b) => a.localeCompare(b)), - 1, - true - ); - - const ammunitions = new Texts( - 0, - 0, - Util.getActorItems(actor, 'ammunition') - .map((item) => { - return `${item.data.data.quantity.value} ${item.name} : ${ - item.data.data.range.value.length > 0 - ? item.data.data.range.value - : 'As Weapon' - }, ${ - item.data.data.damage.value.length > 0 - ? item.data.data.damage.value - : '+0' - }, ${item.OriginalQualities.concat(item.OriginalFlaws).join(', ')}`; - }) - .sort((a, b) => a.localeCompare(b)), - 2, - true - ); - - const armourLocation: string[] = []; - const armourLabels: { [key: string]: string[] } = {}; - for (const armour of Util.getActorItems(actor, 'armour')) { - const maxAp = armour.data.data.maxAP; - for (const key of Object.keys(maxAp)) { - if (maxAp[key] > 0) { - if (!armourLocation.includes(key)) { - armourLocation.push(key); - } - if (armourLabels[key] == null) { - armourLabels[key] = []; - } - armourLabels[key].push( - `${armour.name} ${maxAp[key]} ${armour.OriginalQualities.concat( - armour.OriginalFlaws - ).join(' ')}` - ); - } - } - } - - const armours = new Texts( - 0, - 0, - armourLocation.map((al) => { - return `${actorStatus?.armour[al]?.label} : ${armourLabels[al]?.join( - ', ' - )}`; - }), - 1, - true - ); - - const petty = new Texts( - 0, - 0, - actor.itemCategories.spell - .filter((s) => s.lore.value === 'petty') - .map((s) => { - return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}`; - }), - 2, - true - ); - - const spell = new Texts( - 0, - 0, - actor.itemCategories.spell - .filter((s) => s.lore.value !== 'petty') - .map((s) => { - return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}, ${s.ingredientList.length}`; - }), - 2, - true - ); - - const blessing = new Texts( - 0, - 0, - actor.itemCategories.prayer - .filter((s) => s.prayerType.value === 'blessing') - .map((s) => { - return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`; - }), - 2, - true - ); - - const miracle = new Texts( - 0, - 0, - actor.itemCategories.prayer - .filter((s) => s.prayerType.value !== 'blessing') - .map((s) => { - return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`; - }), - 2, - true - ); - - const allMoney = Util.getActorItems(actor, 'money'); - const moneyNames: string[] = []; - const moneyByName: { [name: string]: number } = {}; - for (const money of allMoney) { - if (!moneyNames.includes(money.name)) { - moneyNames.push(money.name); - } - if (moneyByName[money.name] == null) { - moneyByName[money.name] = 0; - } - moneyByName[money.name] = - moneyByName[money.name] + money.quantity.value; - } - - const trappingsHeader = new Texts( - 0, - 0, - [ - `${i18nLocalize('Trappings')} : ${i18nLocalize( - 'Money' - )} : ${moneyNames - .map((m) => { - return `${m} : ${moneyByName[m]}`; - }) - .join(', ')}`, - ], - 1, - true - ); - - const trappings = new Texts( - 0, - 0, - Util.getAllActorItems(actor, ['container', 'trapping']) - .map((t) => { - const location = t.location.value; - let prefix = ''; - if (location != null && location !== 0) { - prefix = `${actor.getEmbeddedDocument('Item', location).name} : `; - } - const qteLabel = t.quantity.value > 1 ? `${t.quantity.value} ` : ''; - return `${prefix}${qteLabel}${t.name}`; - }) - .sort((a, b) => a.localeCompare(b)), - 4, - true - ); - - const critical = new Texts( - 0, - 0, - actor.itemCategories.critical.map((i) => { - return i.name; - }), - 3 - ); - - const disease = new Texts( - 0, - 0, - actor.itemCategories.disease.map((i) => { - return i.name; - }), - 3 - ); - - const injury = new Texts( - 0, - 0, - actor.itemCategories.injury.map((i) => { - return i.name; - }), - 3 - ); - - const mutationP = new Texts( - 0, - 0, - actor.itemCategories.mutation - .filter((i) => i.mutationType.value === 'physical') - .map((i) => { - return i.name; - }), - 3 - ); - - const mutationM = new Texts( - 0, - 0, - actor.itemCategories.mutation - .filter((i) => i.mutationType.value === 'mental') - .map((i) => { - return i.name; - }), - 3 - ); - - const psychology = new Texts( - 0, - 0, - actor.itemCategories.psychology.map((i) => { - return i.name; - }), - 3 - ); - - const imageWidth = 25; - const imageY = labelledRowHeight + MARGINS.top + 2; - const actorImageElement = - actorImageData != null - ? new Image(0, imageY, imageWidth, imageWidth, actorImageData) - : new Box(0, imageY, imageWidth, imageWidth); - - docBuilder.build([ - actorImageElement, - new Column(0, 0, [ - new Row(0, 0, [ - new LabelledText(0, 0, 'Name', `${actor.name}`), - new LabelledText( - 0, - 0, - 'Species', - `${actorDetails?.species?.value}` - ), - new LabelledText(0, 0, 'Gender', `${actorDetails?.gender?.value}`), - ]), - new Row(imageWidth + MARGINS.left + 1, 0, [ - new LabelledText(0, 0, 'Class', `${careerDetail?.class?.value}`), - new LabelledText( - 0, - 0, - 'Career Group', - `${careerDetail?.careergroup?.value}` - ), - new LabelledText(0, 0, 'Career', `${currentCareer?.name}`), - ]), - new Row(imageWidth + MARGINS.left + 1, 0, [ - new LabelledText(0, 0, 'Status', `${actorDetails?.status?.value}`), - new LabelledText(0, 0, 'Age', `${actorDetails?.age?.value}`), - new LabelledText(0, 0, 'Height', `${actorDetails?.height?.value}`), - new LabelledText(0, 0, 'Weight', `${actorDetails?.weight?.value}`), - new LabelledText( - 0, - 0, - 'Hair Colour', - `${actorDetails?.haircolour?.value}` - ), - ]), - new Row(imageWidth + MARGINS.left + 1, 0, [ - new LabelledText( - 0, - 0, - 'Eye Colour', - `${actorDetails?.eyecolour?.value}` - ), - new LabelledText( - 0, - 0, - 'Distinguishing Mark', - `${actorDetails?.distinguishingmark?.value}` - ), - new LabelledText( - 0, - 0, - 'Star Sign', - `${actorDetails?.starsign?.value}` - ), - ]), - Blank.heightBlank(2), - new Row(0, 0, [ - new LabelledText( - 0, - 0, - 'CHARAbbrev.WS', - `${actorCharacs?.ws?.value}` - ), - new LabelledText( - 0, - 0, - 'CHARAbbrev.BS', - `${actorCharacs?.bs?.value}` - ), - new LabelledText(0, 0, 'CHARAbbrev.S', `${actorCharacs?.s?.value}`), - new LabelledText(0, 0, 'CHARAbbrev.T', `${actorCharacs?.t?.value}`), - new LabelledText(0, 0, 'CHARAbbrev.I', `${actorCharacs?.i?.value}`), - new LabelledText( - 0, - 0, - 'CHARAbbrev.Ag', - `${actorCharacs?.ag?.value}` - ), - new LabelledText( - 0, - 0, - 'CHARAbbrev.Dex', - `${actorCharacs?.dex?.value}` - ), - new LabelledText( - 0, - 0, - 'CHARAbbrev.Int', - `${actorCharacs?.int?.value}` - ), - new LabelledText( - 0, - 0, - 'CHARAbbrev.WP', - `${actorCharacs?.wp?.value}` - ), - new LabelledText( - 0, - 0, - 'CHARAbbrev.Fel', - `${actorCharacs?.fel?.value}` - ), - ]), - new Row(0, 0, [ - new LabelledText(0, 0, 'Move', `${actorDetails?.move?.value}`), - new LabelledText(0, 0, 'Walk', `${actorDetails?.move?.walk}`), - new LabelledText(0, 0, 'Run', `${actorDetails?.move?.run}`), - new LabelledText(0, 0, 'Fortune', `${actorStatus?.fortune?.value}`), - new LabelledText(0, 0, 'Fate', `${actorStatus?.fate?.value}`), - new LabelledText(0, 0, 'Resolve', `${actorStatus?.resolve?.value}`), - new LabelledText( - 0, - 0, - 'Resilience', - `${actorStatus?.resilience?.value}` - ), - new LabelledText( - 0, - 0, - 'Wounds', - `${actorStatus?.wounds?.value}/${actorStatus?.wounds?.max}` - ), - ]), - new Separator(0, 0), - new Text(0, 0, 'Skills'), - skills, - new Separator(0, 0), - new Text( - 0, - 0, - `${i18nLocalize('Talents')} : ${i18nLocalize('Tests')}` - ), - talents, - traits.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - traits.elements.length > 0 - ? new Text(0, 0, 'Traits') - : Blank.heightBlank(0), - traits, - weaponsMelee.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - weaponsMelee.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('SHEET.MeleeWeaponHeader')} : ${i18nLocalize( - 'Weapon Group' - )}, ${i18nLocalize('Reach')}, ${i18nLocalize( - 'Damage' - )}, ${i18nLocalize('Qualities')}, ${i18nLocalize('Flaws')}` - ) - : Blank.heightBlank(0), - weaponsMelee, - weaponsRanged.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - weaponsRanged.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('SHEET.RangedWeaponHeader')} : ${i18nLocalize( - 'Weapon Group' - )}, ${i18nLocalize('Range')}, ${i18nLocalize( - 'Damage' - )}, ${i18nLocalize('Qualities')}, ${i18nLocalize('Flaws')}` - ) - : Blank.heightBlank(0), - weaponsRanged, - ammunitions.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - ammunitions.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('Ammunition')} : ${i18nLocalize( - 'Range' - )}, ${i18nLocalize('Damage')}, ${i18nLocalize( - 'Qualities' - )}, ${i18nLocalize('Flaws')}` - ) - : Blank.heightBlank(0), - ammunitions, - armours.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - armours.elements.length > 0 - ? new Text(0, 0, 'Armour') - : Blank.heightBlank(0), - armours, - petty.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - petty.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('SHEET.PettySpell')} : ${i18nLocalize( - 'Casting Number' - )}, ${i18nLocalize('Range')}, ${i18nLocalize( - 'Target' - )}, ${i18nLocalize('Duration')}` - ) - : Blank.heightBlank(0), - petty, - spell.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - spell.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('SHEET.LoreSpell')} : ${i18nLocalize( - 'Casting Number' - )}, ${i18nLocalize('Range')}, ${i18nLocalize( - 'Target' - )}, ${i18nLocalize('Duration')}, ${i18nLocalize( - 'WFRP4E.TrappingType.Ingredients' - )}` - ) - : Blank.heightBlank(0), - spell, - blessing.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - blessing.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('Blessing')} : ${i18nLocalize( - 'Range' - )}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}` - ) - : Blank.heightBlank(0), - blessing, - miracle.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - miracle.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('Miracle')} : ${i18nLocalize( - 'Range' - )}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}` - ) - : Blank.heightBlank(0), - miracle, - new Separator(0, 0), - trappingsHeader, - trappings, - psychology.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - psychology.elements.length > 0 - ? new Text(0, 0, 'Psychology') - : Blank.heightBlank(0), - psychology, - critical.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - critical.elements.length > 0 - ? new Text(0, 0, 'Criticals') - : Blank.heightBlank(0), - critical, - disease.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - disease.elements.length > 0 - ? new Text(0, 0, 'Diseases') - : Blank.heightBlank(0), - disease, - injury.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - injury.elements.length > 0 - ? new Text(0, 0, 'Injuries') - : Blank.heightBlank(0), - injury, - mutationP.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - mutationP.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('Mutations')} (${i18nLocalize('Physical')})` - ) - : Blank.heightBlank(0), - mutationP, - mutationM.elements.length > 0 - ? new Separator(0, 0) - : Blank.heightBlank(0), - mutationM.elements.length > 0 - ? new Text( - 0, - 0, - `${i18nLocalize('Mutations')} (${i18nLocalize('Mental')})` - ) - : Blank.heightBlank(0), - mutationM, - ]), - ]); - docBuilder.doc.save(`${app.actor.name}.pdf`); + addActorSheetActionButton(html, 'print', async () => { + await generatePdf(actor); }); } ); @@ -659,3 +59,555 @@ function addActorSheetActionButton( const title = header.find('.window-title'); title.after(button); } + +async function generatePdf(actor: Actor & any) { + const actorData = actor.data; + // @ts-ignore + const actorDetails = actorData.data.details; + const actorStatus = actorData.data.status; + const actorCharacs = actor.characteristics; + const actorImage = actor.img; + let actorImageData: string | null = null; + if (actorImage != null) { + const texture = await loadTexture(actorImage); + actorImageData = ImageHelper.textureToImage(texture); + } + const currentCareer: Item & any = actor.currentCareer; + const careerData: ItemData = currentCareer?.data; + const careerDetail: any = careerData?.data; + + const docBuilder = new PdfBuilder({ + orientation: 'p', + unit: 'mm', + }); + + const labelledRowHeight = + Util.getHeightFromPx(docBuilder.doc, TEXT_SIZE + LABEL_SIZE) + 1; + + const skills = new LabelledValues( + 0, + 0, + actor.itemCategories.skill + .map((item) => { + return { + label: `${item.name} (${i18nLocalize(item.characteristic.abrev)})`, + value: item.data.data.total.value, + }; + }) + .sort((a, b) => a.label.localeCompare(b.label)) + ); + + const talents = new LabelledValues( + 0, + 0, + actor.itemCategories.talent + .map((item) => { + return { + label: + item.data.data.tests.value.length > 0 + ? `${item.name} : ${item.data.data.tests.value}` + : item.name, + value: item.data.data.advances.value, + }; + }) + .sort((a, b) => a.label.localeCompare(b.label)), + 1, + true + ); + + const traits = new Texts( + 0, + 0, + actor.itemCategories.trait + .map((item) => { + return item.name; + }) + .sort((a, b) => a.localeCompare(b)), + 4 + ); + + const weaponsMelee = new Texts( + 0, + 0, + Util.getActorItems(actor, 'weapon') + .filter((w) => w.isMelee) + .map((item) => { + return `${item.name} : ${item.WeaponGroup}, ${item.Reach}, ${ + item.data.data.damage.meleeValue + } (${item.mountDamage}), ${item.OriginalQualities.concat( + item.OriginalFlaws + ).join(', ')}`; + }) + .sort((a, b) => a.localeCompare(b)), + 1, + true + ); + + const weaponsRanged = new Texts( + 0, + 0, + Util.getActorItems(actor, 'weapon') + .filter((w) => w.isRanged) + .map((item) => { + return `${item.name} : ${item.WeaponGroup}, ${ + item.data.data.range.value + } (${item.Range}), ${item.data.data.damage.rangedValue} (${ + item.Damage + }), ${item.OriginalQualities.concat(item.OriginalFlaws).join(', ')}`; + }) + .sort((a, b) => a.localeCompare(b)), + 1, + true + ); + + const ammunitions = new Texts( + 0, + 0, + Util.getActorItems(actor, 'ammunition') + .map((item) => { + return `${item.data.data.quantity.value} ${item.name} : ${ + item.data.data.range.value.length > 0 + ? item.data.data.range.value + : 'As Weapon' + }, ${ + item.data.data.damage.value.length > 0 + ? item.data.data.damage.value + : '+0' + }, ${item.OriginalQualities.concat(item.OriginalFlaws).join(', ')}`; + }) + .sort((a, b) => a.localeCompare(b)), + 2, + true + ); + + const armourLocation: string[] = []; + const armourLabels: { [key: string]: string[] } = {}; + for (const armour of Util.getActorItems(actor, 'armour')) { + const maxAp = armour.data.data.maxAP; + for (const key of Object.keys(maxAp)) { + if (maxAp[key] > 0) { + if (!armourLocation.includes(key)) { + armourLocation.push(key); + } + if (armourLabels[key] == null) { + armourLabels[key] = []; + } + armourLabels[key].push( + `${armour.name} ${maxAp[key]} ${armour.OriginalQualities.concat( + armour.OriginalFlaws + ).join(' ')}` + ); + } + } + } + + const armours = new Texts( + 0, + 0, + armourLocation.map((al) => { + return `${actorStatus?.armour[al]?.label} : ${armourLabels[al]?.join( + ', ' + )}`; + }), + 1, + true + ); + + const petty = new Texts( + 0, + 0, + actor.itemCategories.spell + .filter((s) => s.lore.value === 'petty') + .map((s) => { + return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}`; + }), + 2, + true + ); + + const spell = new Texts( + 0, + 0, + actor.itemCategories.spell + .filter((s) => s.lore.value !== 'petty') + .map((s) => { + return `${s.name} : ${s.cn.value}, ${s.Range}, ${s.Target}, ${s.Duration}, ${s.ingredientList.length}`; + }), + 2, + true + ); + + const blessing = new Texts( + 0, + 0, + actor.itemCategories.prayer + .filter((s) => s.prayerType.value === 'blessing') + .map((s) => { + return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`; + }), + 2, + true + ); + + const miracle = new Texts( + 0, + 0, + actor.itemCategories.prayer + .filter((s) => s.prayerType.value !== 'blessing') + .map((s) => { + return `${s.name} : ${s.Range}, ${s.Target}, ${s.Duration}`; + }), + 2, + true + ); + + const allMoney = Util.getActorItems(actor, 'money'); + const moneyNames: string[] = []; + const moneyByName: { [name: string]: number } = {}; + for (const money of allMoney) { + if (!moneyNames.includes(money.name)) { + moneyNames.push(money.name); + } + if (moneyByName[money.name] == null) { + moneyByName[money.name] = 0; + } + moneyByName[money.name] = moneyByName[money.name] + money.quantity.value; + } + + const trappingsHeader = new Texts( + 0, + 0, + [ + `${i18nLocalize('Trappings')} : ${i18nLocalize('Money')} : ${moneyNames + .map((m) => { + return `${m} : ${moneyByName[m]}`; + }) + .join(', ')}`, + ], + 1, + true + ); + + const trappings = new Texts( + 0, + 0, + Util.getAllActorItems(actor, ['container', 'trapping']) + .map((t) => { + const location = t.location.value; + let prefix = ''; + if (location != null && location !== 0) { + prefix = `${actor.getEmbeddedDocument('Item', location).name} : `; + } + const qteLabel = t.quantity.value > 1 ? `${t.quantity.value} ` : ''; + return `${prefix}${qteLabel}${t.name}`; + }) + .sort((a, b) => a.localeCompare(b)), + 4, + true + ); + + const critical = new Texts( + 0, + 0, + actor.itemCategories.critical.map((i) => { + return i.name; + }), + 3 + ); + + const disease = new Texts( + 0, + 0, + actor.itemCategories.disease.map((i) => { + return i.name; + }), + 3 + ); + + const injury = new Texts( + 0, + 0, + actor.itemCategories.injury.map((i) => { + return i.name; + }), + 3 + ); + + const mutationP = new Texts( + 0, + 0, + actor.itemCategories.mutation + .filter((i) => i.mutationType.value === 'physical') + .map((i) => { + return i.name; + }), + 3 + ); + + const mutationM = new Texts( + 0, + 0, + actor.itemCategories.mutation + .filter((i) => i.mutationType.value === 'mental') + .map((i) => { + return i.name; + }), + 3 + ); + + const psychology = new Texts( + 0, + 0, + actor.itemCategories.psychology.map((i) => { + return i.name; + }), + 3 + ); + + const imageWidth = 25; + const imageY = labelledRowHeight + MARGINS.top + 2; + const actorImageElement = + actorImageData != null + ? new Image(0, imageY, imageWidth, imageWidth, actorImageData) + : new Box(0, imageY, imageWidth, imageWidth); + + docBuilder.build([ + actorImageElement, + new Column(0, 0, [ + new Row(0, 0, [ + new LabelledText(0, 0, 'Name', `${actor.name}`), + new LabelledText(0, 0, 'Species', `${actorDetails?.species?.value}`), + new LabelledText(0, 0, 'Gender', `${actorDetails?.gender?.value}`), + ]), + new Row(imageWidth + MARGINS.left + 1, 0, [ + new LabelledText(0, 0, 'Class', `${careerDetail?.class?.value}`), + new LabelledText( + 0, + 0, + 'Career Group', + `${careerDetail?.careergroup?.value}` + ), + new LabelledText(0, 0, 'Career', `${currentCareer?.name}`), + ]), + new Row(imageWidth + MARGINS.left + 1, 0, [ + new LabelledText(0, 0, 'Status', `${actorDetails?.status?.value}`), + new LabelledText(0, 0, 'Age', `${actorDetails?.age?.value}`), + new LabelledText(0, 0, 'Height', `${actorDetails?.height?.value}`), + new LabelledText(0, 0, 'Weight', `${actorDetails?.weight?.value}`), + new LabelledText( + 0, + 0, + 'Hair Colour', + `${actorDetails?.haircolour?.value}` + ), + ]), + new Row(imageWidth + MARGINS.left + 1, 0, [ + new LabelledText( + 0, + 0, + 'Eye Colour', + `${actorDetails?.eyecolour?.value}` + ), + new LabelledText( + 0, + 0, + 'Distinguishing Mark', + `${actorDetails?.distinguishingmark?.value}` + ), + new LabelledText(0, 0, 'Star Sign', `${actorDetails?.starsign?.value}`), + ]), + Blank.heightBlank(2), + new Row(0, 0, [ + new LabelledText(0, 0, 'CHARAbbrev.WS', `${actorCharacs?.ws?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.BS', `${actorCharacs?.bs?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.S', `${actorCharacs?.s?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.T', `${actorCharacs?.t?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.I', `${actorCharacs?.i?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.Ag', `${actorCharacs?.ag?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.Dex', `${actorCharacs?.dex?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.Int', `${actorCharacs?.int?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.WP', `${actorCharacs?.wp?.value}`), + new LabelledText(0, 0, 'CHARAbbrev.Fel', `${actorCharacs?.fel?.value}`), + ]), + new Row(0, 0, [ + new LabelledText(0, 0, 'Move', `${actorDetails?.move?.value}`), + new LabelledText(0, 0, 'Walk', `${actorDetails?.move?.walk}`), + new LabelledText(0, 0, 'Run', `${actorDetails?.move?.run}`), + new LabelledText(0, 0, 'Fortune', `${actorStatus?.fortune?.value}`), + new LabelledText(0, 0, 'Fate', `${actorStatus?.fate?.value}`), + new LabelledText(0, 0, 'Resolve', `${actorStatus?.resolve?.value}`), + new LabelledText( + 0, + 0, + 'Resilience', + `${actorStatus?.resilience?.value}` + ), + new LabelledText( + 0, + 0, + 'Wounds', + `${actorStatus?.wounds?.value}/${actorStatus?.wounds?.max}` + ), + ]), + new Separator(0, 0), + new Text(0, 0, 'Skills'), + skills, + new Separator(0, 0), + new Text(0, 0, `${i18nLocalize('Talents')} : ${i18nLocalize('Tests')}`), + talents, + traits.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + traits.elements.length > 0 + ? new Text(0, 0, 'Traits') + : Blank.heightBlank(0), + traits, + weaponsMelee.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + weaponsMelee.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('SHEET.MeleeWeaponHeader')} : ${i18nLocalize( + 'Weapon Group' + )}, ${i18nLocalize('Reach')}, ${i18nLocalize( + 'Damage' + )}, ${i18nLocalize('Qualities')}, ${i18nLocalize('Flaws')}` + ) + : Blank.heightBlank(0), + weaponsMelee, + weaponsRanged.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + weaponsRanged.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('SHEET.RangedWeaponHeader')} : ${i18nLocalize( + 'Weapon Group' + )}, ${i18nLocalize('Range')}, ${i18nLocalize( + 'Damage' + )}, ${i18nLocalize('Qualities')}, ${i18nLocalize('Flaws')}` + ) + : Blank.heightBlank(0), + weaponsRanged, + ammunitions.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + ammunitions.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('Ammunition')} : ${i18nLocalize( + 'Range' + )}, ${i18nLocalize('Damage')}, ${i18nLocalize( + 'Qualities' + )}, ${i18nLocalize('Flaws')}` + ) + : Blank.heightBlank(0), + ammunitions, + armours.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + armours.elements.length > 0 + ? new Text(0, 0, 'Armour') + : Blank.heightBlank(0), + armours, + petty.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + petty.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('SHEET.PettySpell')} : ${i18nLocalize( + 'Casting Number' + )}, ${i18nLocalize('Range')}, ${i18nLocalize( + 'Target' + )}, ${i18nLocalize('Duration')}` + ) + : Blank.heightBlank(0), + petty, + spell.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + spell.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('SHEET.LoreSpell')} : ${i18nLocalize( + 'Casting Number' + )}, ${i18nLocalize('Range')}, ${i18nLocalize( + 'Target' + )}, ${i18nLocalize('Duration')}, ${i18nLocalize( + 'WFRP4E.TrappingType.Ingredients' + )}` + ) + : Blank.heightBlank(0), + spell, + blessing.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + blessing.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('Blessing')} : ${i18nLocalize( + 'Range' + )}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}` + ) + : Blank.heightBlank(0), + blessing, + miracle.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + miracle.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('Miracle')} : ${i18nLocalize( + 'Range' + )}, ${i18nLocalize('Target')}, ${i18nLocalize('Duration')}` + ) + : Blank.heightBlank(0), + miracle, + new Separator(0, 0), + trappingsHeader, + trappings, + psychology.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + psychology.elements.length > 0 + ? new Text(0, 0, 'Psychology') + : Blank.heightBlank(0), + psychology, + critical.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + critical.elements.length > 0 + ? new Text(0, 0, 'Criticals') + : Blank.heightBlank(0), + critical, + disease.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + disease.elements.length > 0 + ? new Text(0, 0, 'Diseases') + : Blank.heightBlank(0), + disease, + injury.elements.length > 0 ? new Separator(0, 0) : Blank.heightBlank(0), + injury.elements.length > 0 + ? new Text(0, 0, 'Injuries') + : Blank.heightBlank(0), + injury, + mutationP.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + mutationP.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('Mutations')} (${i18nLocalize('Physical')})` + ) + : Blank.heightBlank(0), + mutationP, + mutationM.elements.length > 0 + ? new Separator(0, 0) + : Blank.heightBlank(0), + mutationM.elements.length > 0 + ? new Text( + 0, + 0, + `${i18nLocalize('Mutations')} (${i18nLocalize('Mental')})` + ) + : Blank.heightBlank(0), + mutationM, + ]), + ]); + docBuilder.doc.save(`${actor.name}.pdf`); +}