Merge branch '066-switch-to-foundry-vtt-types' into 'master'

Switch to using foundry-vtt-types type definitions

Closes #66

See merge request dungeonslayers/ds4!70
This commit is contained in:
Johannes Loher 2021-02-07 12:31:23 +01:00
commit a31f5fa4b6
22 changed files with 908 additions and 275 deletions

View file

@ -12,6 +12,8 @@ module.exports = {
"plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array. "plugin:prettier/recommended", // Enables eslint-plugin-prettier and eslint-config-prettier. This will display prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
], ],
plugins: ["@typescript-eslint"],
rules: { rules: {
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
// e.g. "@typescript-eslint/explicit-function-return-type": "off", // e.g. "@typescript-eslint/explicit-function-return-type": "off",

571
package-lock.json generated
View file

@ -110,6 +110,383 @@
"fastq": "^1.6.0" "fastq": "^1.6.0"
} }
}, },
"@pixi/accessibility": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/accessibility/-/accessibility-5.3.4.tgz",
"integrity": "sha512-g8hQnnVSYJ+gLrdQyCsDDSu+VehhVL9Pcr2fkQSC9VBhxiMIN+Paky8kOxC2LL5nsKRIUGGaTa6iHtiopPQQMw==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/app": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/app/-/app-5.3.4.tgz",
"integrity": "sha512-XT/EFyGslFdvdHY9ZS7yDAdLOj0U1UHeLxFr1kwiawuwIt/WsxNeH4jq2IijvZuQ3L5ON7Y7zQf54JEPv5fK0Q==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4"
}
},
"@pixi/constants": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/constants/-/constants-5.3.4.tgz",
"integrity": "sha512-YsWjdMVMoJA8kG/0D4s9/DWWa2lPlexk0qNZOcV3tICaPG0IYfIhepfveMeMhIb0QrdSAsPbhYdcaxxgoaNF1A==",
"dev": true
},
"@pixi/core": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/core/-/core-5.3.4.tgz",
"integrity": "sha512-k6SRniy4pH7ZKAKC2HkbLSKPm+j7bF17fTO5+6xLSiVqLnfa7ChV51wNuoa30olVF3/d8ME2uraf7dsvXwomzw==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/runner": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/ticker": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/display": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/display/-/display-5.3.4.tgz",
"integrity": "sha512-RCi39Qi1L8mlIu1YvWvPI45WpKHRbpYlvSIT/414wmoaAoFZnaJ+qoVuqDCfzfNhWWirGAWpXniQjNRzkUZjcA==",
"dev": true,
"requires": {
"@pixi/math": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/extract": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/extract/-/extract-5.3.4.tgz",
"integrity": "sha512-HTGF5WKts4kF0v1rOU4YcLMUpb18FzcxKhaCwjXpqm3vANgjuGAUL9PxpmC4ecS03mkRa0+9vAXEUkJLQeNLPg==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/filter-alpha": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-alpha/-/filter-alpha-5.3.4.tgz",
"integrity": "sha512-lgRCN8bDeHlMpRtQv/P5gCJ+9e3AufJVC2H0TdkCRmJqm1dB+rhKwxIeNINsjjz+kiuumOe88CxRbRd3CpEydg==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4"
}
},
"@pixi/filter-blur": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-blur/-/filter-blur-5.3.4.tgz",
"integrity": "sha512-PYPHc8MEsZWfmVQkm0UKO70dmZpcWyu/Bs0xJa5apsmCm6zXNzXfMh02lsXu82HrNQ+9iJT/mAKrrDABGn9vtg==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/settings": "5.3.4"
}
},
"@pixi/filter-color-matrix": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-color-matrix/-/filter-color-matrix-5.3.4.tgz",
"integrity": "sha512-9Iflvr1moc7ns5A/73lWVwLUbe+wb678NLA4X9SYXAJTiij4M1isDrULhk95TGUaWo4bbSBaov1vm8XbUZNG8w==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4"
}
},
"@pixi/filter-displacement": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-displacement/-/filter-displacement-5.3.4.tgz",
"integrity": "sha512-CldemXpcKr1GRT1Ll33TTFWtU6KDl4sYTvAwWTAEu8OhKedobBB/mRCIK9p1h7iZYtaj5MRYQjewmFKRrqyXrQ==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/math": "5.3.4"
}
},
"@pixi/filter-fxaa": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-fxaa/-/filter-fxaa-5.3.4.tgz",
"integrity": "sha512-GtIfaOsqQlsK+F1795V/JJIq5Uu15nasiCwGr+wVwHNGMBanAXt7AnSy8JHcgup3Eqx8FXRuM/AyD/4IYUquuA==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4"
}
},
"@pixi/filter-noise": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/filter-noise/-/filter-noise-5.3.4.tgz",
"integrity": "sha512-pNq4T4LC2naWz0pZXF3RT9aA7XdLL4TuBjJsYrrBaJZraupbOo6Mp8VwxVJs8GThmMl7/U13GalOzVSb/HjzDg==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4"
}
},
"@pixi/graphics": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/graphics/-/graphics-5.3.4.tgz",
"integrity": "sha512-W6cuFfzwgfx3zVFICu98cENgwjy+d2e6xNJ/yJI0q8QiwlZmpuSXHBCfZrtIWpp9VSJZe2KDIo1LUnLhCpp3Yg==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/interaction": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/interaction/-/interaction-5.3.4.tgz",
"integrity": "sha512-7/JN7AtCuYmmWczrQROKSI9Z42p6C6p7B2wDVqNYYgROSaeGbGsZ8H0sa6nYLnIj4F3CaGSRoRnAMPz+CO70bw==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/ticker": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/loaders": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/loaders/-/loaders-5.3.4.tgz",
"integrity": "sha512-/dFznZnsivzq/MW7n/PPhMeznWFMMDYrac958OlxzSwrEAgtq6ZVLZbz7pCf9uhiifMnqwBGefphOFubj3Qorw==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/utils": "5.3.4",
"resource-loader": "^3.0.1"
}
},
"@pixi/math": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/math/-/math-5.3.4.tgz",
"integrity": "sha512-UQ2jhdlCHIvAVf8EcHB3QuR5GhB49VdTccWmer96RZCeGkcZsPSUk1ldO1GZnIctcf0Iuvmq74G02dYbtC7JxQ==",
"dev": true
},
"@pixi/mesh": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/mesh/-/mesh-5.3.4.tgz",
"integrity": "sha512-y0Y52cwsqETc/35DMGVCzQmhPCrQ3ZhjWcW9JwQoHMy3PoNSN9QUqYjVjF2oEj5hxcJnGNo3GAXFZz2Uh/UReQ==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/mesh-extras": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/mesh-extras/-/mesh-extras-5.3.4.tgz",
"integrity": "sha512-mjc3RlgLGYUv2FUKrVv/Dfaj2KW5qhX9c6Ev+yJ4lg/sMblet5gtYuyKsmJMS/K6B8V8+oMlTfX9ozFCzq1oJQ==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/mesh": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/mixin-cache-as-bitmap": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/mixin-cache-as-bitmap/-/mixin-cache-as-bitmap-5.3.4.tgz",
"integrity": "sha512-8ZAmzDK1fHXIzYFHFH72LUMRZerY1Pt71XI3UgsWExABS1aREe20oPLuVByLP94W7X/kTXz+zK+nt51O5MGKsA==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/mixin-get-child-by-name": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/mixin-get-child-by-name/-/mixin-get-child-by-name-5.3.4.tgz",
"integrity": "sha512-PY1Qe6CKYu+UNSRAFIfRyhRfkrpsTMwh9sI6iXVVi712bM3JkZIwDfDF31TA4nYX8z7H49w+KCWY4PejZ8l2WA==",
"dev": true,
"requires": {
"@pixi/display": "5.3.4"
}
},
"@pixi/mixin-get-global-position": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/mixin-get-global-position/-/mixin-get-global-position-5.3.4.tgz",
"integrity": "sha512-yv+huwUAOfyXDEHbQp6W5/3RjQpwG6AhpgMY4b3XBMtvrp9R/5Wgw/YC/nea9kZ3Gb2u4Aqeco8U+tPIRNjeIA==",
"dev": true,
"requires": {
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4"
}
},
"@pixi/particles": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/particles/-/particles-5.3.4.tgz",
"integrity": "sha512-sX0BGGbS7yCwlam1mC5awW2BjU7QFmZv82E8ON/r9aAZS6InT25zOpMdvy0ImIIqBvF0Z1Qz1IT6pKEBxqMo9Q==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/polyfill": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/polyfill/-/polyfill-5.3.4.tgz",
"integrity": "sha512-bxk8bhrfQ9Y2rU/L0ss2gIeXwmMlOciw+B5yVUDVLqzjE4y8Fm2619L4qu9v51Z9a+8JbyVE5c1eT7HJgx0g0w==",
"dev": true,
"requires": {
"es6-promise-polyfill": "^1.2.0",
"object-assign": "^4.1.1"
}
},
"@pixi/prepare": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/prepare/-/prepare-5.3.4.tgz",
"integrity": "sha512-MVMvNTrNYQidWXd4LSkgv+eqTzHtSViADA+Tvnemy9QMuWqbTfxFn4UMhrBjQIfG9+hwdIFS14pfFKt/BLHNrw==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/graphics": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/text": "5.3.4",
"@pixi/ticker": "5.3.4"
}
},
"@pixi/runner": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/runner/-/runner-5.3.4.tgz",
"integrity": "sha512-iPWHVhv2js+NhDQNmePkHfic8SilBT7H/pzRjMqHqvafTdl8Y+4g+hdQDalZJNr3Ixl77QPAYlOKhegBujn2mQ==",
"dev": true
},
"@pixi/settings": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/settings/-/settings-5.3.4.tgz",
"integrity": "sha512-Jqj1NLtYODCqK8ZKVccUBAaBDkn7SQ6b7N15FwxbiSgfbvwpynSKr6WQTxqMq29h42MKsic6BJcQrlGEbDNz5w==",
"dev": true,
"requires": {
"ismobilejs": "^1.1.0"
}
},
"@pixi/sprite": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/sprite/-/sprite-5.3.4.tgz",
"integrity": "sha512-vO+GMJWnumnVzc2R7jGcLlUeIXIek+SDqVQyPDPJ5T8sWTgFhanHCrgpKfplZIu08X/zvIZQxPfd332R0waeog==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/sprite-animated": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/sprite-animated/-/sprite-animated-5.3.4.tgz",
"integrity": "sha512-HaTelbvm2xekw9b9GdYbupM2RZ/muRZvstkmSqMZhiIViZekzKPa5WQJwnqZzVBjCg735j09G8aF4H2NpNqF9g==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/ticker": "5.3.4"
}
},
"@pixi/sprite-tiling": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/sprite-tiling/-/sprite-tiling-5.3.4.tgz",
"integrity": "sha512-NMqpNuWEIic2n5EL/TrGmn1+bab4TwxcILnco4myvw9Sd/wLsaJx3XboegY7YCWCKhnl+Ax6cl8DMkk7OJkpJQ==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/spritesheet": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/spritesheet/-/spritesheet-5.3.4.tgz",
"integrity": "sha512-gfCqOMD2XJHw1bMXxXbuYPnBbCBUvbzMN7Pw2po7U5R6bsk7WEoG7Hp3HjAPyPQvg36v2Db6dcz0//ZNNqm+EQ==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/loaders": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/text": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/text/-/text-5.3.4.tgz",
"integrity": "sha512-kmdK1KLrWY8PHGIIXKVRQmik3gWquiYz6DB0jqabi3j0gVp6h+CVDje01N6Nl75ZCQ/PjaWafzQvURypfX73ng==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/text-bitmap": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/text-bitmap/-/text-bitmap-5.3.4.tgz",
"integrity": "sha512-uNJOYvy3sn0S5Bp6H113ZAmaQm68ojCXSuOBJzIMEV2cUuYLngW+7DqKOsHMMhNmcONs/OBq57SRrzDcr8WYdw==",
"dev": true,
"requires": {
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/loaders": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/mesh": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/text": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"@pixi/ticker": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/ticker/-/ticker-5.3.4.tgz",
"integrity": "sha512-PmCAstgyI6vLPXKZVFlo4Zornry21BwFiTOp1dBUW3sIMky9Wx2fajjyVHIridCY6yaazt6Xu37khZf5qRgASw==",
"dev": true,
"requires": {
"@pixi/settings": "5.3.4"
}
},
"@pixi/utils": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/@pixi/utils/-/utils-5.3.4.tgz",
"integrity": "sha512-HjUWFfAmPPKX0BSq20GWY//Vm+gC9O+wcn9sXMqOItCuf0DDFwxoBrUVaHNNnEVhM1Djpz/+YijCijmGdZeddA==",
"dev": true,
"requires": {
"@pixi/constants": "5.3.4",
"@pixi/settings": "5.3.4",
"earcut": "^2.1.5",
"eventemitter3": "^3.1.0",
"url": "^0.11.0"
}
},
"@types/fs-extra": { "@types/fs-extra": {
"version": "9.0.6", "version": "9.0.6",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.6.tgz", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.6.tgz",
@ -119,6 +496,12 @@
"@types/node": "*" "@types/node": "*"
} }
}, },
"@types/howler": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@types/howler/-/howler-2.2.1.tgz",
"integrity": "sha512-1MiSldngr+eAO4lDPtjzl4Nf2GmRh8VDHIpNBIkyd25L22JExVlI6w3fjSM7+FNc1e1WZAPNq7/flkw685byfg==",
"dev": true
},
"@types/jasmine": { "@types/jasmine": {
"version": "3.6.2", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.2.tgz", "resolved": "https://registry.npmjs.org/@types/jasmine/-/jasmine-3.6.2.tgz",
@ -126,9 +509,9 @@
"dev": true "dev": true
}, },
"@types/jquery": { "@types/jquery": {
"version": "3.5.5", "version": "3.5.1",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.5.tgz", "resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.1.tgz",
"integrity": "sha512-6RXU9Xzpc6vxNrS6FPPapN1SxSHgQ336WC6Jj/N8q30OiaBZ00l1GBgeP7usjVZPivSkGUfL1z/WW6TX989M+w==", "integrity": "sha512-Tyctjh56U7eX2b9udu3wG853ASYP0uagChJcQJXLUXEU6C/JiW5qt5dl8ao01VRj1i5pgXPAf8f1mq4+FDLRQg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/sizzle": "*" "@types/sizzle": "*"
@ -1821,6 +2204,12 @@
"object.defaults": "^1.1.0" "object.defaults": "^1.1.0"
} }
}, },
"earcut": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.2.tgz",
"integrity": "sha512-eZoZPPJcUHnfRZ0PjLvx2qBordSiO8ofC3vt+qACLM95u+4DovnbYNpQtJh0DNsWj8RnxrQytD4WA8gj5cRIaQ==",
"dev": true
},
"ecc-jsbn": { "ecc-jsbn": {
"version": "0.1.2", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@ -1935,6 +2324,12 @@
"es6-symbol": "^3.1.1" "es6-symbol": "^3.1.1"
} }
}, },
"es6-promise-polyfill": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/es6-promise-polyfill/-/es6-promise-polyfill-1.2.0.tgz",
"integrity": "sha1-84kl8jyz4+jObNqP93T867sJDN4=",
"dev": true
},
"es6-symbol": { "es6-symbol": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
@ -2224,6 +2619,12 @@
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true "dev": true
}, },
"eventemitter3": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz",
"integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==",
"dev": true
},
"execa": { "execa": {
"version": "4.1.0", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz",
@ -2717,14 +3118,28 @@
"mime-types": "^2.1.12" "mime-types": "^2.1.12"
} }
}, },
"foundry-pc-types": { "foundry-vtt-types": {
"version": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#ac45653fdec5fb935bf7db72889cb40cd6b80b20", "version": "github:League-of-Foundry-Developers/foundry-vtt-types#32d849fd2afa4e88319c0105c989cec62bb888c2",
"from": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes", "from": "github:League-of-Foundry-Developers/foundry-vtt-types#foundry-0.7.9",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/jquery": "^3.5.1", "@types/howler": "2.2.1",
"@types/jquery": "3.5.1",
"@types/node": "^14.14.21",
"@types/socket.io-client": "^1.4.33", "@types/socket.io-client": "^1.4.33",
"@types/tinymce": "^4.5.24" "@types/tinymce": "^4.5.24",
"handlebars": "4.7.6",
"pixi.js": "5.3.4",
"typescript": "^4.1.3",
"utility-types": "^3.10.0"
},
"dependencies": {
"@types/node": {
"version": "14.14.25",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.25.tgz",
"integrity": "sha512-EPpXLOVqDvisVxtlbvzfyqSsFeQxltFbluZNRndIb8tr9KiBnYNLzrc1N3pyKUCww2RNrfHDViqDWWE1LCJQtQ==",
"dev": true
}
} }
}, },
"fragment-cache": { "fragment-cache": {
@ -3277,6 +3692,40 @@
"glogg": "^1.0.0" "glogg": "^1.0.0"
} }
}, },
"handlebars": {
"version": "4.7.6",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.6.tgz",
"integrity": "sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA==",
"dev": true,
"requires": {
"minimist": "^1.2.5",
"neo-async": "^2.6.0",
"source-map": "^0.6.1",
"uglify-js": "^3.1.4",
"wordwrap": "^1.0.0"
},
"dependencies": {
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
},
"uglify-js": {
"version": "3.12.7",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.12.7.tgz",
"integrity": "sha512-SIZhkoh+U/wjW+BHGhVwE9nt8tWJspncloBcFapkpGRwNPqcH8pzX36BXe3TPBjzHWPMUZotpCigak/udWNr1Q==",
"dev": true,
"optional": true
},
"wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=",
"dev": true
}
}
},
"har-schema": { "har-schema": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
@ -3776,6 +4225,12 @@
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
"dev": true "dev": true
}, },
"ismobilejs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ismobilejs/-/ismobilejs-1.1.1.tgz",
"integrity": "sha512-VaFW53yt8QO61k2WJui0dHf4SlL8lxBofUuUmwBo0ljPk0Drz2TiuDW4jo3wDcv41qy/SxrJ+VAzJ/qYqsmzRw==",
"dev": true
},
"isobject": { "isobject": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
@ -4551,6 +5006,12 @@
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true "dev": true
}, },
"mini-signals": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mini-signals/-/mini-signals-1.2.0.tgz",
"integrity": "sha1-RbCAE8X65RokqhqTXNMXye1yHXQ=",
"dev": true
},
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@ -4646,6 +5107,12 @@
"integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=",
"dev": true "dev": true
}, },
"neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"next-tick": { "next-tick": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
@ -5072,6 +5539,12 @@
"integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=",
"dev": true "dev": true
}, },
"parse-uri": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/parse-uri/-/parse-uri-1.0.3.tgz",
"integrity": "sha512-upMnGxNcm+45So85HoguwZTVZI9u11i36DdxJfGF2HYWS2eh3TIx7+/tTi7qrEq15qzGkVhsKjesau+kCk48pA==",
"dev": true
},
"pascalcase": { "pascalcase": {
"version": "0.1.1", "version": "0.1.1",
"resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
@ -5170,6 +5643,48 @@
"pinkie": "^2.0.0" "pinkie": "^2.0.0"
} }
}, },
"pixi.js": {
"version": "5.3.4",
"resolved": "https://registry.npmjs.org/pixi.js/-/pixi.js-5.3.4.tgz",
"integrity": "sha512-CrAaQQRw+iTA75IEu57CEk6stFs587iWE3HwQG0rZL2ESW2uJvdsF/ieeS/hFk35QmlEsPRqmH1sf7t7FGtsyw==",
"dev": true,
"requires": {
"@pixi/accessibility": "5.3.4",
"@pixi/app": "5.3.4",
"@pixi/constants": "5.3.4",
"@pixi/core": "5.3.4",
"@pixi/display": "5.3.4",
"@pixi/extract": "5.3.4",
"@pixi/filter-alpha": "5.3.4",
"@pixi/filter-blur": "5.3.4",
"@pixi/filter-color-matrix": "5.3.4",
"@pixi/filter-displacement": "5.3.4",
"@pixi/filter-fxaa": "5.3.4",
"@pixi/filter-noise": "5.3.4",
"@pixi/graphics": "5.3.4",
"@pixi/interaction": "5.3.4",
"@pixi/loaders": "5.3.4",
"@pixi/math": "5.3.4",
"@pixi/mesh": "5.3.4",
"@pixi/mesh-extras": "5.3.4",
"@pixi/mixin-cache-as-bitmap": "5.3.4",
"@pixi/mixin-get-child-by-name": "5.3.4",
"@pixi/mixin-get-global-position": "5.3.4",
"@pixi/particles": "5.3.4",
"@pixi/polyfill": "5.3.4",
"@pixi/prepare": "5.3.4",
"@pixi/runner": "5.3.4",
"@pixi/settings": "5.3.4",
"@pixi/sprite": "5.3.4",
"@pixi/sprite-animated": "5.3.4",
"@pixi/sprite-tiling": "5.3.4",
"@pixi/spritesheet": "5.3.4",
"@pixi/text": "5.3.4",
"@pixi/text-bitmap": "5.3.4",
"@pixi/ticker": "5.3.4",
"@pixi/utils": "5.3.4"
}
},
"pkg-dir": { "pkg-dir": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz",
@ -5348,6 +5863,12 @@
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
"dev": true "dev": true
}, },
"querystring": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
"integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=",
"dev": true
},
"read-pkg": { "read-pkg": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
@ -5596,6 +6117,16 @@
"integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=",
"dev": true "dev": true
}, },
"resource-loader": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/resource-loader/-/resource-loader-3.0.1.tgz",
"integrity": "sha512-fBuCRbEHdLCI1eglzQhUv9Rrdcmqkydr1r6uHE2cYHvRBrcLXeSmbE/qI/urFt8rPr/IGxir3BUwM5kUK8XoyA==",
"dev": true,
"requires": {
"mini-signals": "^1.2.0",
"parse-uri": "^1.0.0"
}
},
"restore-cursor": { "restore-cursor": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
@ -6891,6 +7422,24 @@
"integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=",
"dev": true "dev": true
}, },
"url": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
"integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=",
"dev": true,
"requires": {
"punycode": "1.3.2",
"querystring": "0.2.0"
},
"dependencies": {
"punycode": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
"integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=",
"dev": true
}
}
},
"use": { "use": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
@ -6903,6 +7452,12 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true "dev": true
}, },
"utility-types": {
"version": "3.10.0",
"resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.10.0.tgz",
"integrity": "sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg==",
"dev": true
},
"uuid": { "uuid": {
"version": "3.4.0", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",

View file

@ -35,7 +35,7 @@
"build:watch": "gulp watch", "build:watch": "gulp watch",
"link": "gulp link", "link": "gulp link",
"clean": "gulp clean && gulp link --clean", "clean": "gulp clean && gulp link --clean",
"update": "npm install --save-dev git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes", "update": "npm install --save-dev github:League-of-Foundry-Developers/foundry-vtt-types#foundry-0.7.9",
"updateManifest": "gulp updateManifest", "updateManifest": "gulp updateManifest",
"lint": "eslint 'src/**/*.ts' --cache", "lint": "eslint 'src/**/*.ts' --cache",
"lint:fix": "eslint 'src/**/*.ts' --cache --fix", "lint:fix": "eslint 'src/**/*.ts' --cache --fix",
@ -53,7 +53,7 @@
"eslint": "^7.18.0", "eslint": "^7.18.0",
"eslint-config-prettier": "^7.1.0", "eslint-config-prettier": "^7.1.0",
"eslint-plugin-prettier": "^3.3.1", "eslint-plugin-prettier": "^3.3.1",
"foundry-pc-types": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes", "foundry-vtt-types": "github:League-of-Foundry-Developers/foundry-vtt-types#foundry-0.7.9",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-git": "^2.10.1", "gulp-git": "^2.10.1",

View file

@ -1,20 +1,31 @@
import { ModifiableData, ResourceData, UsableResource } from "../common/common-data"; import { ModifiableData, ResourceData, UsableResource } from "../common/common-data";
import { DS4 } from "../config";
import { DS4ItemData } from "../item/item-data";
export type DS4ActorDataType = DS4ActorDataCharacter | DS4ActorDataCreature; export type DS4ActorData = DS4CharacterData | DS4CreatureData;
interface DS4ActorDataBase { type ActorType = keyof typeof DS4.i18n.actorTypes;
attributes: DS4ActorDataAttributes;
traits: DS4ActorDataTraits; interface DS4ActorDataHelper<T, U extends ActorType> extends Actor.Data<T, DS4ItemData> {
combatValues: DS4ActorDataCombatValues; type: U;
} }
interface DS4ActorDataAttributes { type DS4CharacterData = DS4ActorDataHelper<DS4CharacterDataData, "character">;
type DS4CreatureData = DS4ActorDataHelper<DS4CreatureDataData, "creature">;
interface DS4ActorDataDataBase {
attributes: DS4ActorDataDataAttributes;
traits: DS4ActorDataDataTraits;
combatValues: DS4ActorDataDataCombatValues;
}
interface DS4ActorDataDataAttributes {
body: ModifiableData<number>; body: ModifiableData<number>;
mobility: ModifiableData<number>; mobility: ModifiableData<number>;
mind: ModifiableData<number>; mind: ModifiableData<number>;
} }
interface DS4ActorDataTraits { interface DS4ActorDataDataTraits {
strength: ModifiableData<number>; strength: ModifiableData<number>;
constitution: ModifiableData<number>; constitution: ModifiableData<number>;
agility: ModifiableData<number>; agility: ModifiableData<number>;
@ -23,7 +34,7 @@ interface DS4ActorDataTraits {
aura: ModifiableData<number>; aura: ModifiableData<number>;
} }
interface DS4ActorDataCombatValues { interface DS4ActorDataDataCombatValues {
hitPoints: ResourceData<number>; hitPoints: ResourceData<number>;
defense: ModifiableData<number>; defense: ModifiableData<number>;
initiative: ModifiableData<number>; initiative: ModifiableData<number>;
@ -34,34 +45,32 @@ interface DS4ActorDataCombatValues {
targetedSpellcasting: ModifiableData<number>; targetedSpellcasting: ModifiableData<number>;
} }
interface DS4ActorDataCharacter extends DS4ActorDataBase { interface DS4CharacterDataData extends DS4ActorDataDataBase {
baseInfo: DS4ActorDataCharacterBaseInfo; baseInfo: DS4CharacterDataDataBaseInfo;
progression: DS4ActorDataCharacterProgression; progression: DS4CharacterDataDataProgression;
language: DS4ActorDataCharacterLanguage; language: DS4CharacterDataDataLanguage;
profile: DS4ActorDataCharacterProfile; profile: DS4CharacterDataDataProfile;
currency: DS4ActorDataCharacterCurrency; currency: DS4CharacterDataDataCurrency;
} }
interface DS4CharacterDataDataBaseInfo {
interface DS4ActorDataCharacterBaseInfo {
race: string; race: string;
class: string; class: string;
heroClass: string; heroClass: string;
culture: string; culture: string;
} }
interface DS4CharacterDataDataProgression {
interface DS4ActorDataCharacterProgression {
level: number; level: number;
experiencePoints: number; experiencePoints: number;
talentPoints: UsableResource<number>; talentPoints: UsableResource<number>;
progressPoints: UsableResource<number>; progressPoints: UsableResource<number>;
} }
interface DS4ActorDataCharacterLanguage { interface DS4CharacterDataDataLanguage {
languages: string; languages: string;
alphabets: string; alphabets: string;
} }
interface DS4ActorDataCharacterProfile { interface DS4CharacterDataDataProfile {
biography: string; biography: string;
gender: string; gender: string;
birthday: string; birthday: string;
@ -74,21 +83,21 @@ interface DS4ActorDataCharacterProfile {
specialCharacteristics: string; specialCharacteristics: string;
} }
interface DS4ActorDataCharacterCurrency { interface DS4CharacterDataDataCurrency {
gold: number; gold: number;
silver: number; silver: number;
copper: number; copper: number;
} }
interface DS4ActorDataCreature extends DS4ActorDataBase { interface DS4CreatureDataData extends DS4ActorDataDataBase {
baseInfo: DS4ActorDataCreatureBaseInfo; baseInfo: DS4CreatureDataDataBaseInfo;
} }
type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead"; type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead";
type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal"; type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal";
interface DS4ActorDataCreatureBaseInfo { interface DS4CreatureDataDataBaseInfo {
loot: string; loot: string;
foeFactor: number; foeFactor: number;
creatureType: CreatureType; creatureType: CreatureType;

View file

@ -1,9 +1,12 @@
import { ModifiableData } from "../common/common-data"; import { ModifiableData } from "../common/common-data";
import { DS4Item } from "../item/item"; import { DS4Item } from "../item/item";
import { DS4Armor, DS4ItemDataType, DS4Shield, ItemType } from "../item/item-data"; import { ItemType } from "../item/item-data";
import { DS4ActorDataType } from "./actor-data"; import { DS4ActorData } from "./actor-data";
export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item> { /**
* The Actor class for DS4
*/
export class DS4Actor extends Actor<DS4ActorData, DS4Item> {
/** @override */ /** @override */
prepareDerivedData(): void { prepareDerivedData(): void {
const data = this.data; const data = this.data;
@ -45,7 +48,7 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
/** /**
* Checks whether or not the given item type can be owned by the actor. * Checks whether or not the given item type can be owned by the actor.
* @param itemType the item type to check * @param itemType - The item type to check
*/ */
canOwnItemType(itemType: ItemType): boolean { canOwnItemType(itemType: ItemType): boolean {
return this.ownableItemTypes.includes(itemType); return this.ownableItemTypes.includes(itemType);
@ -84,10 +87,13 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
*/ */
private _calculateArmorValueOfEquippedItems(): number { private _calculateArmorValueOfEquippedItems(): number {
return this.items return this.items
.filter((item) => ["armor", "shield"].includes(item.type)) .map((item) => {
.map((item) => item.data.data as DS4Armor | DS4Shield) if (item.data.type === "armor" || item.data.type === "shield") {
.filter((itemData) => itemData.equipped) return item.data.data.equipped ? item.data.data.armorValue : 0;
.map((itemData) => itemData.armorValue) } else {
return 0;
}
})
.reduce((a, b) => a + b, 0); .reduce((a, b) => a + b, 0);
} }
@ -96,7 +102,7 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
* This only differs from the base implementation by also allowing negative values. * This only differs from the base implementation by also allowing negative values.
* @override * @override
*/ */
async modifyTokenAttribute(attribute: string, value: number, isDelta = false, isBar = true): Promise<DS4Actor> { async modifyTokenAttribute(attribute: string, value: number, isDelta = false, isBar = true): Promise<this> {
const current = getProperty(this.data.data, attribute); const current = getProperty(this.data.data, attribute);
// Determine the updates to make to the actor data // Determine the updates to make to the actor data

View file

@ -1,20 +1,38 @@
import { DS4 } from "../../config";
import { DS4Item } from "../../item/item"; import { DS4Item } from "../../item/item";
import { DS4ItemDataType, ItemType } from "../../item/item-data"; import { DS4ItemData } from "../../item/item-data";
import { DS4Actor } from "../actor"; import { DS4Actor } from "../actor";
import { DS4ActorDataType } from "../actor-data";
/** /**
* Extend the basic ActorSheet with some very simple modifications * The base Sheet class for all DS4 Actors
* @extends {ActorSheet}
*/ */
export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4ItemDataType> { export class DS4ActorSheet extends ActorSheet<DS4Actor> {
// TODO(types): Improve mergeObject in upstream so that it isn't necessary to provide all parameters (see https://github.com/League-of-Foundry-Developers/foundry-vtt-types/issues/272)
/** @override */ /** @override */
static get defaultOptions(): FormApplicationOptions { static get defaultOptions(): BaseEntitySheet.Options {
return mergeObject(super.defaultOptions, { const superDefaultOptions = super.defaultOptions;
return mergeObject(superDefaultOptions, {
classes: ["ds4", "sheet", "actor"], classes: ["ds4", "sheet", "actor"],
width: 745, width: 745,
height: 600, height: 600,
scrollY: [".sheet-body"], scrollY: [".sheet-body"],
template: superDefaultOptions.template,
viewPermission: superDefaultOptions.viewPermission,
closeOnSubmit: superDefaultOptions.closeOnSubmit,
submitOnChange: superDefaultOptions.submitOnChange,
submitOnClose: superDefaultOptions.submitOnClose,
editable: superDefaultOptions.editable,
baseApplication: superDefaultOptions.baseApplication,
top: superDefaultOptions.top,
left: superDefaultOptions.left,
popOut: superDefaultOptions.popOut,
minimizable: superDefaultOptions.minimizable,
resizable: superDefaultOptions.resizable,
id: superDefaultOptions.id,
dragDrop: superDefaultOptions.dragDrop,
filters: superDefaultOptions.filters,
title: superDefaultOptions.title,
tabs: superDefaultOptions.tabs,
}); });
} }
@ -24,27 +42,23 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
return `${path}/${this.actor.data.type}-sheet.hbs`; return `${path}/${this.actor.data.type}-sheet.hbs`;
} }
/* -------------------------------------------- */
/** /**
* This method returns the data for the template of the actor sheet. * This method returns the data for the template of the actor sheet.
* It explicitly adds the items of the object sorted by type in the * It explicitly adds the items of the object sorted by type in the
* object itemsByType. * object itemsByType.
* @returns the data fed to the template of the actor sheet * @returns The data fed to the template of the actor sheet
*/ */
getData(): ActorSheetData<DS4ActorDataType, DS4Actor> { getData(): ActorSheet.Data<DS4Actor> | Promise<ActorSheet.Data<DS4Actor>> {
const data = { const data = {
...super.getData(), ...super.getData(),
// Add the localization config to the data: // Add the localization config to the data:
config: CONFIG.DS4, config: DS4,
// Add the items explicitly sorted by type to the data: // Add the items explicitly sorted by type to the data:
itemsByType: this.actor.itemTypes, itemsByType: this.actor.itemTypes,
}; };
return data; return data;
} }
/* -------------------------------------------- */
/** @override */ /** @override */
activateListeners(html: JQuery): void { activateListeners(html: JQuery): void {
super.activateListeners(html); super.activateListeners(html);
@ -75,20 +89,16 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
html.find(".rollable").click(this._onRoll.bind(this)); html.find(".rollable").click(this._onRoll.bind(this));
} }
/* -------------------------------------------- */
/** /**
* Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset * Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset
* @param {JQuery.ClickEvent} event The originating click event * @param event - The originating click event
* @private
*/ */
private _onItemCreate(event: JQuery.ClickEvent): Promise<Item> { protected _onItemCreate(event: JQuery.ClickEvent): Promise<DS4ItemData> {
event.preventDefault(); event.preventDefault();
const header = event.currentTarget; const header = event.currentTarget;
// Get the type of item to create. // Get the type of item to create.
const type = header.dataset.type;
// Grab any data associated with this control. // Grab any data associated with this control.
const data = duplicate(header.dataset); const { type, ...data } = duplicate(header.dataset);
// Initialize a default name. // Initialize a default name.
const name = `New ${type.capitalize()}`; const name = `New ${type.capitalize()}`;
// Prepare the item object. // Prepare the item object.
@ -97,8 +107,6 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
type: type, type: type,
data: data, data: data,
}; };
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data.type;
// Finally, create the item! // Finally, create the item!
return this.actor.createOwnedItem(itemData); return this.actor.createOwnedItem(itemData);
@ -108,15 +116,14 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
* Handle changes to properties of an Owned Item from within character sheet. * Handle changes to properties of an Owned Item from within character sheet.
* Can currently properly bind: see getValue(). * Can currently properly bind: see getValue().
* Assumes the item property is given as the value of the HTML element property 'data-property'. * Assumes the item property is given as the value of the HTML element property 'data-property'.
* @param {JQuery.ChangeEvent<HTMLFormElement>} ev The originating change event * @param ev - The originating change event
* @private
*/ */
private _onItemChange(ev: JQuery.ChangeEvent<HTMLFormElement>): void { protected _onItemChange(ev: JQuery.ChangeEvent): void {
ev.preventDefault(); ev.preventDefault();
console.log("Current target:", $(ev.currentTarget).get(0)["name"]); console.log("Current target:", $(ev.currentTarget).get(0)["name"]);
const el: HTMLFormElement = $(ev.currentTarget).get(0); const el: HTMLFormElement = $(ev.currentTarget).get(0);
const id = $(ev.currentTarget).parents(".item").data("itemId"); const id = $(ev.currentTarget).parents(".item").data("itemId");
const item = duplicate(this.actor.getOwnedItem(id)); // getOwnedItem is typed incorrectly, it actually returns a ItemData<DS4ItemDataType>, not an Item const item = duplicate<DS4Item, "lenient">(this.actor.getOwnedItem(id));
const property: string | undefined = $(ev.currentTarget).data("property"); const property: string | undefined = $(ev.currentTarget).data("property");
// Early return: // Early return:
@ -139,7 +146,7 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
* - Checkbox: boolean * - Checkbox: boolean
* - Text input: string * - Text input: string
* - Number: number * - Number: number
* @param el the input element to collect the value of * @param el - The input element to collect the value of
*/ */
private getValue(el: HTMLFormElement): boolean | string | number { private getValue(el: HTMLFormElement): boolean | string | number {
// One needs to differentiate between e.g. checkboxes (value="on") and select boxes etc. // One needs to differentiate between e.g. checkboxes (value="on") and select boxes etc.
@ -190,10 +197,9 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
/** /**
* Handle clickable rolls. * Handle clickable rolls.
* @param {JQuery.ClickEvent} event The originating click event * @param event - The originating click event
* @private
*/ */
private _onRoll(event: JQuery.ClickEvent): void { protected _onRoll(event: JQuery.ClickEvent): void {
event.preventDefault(); event.preventDefault();
const element = event.currentTarget; const element = event.currentTarget;
const dataset = element.dataset; const dataset = element.dataset;
@ -209,9 +215,12 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor, DS4Ite
} }
/** @override */ /** @override */
async _onDropItem(event: DragEvent, data: Parameters<typeof DS4Item.fromDropData>[0]): Promise<unknown> { protected async _onDropItem(
const item = await Item.fromDropData(data); event: DragEvent,
if (item && !this.actor.canOwnItemType(item.data.type as ItemType)) { data: { type: "Item" } & (DeepPartial<ActorSheet.OwnedItemData<DS4Actor>> | { pack: string } | { id: string }),
): Promise<boolean | undefined | ActorSheet.OwnedItemData<DS4Actor>> {
const item = ((await Item.fromDropData(data)) as unknown) as DS4Item;
if (item && !this.actor.canOwnItemType(item.data.type)) {
ui.notifications.warn( ui.notifications.warn(
game.i18n.format("DS4.WarningActorCannotOwnItem", { game.i18n.format("DS4.WarningActorCannotOwnItem", {
actorName: this.actor.name, actorName: this.actor.name,

View file

@ -1,11 +1,34 @@
import { DS4ActorSheet } from "./actor-sheet"; import { DS4ActorSheet } from "./actor-sheet";
/**
* The Sheet class for DS4 Character Actors
*/
export class DS4CharacterActorSheet extends DS4ActorSheet { export class DS4CharacterActorSheet extends DS4ActorSheet {
/** @override */ /** @override */
static get defaultOptions(): FormApplicationOptions { static get defaultOptions(): BaseEntitySheet.Options {
return mergeObject(super.defaultOptions, { const superDefaultOptions = super.defaultOptions;
return mergeObject(superDefaultOptions, {
classes: ["ds4", "sheet", "actor", "character"], classes: ["ds4", "sheet", "actor", "character"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }],
template: superDefaultOptions.template,
viewPermission: superDefaultOptions.viewPermission,
closeOnSubmit: superDefaultOptions.closeOnSubmit,
submitOnChange: superDefaultOptions.submitOnChange,
submitOnClose: superDefaultOptions.submitOnClose,
editable: superDefaultOptions.editable,
baseApplication: superDefaultOptions.baseApplication,
top: superDefaultOptions.top,
left: superDefaultOptions.left,
popOut: superDefaultOptions.popOut,
minimizable: superDefaultOptions.minimizable,
resizable: superDefaultOptions.resizable,
id: superDefaultOptions.id,
dragDrop: superDefaultOptions.dragDrop,
filters: superDefaultOptions.filters,
title: superDefaultOptions.title,
width: superDefaultOptions.width,
height: superDefaultOptions.height,
scrollY: superDefaultOptions.scrollY,
}); });
} }
} }

View file

@ -1,11 +1,34 @@
import { DS4ActorSheet } from "./actor-sheet"; import { DS4ActorSheet } from "./actor-sheet";
/**
* The Sheet class for DS4 Creature Actors
*/
export class DS4CreatureActorSheet extends DS4ActorSheet { export class DS4CreatureActorSheet extends DS4ActorSheet {
/** @override */ /** @override */
static get defaultOptions(): FormApplicationOptions { static get defaultOptions(): BaseEntitySheet.Options {
return mergeObject(super.defaultOptions, { const superDefaultOptions = super.defaultOptions;
return mergeObject(superDefaultOptions, {
classes: ["ds4", "sheet", "actor", "creature"], classes: ["ds4", "sheet", "actor", "creature"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "inventory" }],
template: superDefaultOptions.template,
viewPermission: superDefaultOptions.viewPermission,
closeOnSubmit: superDefaultOptions.closeOnSubmit,
submitOnChange: superDefaultOptions.submitOnChange,
submitOnClose: superDefaultOptions.submitOnClose,
editable: superDefaultOptions.editable,
baseApplication: superDefaultOptions.baseApplication,
top: superDefaultOptions.top,
left: superDefaultOptions.left,
popOut: superDefaultOptions.popOut,
minimizable: superDefaultOptions.minimizable,
resizable: superDefaultOptions.resizable,
id: superDefaultOptions.id,
dragDrop: superDefaultOptions.dragDrop,
filters: superDefaultOptions.filters,
title: superDefaultOptions.title,
width: superDefaultOptions.width,
height: superDefaultOptions.height,
scrollY: superDefaultOptions.scrollY,
}); });
} }
} }

View file

@ -0,0 +1,37 @@
/**
* Partition an array into two, following a predicate.
* @param input - The Array to split.
* @param predicate - The predicate by which to split.
* @returns A tuple of two arrays, the first one containing all elements from `input` that match the predicate, the second one containing those that do not.
*/
export function partition<T>(input: Array<T>, predicate: (v: T) => boolean): [T[], T[]] {
return input.reduce(
(p: [Array<T>, Array<T>], cur: T) => {
if (predicate(cur)) {
p[0].push(cur);
} else {
p[1].push(cur);
}
return p;
},
[[], []],
);
}
/**
* Zips two Arrays to an array of pairs of elements with corresponding indices. Excessive elements are dropped.
* @param a1 - First array to zip.
* @param a2 - Second array to zip.
*
* @typeParam T - Type of elements contained in `a1`.
* @typeParam U - Type of elements contained in `a2`.
*
* @returns The array of pairs that had the same index in their source array.
*/
export function zip<T, U>(a1: Array<T>, a2: Array<U>): Array<[T, U]> {
if (a1.length <= a2.length) {
return a1.map((e1, i) => [e1, a2[i]]);
} else {
return a2.map((e2, i) => [a1[i], e2]);
}
}

View file

@ -76,7 +76,7 @@ export const DS4 = {
}, },
/** /**
* Define the set of armor materials, used to determine if a characer may wear the armor without additional penalties * Define the set of armor materials, used to determine if a character may wear the armor without additional penalties
*/ */
armorMaterialTypes: { armorMaterialTypes: {
cloth: "DS4.ArmorMaterialTypeCloth", cloth: "DS4.ArmorMaterialTypeCloth",

View file

@ -1,4 +1,3 @@
// Import Modules
import { DS4Actor } from "./actor/actor"; import { DS4Actor } from "./actor/actor";
import { DS4Item } from "./item/item"; import { DS4Item } from "./item/item";
import { DS4ItemSheet } from "./item/item-sheet"; import { DS4ItemSheet } from "./item/item-sheet";
@ -21,29 +20,19 @@ Hooks.once("init", async function () {
migration, migration,
}; };
// Record configuration
CONFIG.DS4 = DS4; CONFIG.DS4 = DS4;
// Define custom Entity classes CONFIG.Actor.entityClass = DS4Actor;
CONFIG.Actor.entityClass = DS4Actor as typeof Actor; CONFIG.Item.entityClass = DS4Item;
CONFIG.Item.entityClass = DS4Item as typeof Item;
// Define localized type labels
CONFIG.Actor.typeLabels = DS4.i18n.actorTypes; CONFIG.Actor.typeLabels = DS4.i18n.actorTypes;
CONFIG.Item.typeLabels = DS4.i18n.itemTypes; CONFIG.Item.typeLabels = DS4.i18n.itemTypes;
// Configure Dice CONFIG.Dice.types.push(DS4Check);
CONFIG.Dice.types = [Die, DS4Check]; CONFIG.Dice.terms.s = DS4Check;
CONFIG.Dice.terms = {
c: Coin,
d: Die,
s: DS4Check,
};
// Register system settings
registerSystemSettings(); registerSystemSettings();
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true }); Actors.registerSheet("ds4", DS4CharacterActorSheet, { types: ["character"], makeDefault: true });
Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true }); Actors.registerSheet("ds4", DS4CreatureActorSheet, { types: ["creature"], makeDefault: true });
@ -69,31 +58,26 @@ async function registerHandlebarsPartials() {
"systems/ds4/templates/actor/partials/combat-values.hbs", "systems/ds4/templates/actor/partials/combat-values.hbs",
"systems/ds4/templates/actor/partials/profile.hbs", "systems/ds4/templates/actor/partials/profile.hbs",
"systems/ds4/templates/actor/partials/character-progression.hbs", "systems/ds4/templates/actor/partials/character-progression.hbs",
"systems/ds4/templates/actor/partials/special-creature-abilites-overview.hbs", "systems/ds4/templates/actor/partials/special-creature-abilities-overview.hbs",
"systems/ds4/templates/actor/partials/character-inventory.hbs", "systems/ds4/templates/actor/partials/character-inventory.hbs",
"systems/ds4/templates/actor/partials/creature-inventory.hbs", "systems/ds4/templates/actor/partials/creature-inventory.hbs",
]; ];
return loadTemplates(templatePaths); return loadTemplates(templatePaths);
} }
/* -------------------------------------------- */
/* Foundry VTT Setup */
/* -------------------------------------------- */
/** /**
* This function runs after game data has been requested and loaded from the servers, so entities exist * This function runs after game data has been requested and loaded from the servers, so entities exist
*/ */
Hooks.once("setup", function () { Hooks.once("setup", function () {
// Exclude some from sorting where the default order matters
const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"]; const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"];
// Localize and sort CONFIG objects // Localize and sort CONFIG objects
for (const o of Object.keys(CONFIG.DS4.i18n)) { for (const o of Object.keys(DS4.i18n)) {
const localized = Object.entries(CONFIG.DS4.i18n[o]).map((e) => { const localized = Object.entries(DS4.i18n[o]).map((e) => {
return [e[0], game.i18n.localize(e[1] as string)]; return [e[0], game.i18n.localize(e[1] as string)];
}); });
if (!noSort.includes(o)) localized.sort((a, b) => a[1].localeCompare(b[1])); if (!noSort.includes(o)) localized.sort((a, b) => a[1].localeCompare(b[1]));
CONFIG.DS4.i18n[o] = localized.reduce((obj, e) => { DS4.i18n[o] = localized.reduce((obj, e) => {
obj[e[0]] = e[1]; obj[e[0]] = e[1];
return obj; return obj;
}, {}); }, {});
@ -113,7 +97,7 @@ Hooks.once("ready", function () {
* (in this order). * (in this order).
*/ */
["renderApplication", "renderActorSheet", "renderItemSheet"].forEach((hookName: string) => { ["renderApplication", "renderActorSheet", "renderItemSheet"].forEach((hookName: string) => {
Hooks.on(hookName, (app: Dialog, html: JQueryStatic, data: any) => { Hooks.on(hookName, (app: Dialog, html: JQueryStatic) => {
$(html) $(html)
.find("input") .find("input")
.on("focus", (ev: JQuery.FocusEvent<HTMLInputElement>) => { .on("focus", (ev: JQuery.FocusEvent<HTMLInputElement>) => {

View file

@ -3,33 +3,53 @@ import { DS4 } from "../config";
export type ItemType = keyof typeof DS4.i18n.itemTypes; export type ItemType = keyof typeof DS4.i18n.itemTypes;
export type DS4ItemDataType = export type DS4ItemData =
| DS4Weapon | DS4WeaponData
| DS4Armor | DS4ArmorData
| DS4Shield | DS4ShieldData
| DS4Spell | DS4SpellData
| DS4Trinket | DS4TrinketData
| DS4Equipment | DS4EquipmentData
| DS4Talent | DS4TalentData
| DS4RacialAbility | DS4RacialAbilityData
| DS4Language | DS4LanguageData
| DS4Alphabet | DS4AlphabetData
| DS4SpecialCreatureAbility; | DS4SpecialCreatureAbilityData;
interface DS4ItemDataHelper<T, U extends ItemType> extends Item.Data<T> {
type: U;
}
type DS4WeaponData = DS4ItemDataHelper<DS4WeaponDataData, "weapon">;
type DS4ArmorData = DS4ItemDataHelper<DS4ArmorDataData, "armor">;
type DS4ShieldData = DS4ItemDataHelper<DS4ShieldDataData, "shield">;
type DS4SpellData = DS4ItemDataHelper<DS4SpellDataData, "spell">;
type DS4TrinketData = DS4ItemDataHelper<DS4TrinketDataData, "trinket">;
type DS4EquipmentData = DS4ItemDataHelper<DS4EquipmentDataData, "equipment">;
type DS4TalentData = DS4ItemDataHelper<DS4TalentDataData, "talent">;
type DS4RacialAbilityData = DS4ItemDataHelper<DS4RacialAbilityDataData, "racialAbility">;
type DS4LanguageData = DS4ItemDataHelper<DS4LanguageDataData, "language">;
type DS4AlphabetData = DS4ItemDataHelper<DS4AlphabetDataData, "alphabet">;
type DS4SpecialCreatureAbilityData = DS4ItemDataHelper<DS4SpecialCreatureAbilityDataData, "specialCreatureAbility">;
// types // types
interface DS4Weapon extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable { interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {
attackType: "melee" | "ranged" | "meleeRanged"; attackType: "melee" | "ranged" | "meleeRanged";
weaponBonus: number; weaponBonus: number;
opponentDefense: number; opponentDefense: number;
} }
export interface DS4Armor extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective { interface DS4ArmorDataData
extends DS4ItemDataDataBase,
DS4ItemDataDataPhysical,
DS4ItemDataDataEquipable,
DS4ItemDataDataProtective {
armorMaterialType: "cloth" | "leather" | "chain" | "plate"; armorMaterialType: "cloth" | "leather" | "chain" | "plate";
armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves"; armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
} }
export interface DS4Talent extends DS4ItemBase { interface DS4TalentDataData extends DS4ItemDataDataBase {
rank: DS4TalentRank; rank: DS4TalentRank;
} }
@ -37,7 +57,7 @@ interface DS4TalentRank extends ModifiableData<number> {
max: number; max: number;
} }
interface DS4Spell extends DS4ItemBase, DS4ItemEquipable { interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable {
spellType: "spellcasting" | "targetedSpellcasting"; spellType: "spellcasting" | "targetedSpellcasting";
bonus: string; bonus: string;
spellCategory: spellCategory:
@ -57,37 +77,41 @@ interface DS4Spell extends DS4ItemBase, DS4ItemEquipable {
scrollPrice: number; scrollPrice: number;
} }
export interface DS4Shield extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {} interface DS4ShieldDataData
interface DS4Trinket extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {} extends DS4ItemDataDataBase,
interface DS4Equipment extends DS4ItemBase, DS4ItemPhysical {} DS4ItemDataDataPhysical,
type DS4RacialAbility = DS4ItemBase; DS4ItemDataDataEquipable,
type DS4Language = DS4ItemBase; DS4ItemDataDataProtective {}
type DS4Alphabet = DS4ItemBase; interface DS4TrinketDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {}
interface DS4SpecialCreatureAbility extends DS4ItemBase { interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {}
type DS4RacialAbilityDataData = DS4ItemDataDataBase;
type DS4LanguageDataData = DS4ItemDataDataBase;
type DS4AlphabetDataData = DS4ItemDataDataBase;
interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase {
experiencePoints: number; experiencePoints: number;
} }
// templates // templates
interface DS4ItemBase { interface DS4ItemDataDataBase {
description: string; description: string;
} }
interface DS4ItemPhysical { interface DS4ItemDataDataPhysical {
quantity: number; quantity: number;
price: number; price: number;
availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "nowhere" | "unset"; availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "nowhere" | "unset";
storageLocation: string; storageLocation: string;
} }
export function isDS4ItemDataTypePhysical(input: DS4ItemDataType): boolean { export function isDS4ItemDataTypePhysical(input: DS4ItemData["data"]): boolean {
return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input; return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input;
} }
interface DS4ItemEquipable { interface DS4ItemDataDataEquipable {
equipped: boolean; equipped: boolean;
} }
interface DS4ItemProtective { interface DS4ItemDataDataProtective {
armorValue: number; armorValue: number;
} }

View file

@ -1,19 +1,36 @@
import { DS4 } from "../config";
import { DS4Item } from "./item"; import { DS4Item } from "./item";
import { DS4ItemDataType, isDS4ItemDataTypePhysical } from "./item-data"; import { isDS4ItemDataTypePhysical } from "./item-data";
/** /**
* Extend the basic ItemSheet with some very simple modifications * The Sheet class for DS4 Items
* @extends {ItemSheet}
*/ */
export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> { export class DS4ItemSheet extends ItemSheet<DS4Item> {
/** @override */ /** @override */
static get defaultOptions(): FormApplicationOptions { static get defaultOptions(): BaseEntitySheet.Options {
return mergeObject(super.defaultOptions, { const superDefaultOptions = super.defaultOptions;
return mergeObject(superDefaultOptions, {
width: 530, width: 530,
height: 400, height: 400,
classes: ["ds4", "sheet", "item"], classes: ["ds4", "sheet", "item"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }],
scrollY: [".sheet-body"], scrollY: [".sheet-body"],
template: superDefaultOptions.template,
viewPermission: superDefaultOptions.viewPermission,
closeOnSubmit: superDefaultOptions.closeOnSubmit,
submitOnChange: superDefaultOptions.submitOnChange,
submitOnClose: superDefaultOptions.submitOnClose,
editable: superDefaultOptions.editable,
baseApplication: superDefaultOptions.baseApplication,
top: superDefaultOptions.top,
left: superDefaultOptions.left,
popOut: superDefaultOptions.popOut,
minimizable: superDefaultOptions.minimizable,
resizable: superDefaultOptions.resizable,
id: superDefaultOptions.id,
dragDrop: superDefaultOptions.dragDrop,
filters: superDefaultOptions.filters,
title: superDefaultOptions.title,
}); });
} }
@ -23,13 +40,11 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
return `${path}/${this.item.data.type}-sheet.hbs`; return `${path}/${this.item.data.type}-sheet.hbs`;
} }
/* -------------------------------------------- */
/** @override */ /** @override */
getData(): ItemSheetData<DS4ItemDataType, DS4Item> { getData(): ItemSheet.Data<DS4Item> | Promise<ItemSheet.Data<DS4Item>> {
const data = { const data = {
...super.getData(), ...super.getData(),
config: CONFIG.DS4, config: DS4,
isOwned: this.item.isOwned, isOwned: this.item.isOwned,
actor: this.item.actor, actor: this.item.actor,
isPhysical: isDS4ItemDataTypePhysical(this.item.data.data), isPhysical: isDS4ItemDataTypePhysical(this.item.data.data),
@ -38,10 +53,8 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
return data; return data;
} }
/* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options: ApplicationPosition = {}): ApplicationPosition { setPosition(options: Partial<Application.Position> = {}): Application.Position {
const position = super.setPosition(options); const position = super.setPosition(options);
if ("find" in this.element) { if ("find" in this.element) {
const sheetBody = this.element.find(".sheet-body"); const sheetBody = this.element.find(".sheet-body");
@ -53,8 +66,6 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
return position; return position;
} }
/* -------------------------------------------- */
/** @override */ /** @override */
activateListeners(html: JQuery): void { activateListeners(html: JQuery): void {
super.activateListeners(html); super.activateListeners(html);
@ -66,9 +77,9 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
/** /**
* Handle management of ActiveEffects. * Handle management of ActiveEffects.
* @param {Event} event The originating click event * @param event - he originating click event
*/ */
private async _onManageActiveEffect(event: JQuery.ClickEvent): Promise<unknown> { protected async _onManageActiveEffect(event: JQuery.ClickEvent): Promise<unknown> {
event.preventDefault(); event.preventDefault();
if (this.item.isOwned) { if (this.item.isOwned) {
@ -92,7 +103,7 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
/** /**
* Create a new ActiveEffect for the item using default data. * Create a new ActiveEffect for the item using default data.
*/ */
private async _createActiveEffect(): Promise<unknown> { protected async _createActiveEffect(): Promise<ActiveEffect.Data> {
const label = `New Effect`; const label = `New Effect`;
const createData = { const createData = {
@ -102,7 +113,7 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
transfer: true, transfer: true,
}; };
const effect = await ActiveEffect.create(createData, this.item); const effect = ActiveEffect.create(createData, this.item);
return effect.create({}); return effect.create({});
} }
} }

View file

@ -1,28 +1,20 @@
import { DS4Actor } from "../actor/actor"; import { DS4ItemData } from "./item-data";
import { DS4ActorDataType } from "../actor/actor-data";
import { DS4ItemDataType, DS4Talent } from "./item-data";
/** /**
* Extend the basic Item with some very simple modifications. * The Item class for DS4
* @extends {Item}
*/ */
export class DS4Item extends Item<DS4ItemDataType, DS4ActorDataType, DS4Actor> { export class DS4Item extends Item<DS4ItemData> {
/** /**
* Augment the basic Item data model with additional dynamic data. * @override
*/ */
prepareData(): void { prepareData(): void {
super.prepareData(); super.prepareData();
this.prepareDerivedData(); this.prepareDerivedData();
// Get the Item's data
// const itemData = this.data;
// const actorData = this.actor ? this.actor.data : {};
// const data = itemData.data;
} }
prepareDerivedData(): void { prepareDerivedData(): void {
if (this.type === "talent") { if (this.data.type === "talent") {
const data = this.data.data as DS4Talent; const data = this.data.data;
data.rank.total = data.rank.base + data.rank.mod; data.rank.total = data.rank.base + data.rank.mod;
} }
} }

View file

@ -10,7 +10,7 @@ class DefaultCheckOptions implements DS4CheckFactoryOptions {
readonly rollMode: DS4RollMode = "roll"; readonly rollMode: DS4RollMode = "roll";
mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions { mergeWith(other: Partial<DS4CheckFactoryOptions>): DS4CheckFactoryOptions {
return { ...this, ...other } as DS4CheckFactoryOptions; return { ...this, ...other };
} }
} }
@ -34,7 +34,7 @@ class CheckFactory {
private checkOptions: DS4CheckFactoryOptions; private checkOptions: DS4CheckFactoryOptions;
async execute(): Promise<ChatMessage | unknown> { async execute(): Promise<ChatMessage | unknown> {
const rollCls: typeof Roll = CONFIG.Dice.rolls[0]; const rollCls = CONFIG.Dice.rolls[0];
const formula = [ const formula = [
"ds", "ds",
@ -75,8 +75,8 @@ class CheckFactory {
/** /**
* Asks the user for all unknown/necessary information and passes them on to perform a roll. * Asks the user for all unknown/necessary information and passes them on to perform a roll.
* @param targetValue The Check Target Number ("CTN") * @param targetValue - The Check Target Number ("CTN")
* @param options Options changing the behaviour of the roll and message. * @param options - Options changing the behavior of the roll and message.
*/ */
export async function createCheckRoll( export async function createCheckRoll(
targetValue: number, targetValue: number,
@ -131,17 +131,14 @@ async function askGmModifier(
const renderedHtml = await renderTemplate(usedTemplate, templateData); const renderedHtml = await renderTemplate(usedTemplate, templateData);
const dialogPromise = new Promise<HTMLFormElement>((resolve) => { const dialogPromise = new Promise<HTMLFormElement>((resolve) => {
new Dialog( new Dialog({
{
title: usedTitle, title: usedTitle,
close: () => {
// Don't do anything
},
content: renderedHtml, content: renderedHtml,
buttons: { buttons: {
ok: { ok: {
icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize("DS4.RollDialogOkButton"), label: game.i18n.localize("DS4.RollDialogOkButton"),
callback: (html: HTMLElement | JQuery) => { callback: (html) => {
if (!("jquery" in html)) { if (!("jquery" in html)) {
throw new Error( throw new Error(
game.i18n.format("DS4.ErrorUnexpectedHtmlType", { game.i18n.format("DS4.ErrorUnexpectedHtmlType", {
@ -156,16 +153,12 @@ async function askGmModifier(
}, },
}, },
cancel: { cancel: {
icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize("DS4.RollDialogCancelButton"), label: game.i18n.localize("DS4.RollDialogCancelButton"),
callback: () => {
// Don't do anything
},
}, },
}, },
default: "ok", default: "ok",
}, }).render(true);
{},
).render(true);
}); });
const dialogForm = await dialogPromise; const dialogForm = await dialogPromise;
return parseDialogFormData(dialogForm); return parseDialogFormData(dialogForm);
@ -173,7 +166,7 @@ async function askGmModifier(
/** /**
* Extracts Dialog data from the returned DOM element. * Extracts Dialog data from the returned DOM element.
* @param formData The filed dialog * @param formData - The filed dialog
*/ */
function parseDialogFormData(formData: HTMLFormElement): Partial<IntermediateGmModifierData> { function parseDialogFormData(formData: HTMLFormElement): Partial<IntermediateGmModifierData> {
return { return {

View file

@ -110,7 +110,7 @@ export class DS4Check extends DiceTerm {
let checked = 0; let checked = 0;
while (checked < intermediateResults.length) { while (checked < intermediateResults.length) {
const r = (intermediateResults as Array<RollResult>)[checked]; const r = intermediateResults[checked];
checked++; checked++;
if (!r.active) continue; if (!r.active) continue;

View file

@ -12,7 +12,7 @@ export class DefaultRollOptions implements RollOptions {
public slayingDiceRepetition = false; public slayingDiceRepetition = false;
mergeWith(other: Partial<RollOptions>): RollOptions { mergeWith(other: Partial<RollOptions>): RollOptions {
return { ...this, ...other } as RollOptions; return { ...this, ...other };
} }
} }

View file

@ -4,9 +4,9 @@ import { calculateRollResult, isDiceSwapNecessary, isSlayingDiceRepetition, sepa
/** /**
* Performs a roll against a check target number, e.g. for usage in battle, but not for herbs. * Performs a roll against a check target number, e.g. for usage in battle, but not for herbs.
* @param {number} checkTargetValue the final CTN, including all static modifiers. * @param checkTargetValue - the final CTN, including all static modifiers.
* @param {Partial<RollOptions>} rollOptions optional, final option override that affect the checks outcome, e.g. different values for crits or whether slaying dice are used. * @param rollOptions - optional, final option override that affect the checks outcome, e.g. different values for crits or whether slaying dice are used.
* @param {Array<number>} dice optional, pass already thrown dice that are used instead of rolling new ones. * @param dice - optional, pass already thrown dice that are used instead of rolling new ones.
*/ */
export function ds4roll( export function ds4roll(
checkTargetValue: number, checkTargetValue: number,
@ -27,11 +27,11 @@ export function ds4roll(
* This is not intended for direct usage. Use * This is not intended for direct usage. Use
* {@link ds4roll | the function that is not bound to an amount of Dice} instead. * {@link ds4roll | the function that is not bound to an amount of Dice} instead.
* *
* @param {number} checkTargetValue - The target value to check against. * @param checkTargetValue - The target value to check against.
* @param {RollOptions} rollOptions - Options that affect the checks outcome, e.g. different values for crits or whether slaying dice are used. * @param rollOptions - Options that affect the checks outcome, e.g. different values for crits or whether slaying dice are used.
* @param {Array<number>} dice optional, pass already thrown dice that are used instead of rolling new ones. * @param dice - optional, pass already thrown dice that are used instead of rolling new ones.
* *
* @returns {RollResult} An object containing detailed information on the roll result. * @returns An object containing detailed information on the roll result.
*/ */
export function rollCheckSingleDie( export function rollCheckSingleDie(
checkTargetValue: number, checkTargetValue: number,
@ -66,11 +66,11 @@ export function rollCheckSingleDie(
* This is not intended for direct usage. Use * This is not intended for direct usage. Use
* {@link ds4roll | the function that is not bound to an amount of Dice} instead. * {@link ds4roll | the function that is not bound to an amount of Dice} instead.
* *
* @param {number} targetValue- - The target value to check against. * @param targetValue - The target value to check against.
* @param {RollOptions} rollOptions - Options that affect the checks outcome, e.g. different values for crits or whether slaying dice are used. * @param rollOptions - Options that affect the checks outcome, e.g. different values for crits or whether slaying dice are used.
* @param {Array<number>} dice - Optional array of dice values to consider instead of rolling new ones. * @param dice - Optional array of dice values to consider instead of rolling new ones.
* *
* @returns {RollResult} An object containing detailed information on the roll result. * @returns An object containing detailed information on the roll result.
*/ */
export function rollCheckMultipleDice( export function rollCheckMultipleDice(
targetValue: number, targetValue: number,

View file

@ -1,3 +1,4 @@
import { partition, zip } from "../common/utils";
import { RollOptions } from "./roll-data"; import { RollOptions } from "./roll-data";
/** /**
@ -8,9 +9,9 @@ import { RollOptions } from "./roll-data";
* @private_remarks * @private_remarks
* This uses an internal implementation of a `partition` method. Don't let typescript fool you, it will tell you that a partition method is available for Arrays, but that one's imported globally from foundry's declarations and not available during the test stage! * This uses an internal implementation of a `partition` method. Don't let typescript fool you, it will tell you that a partition method is available for Arrays, but that one's imported globally from foundry's declarations and not available during the test stage!
* *
* @param {Array<number>} dice - The dice values. * @param dice - The dice values.
* @param {RollOptions} usedOptions - Options that affect the check's behaviour. * @param usedOptions - Options that affect the check's behavior.
* @returns {[Array<number>, Array<number>]} A tuple containing two arrays of dice values, the first one containing all critical hits, the second one containing all others. Both arrays are sorted descendingby value. * @returns A tuple containing two arrays of dice values, the first one containing all critical hits, the second one containing all others. Both arrays are sorted descending by value.
*/ */
export function separateCriticalHits(dice: Array<number>, usedOptions: RollOptions): CritsAndNonCrits { export function separateCriticalHits(dice: Array<number>, usedOptions: RollOptions): CritsAndNonCrits {
const [critSuccesses, otherRolls] = partition(dice, (v: number) => { const [critSuccesses, otherRolls] = partition(dice, (v: number) => {
@ -25,40 +26,19 @@ export function separateCriticalHits(dice: Array<number>, usedOptions: RollOptio
*/ */
type CritsAndNonCrits = [Array<number>, Array<number>]; type CritsAndNonCrits = [Array<number>, Array<number>];
/**
* Partition an array into two, following a predicate.
* @param {Array<T>} input The Array to split.
* @param {(T) => boolean} predicate The predicate by which to split.
* @returns A tuple of two arrays, the first one containing all elements from `input` that matched the predicate, the second one containing those that don't.
*/
// TODO: Move to generic utils method?
function partition<T>(input: Array<T>, predicate: (v: T) => boolean) {
return input.reduce(
(p: [Array<T>, Array<T>], cur: T) => {
if (predicate(cur)) {
p[0].push(cur);
} else {
p[1].push(cur);
}
return p;
},
[[], []],
);
}
/** /**
* Calculates if a critical success should be moved to the last position in order to maximize the check's result. * Calculates if a critical success should be moved to the last position in order to maximize the check's result.
* *
* @example * @example
* With regular dice rolling rules and a check target number of 31, the two dice 1 and 19 can get to a check result of 30. * With regular dice rolling rules and a check target number of 31, the two dice 1 and 19 can get to a check result of 30.
* This method would be called as follows: * This method would be called as follows:
* ``` * ```ts
* isDiceSwapNecessary([[1], [19]], 11) * isDiceSwapNecessary([[1], [19]], 11)
* ``` * ```
* *
* @param {[Array<number>, Array<number>]} critsAndNonCrits the dice values thrown. It is assumed that both critical successes and other rolls are sorted descending. * @param critsAndNonCrits - The dice values thrown. It is assumed that both critical successes and other rolls are sorted descending.
* @param {number} remainingTargetValue the target value for the last dice, that is the only one that can be less than 20. * @param remainingTargetValue - The target value for the last dice, that is the only one that can be less than 20.
* @returns {boolean} Bool indicating whether a critical success has to be used as the last dice. * @returns Bool indicating whether a critical success has to be used as the last dice.
*/ */
export function isDiceSwapNecessary( export function isDiceSwapNecessary(
[critSuccesses, otherRolls]: CritsAndNonCrits, [critSuccesses, otherRolls]: CritsAndNonCrits,
@ -81,7 +61,7 @@ export function isDiceSwapNecessary(
* *
* @internal * @internal
* *
* @param {RollOptions} opts the roll options to check against * @param opts - The roll options to check against
*/ */
export function isSlayingDiceRepetition(opts: RollOptions): boolean { export function isSlayingDiceRepetition(opts: RollOptions): boolean {
return opts.useSlayingDice && opts.slayingDiceRepetition; return opts.useSlayingDice && opts.slayingDiceRepetition;
@ -92,9 +72,9 @@ export function isSlayingDiceRepetition(opts: RollOptions): boolean {
* *
* @internal * @internal
* *
* @param assignedRollResults The dice values in the order of usage. * @param assignedRollResults - The dice values in the order of usage.
* @param remainderTargetValue Target value for the last dice (the only one differing from `20`). * @param remainderTargetValue - Target value for the last dice (the only one differing from `20`).
* @param rollOptions Config object containing options that change the way dice results are handled. * @param rollOptions - Config object containing options that change the way dice results are handled.
* *
* @returns {number} The total check value. * @returns {number} The total check value.
*/ */
@ -118,22 +98,3 @@ export function calculateRollResult(
.map(([v]) => v) .map(([v]) => v)
.reduce((a, b) => a + b); .reduce((a, b) => a + b);
} }
// TODO: Move to generic utils method?
/**
* Zips two Arrays to an array of pairs of elements with corresponding indices. Excessive elements are dropped.
* @param {Array<T>} a1 First array to zip.
* @param {Array<U>} a2 Second array to zip.
*
* @typeParam T - Type of elements contained in `a1`.
* @typeParam U - Type of elements contained in `a2`.
*
* @returns {Array<[T,U]>} The array of pairs that had the same index in their source array.
*/
function zip<T, U>(a1: Array<T>, a2: Array<U>): Array<[T, U]> {
if (a1.length <= a2.length) {
return a1.map((e1, i) => [e1, a2[i]]);
} else {
return a2.map((e2, i) => [a1[i], e2]);
}
}

View file

@ -64,7 +64,7 @@
{{> systems/ds4/templates/actor/partials/creature-inventory.hbs}} {{> systems/ds4/templates/actor/partials/creature-inventory.hbs}}
{{!-- Special Creature Abilities Tab --}} {{!-- Special Creature Abilities Tab --}}
{{> systems/ds4/templates/actor/partials/special-creature-abilites-overview.hbs}} {{> systems/ds4/templates/actor/partials/special-creature-abilities-overview.hbs}}
{{!-- Spells Tab --}} {{!-- Spells Tab --}}
{{> systems/ds4/templates/actor/partials/spells-overview.hbs}} {{> systems/ds4/templates/actor/partials/spells-overview.hbs}}

View file

@ -1,8 +1,12 @@
{ {
"compilerOptions": { "compilerOptions": {
"target": "ES2017", "target": "ES2020",
"lib": ["DOM", "ES6", "ES2017"], "lib": ["DOM", "ES2020"],
"types": ["foundry-pc-types"], "types": ["foundry-vtt-types"],
"esModuleInterop": true "esModuleInterop": true,
} "moduleResolution": "node",
"forceConsistentCasingInFileNames": true,
"strict": false
},
"include": ["src"]
} }