Compare commits
2 commits
3bc7c7819b
...
045991073b
Author | SHA1 | Date | |
---|---|---|---|
045991073b | |||
d659e4bed9 |
1590 changed files with 70381 additions and 70413 deletions
|
@ -3,13 +3,13 @@
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
parser: "@typescript-eslint/parser",
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
|
parserOptions: { ecmaVersion: 2020, sourceType: 'module' },
|
||||||
env: { browser: true },
|
env: { browser: true },
|
||||||
extends: ["plugin:@typescript-eslint/recommended", "prettier"],
|
extends: ['plugin:@typescript-eslint/recommended', 'prettier'],
|
||||||
plugins: ["@typescript-eslint"],
|
plugins: ['@typescript-eslint'],
|
||||||
overrides: [
|
overrides: [
|
||||||
{ files: ["./*.cjs"], rules: { "@typescript-eslint/no-var-requires": "off" } },
|
{ files: ['./*.cjs'], rules: { '@typescript-eslint/no-var-requires': 'off' } },
|
||||||
{ files: ["./spec/**/*"], env: { browser: false } },
|
{ files: ['./spec/**/*'], env: { browser: false } },
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
semi: true,
|
|
||||||
trailingComma: "all",
|
|
||||||
singleQuote: false,
|
|
||||||
printWidth: 120,
|
|
||||||
tabWidth: 4,
|
|
||||||
};
|
|
11
.prettierrc.js
Normal file
11
.prettierrc.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
export default {
|
||||||
|
semi: true,
|
||||||
|
trailingComma: 'all',
|
||||||
|
singleQuote: true,
|
||||||
|
printWidth: 120,
|
||||||
|
tabWidth: 2,
|
||||||
|
};
|
|
@ -2,4 +2,4 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
module.exports = { extends: ["@commitlint/config-conventional"] };
|
module.exports = { extends: ['@commitlint/config-conventional'] };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||||
"extends": ["config:base", ":automergeAll", ":automergeBranch", ":prHourlyLimitNone", ":prConcurrentLimitNone"],
|
"extends": ["config:base", ":automergeAll", ":automergePr", ":prHourlyLimitNone", ":prConcurrentLimitNone"],
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
"matchPackagePatterns": ["^@pixi"],
|
"matchPackagePatterns": ["^@pixi"],
|
||||||
|
|
|
@ -2,29 +2,29 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import styles from "@ironkinoko/rollup-plugin-styles";
|
import styles from '@ironkinoko/rollup-plugin-styles';
|
||||||
import { swc } from "rollup-plugin-swc3";
|
import { swc } from 'rollup-plugin-swc3';
|
||||||
|
|
||||||
import { copy } from "@guanghechen/rollup-plugin-copy";
|
import { copy } from '@guanghechen/rollup-plugin-copy';
|
||||||
|
|
||||||
import { distDirectory, name, sourceDirectory } from "./tools/const.js";
|
import { distDirectory, name, sourceDirectory } from './tools/const.js';
|
||||||
|
|
||||||
const staticFiles = [
|
const staticFiles = [
|
||||||
".reuse",
|
'.reuse',
|
||||||
"assets",
|
'assets',
|
||||||
"ATTRIBUTION.md",
|
'ATTRIBUTION.md',
|
||||||
"fonts",
|
'fonts',
|
||||||
"lang",
|
'lang',
|
||||||
"LICENSE.md",
|
'LICENSE.md',
|
||||||
"LICENSES",
|
'LICENSES',
|
||||||
"README.md",
|
'README.md',
|
||||||
"system.json.license",
|
'system.json.license',
|
||||||
"system.json",
|
'system.json',
|
||||||
"template.json.license",
|
'template.json.license',
|
||||||
"template.json",
|
'template.json',
|
||||||
"templates",
|
'templates',
|
||||||
];
|
];
|
||||||
const isProduction = process.env.NODE_ENV === "production";
|
const isProduction = process.env.NODE_ENV === 'production';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('rollup').RollupOptions}
|
* @type {import('rollup').RollupOptions}
|
||||||
|
@ -33,9 +33,9 @@ const config = {
|
||||||
input: { [name]: `${sourceDirectory}/${name}.ts` },
|
input: { [name]: `${sourceDirectory}/${name}.ts` },
|
||||||
output: {
|
output: {
|
||||||
dir: distDirectory,
|
dir: distDirectory,
|
||||||
format: "es",
|
format: 'es',
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
assetFileNames: "[name].[ext]",
|
assetFileNames: '[name].[ext]',
|
||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
swc({
|
swc({
|
||||||
|
@ -51,7 +51,7 @@ const config = {
|
||||||
sourceMaps: true,
|
sourceMaps: true,
|
||||||
}),
|
}),
|
||||||
styles({
|
styles({
|
||||||
mode: ["extract", `css/${name}.css`],
|
mode: ['extract', `css/${name}.css`],
|
||||||
url: false,
|
url: false,
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
minimize: isProduction,
|
minimize: isProduction,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
|
|
||||||
.ds4-actor-header {
|
.ds4-actor-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name-input[type="text"] {
|
&__name-input[type='text'] {
|
||||||
@include mixins.font-heading-upper;
|
@include mixins.font-heading-upper;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/colors";
|
@use '../../utils/colors';
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-actor-progression {
|
.ds4-actor-progression {
|
||||||
@include mixins.mark-invalid-or-disabled-input;
|
@include mixins.mark-invalid-or-disabled-input;
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-actor-properties {
|
.ds4-actor-properties {
|
||||||
@include mixins.mark-invalid-or-disabled-input;
|
@include mixins.mark-invalid-or-disabled-input;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
|
|
||||||
.ds4-check {
|
.ds4-check {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-combat-value {
|
.ds4-combat-value {
|
||||||
$size: 3.75rem;
|
$size: 3.75rem;
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
row-gap: 0.125em;
|
row-gap: 0.125em;
|
||||||
|
|
||||||
&__value {
|
&__value {
|
||||||
$combat-values-icons-path: "#{variables.$official-icons-path}/combat-values";
|
$combat-values-icons-path: '#{variables.$official-icons-path}/combat-values';
|
||||||
@include mixins.centered-content;
|
@include mixins.centered-content;
|
||||||
|
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
@ -26,28 +26,28 @@
|
||||||
width: $size;
|
width: $size;
|
||||||
|
|
||||||
&--hitPoints {
|
&--hitPoints {
|
||||||
background-image: url("#{$combat-values-icons-path}/hit-points.png");
|
background-image: url('#{$combat-values-icons-path}/hit-points.png');
|
||||||
}
|
}
|
||||||
&--defense {
|
&--defense {
|
||||||
background-image: url("#{$combat-values-icons-path}/defense.png");
|
background-image: url('#{$combat-values-icons-path}/defense.png');
|
||||||
}
|
}
|
||||||
&--initiative {
|
&--initiative {
|
||||||
background-image: url("#{$combat-values-icons-path}/initiative.png");
|
background-image: url('#{$combat-values-icons-path}/initiative.png');
|
||||||
}
|
}
|
||||||
&--movement {
|
&--movement {
|
||||||
background-image: url("#{$combat-values-icons-path}/movement-rate.png");
|
background-image: url('#{$combat-values-icons-path}/movement-rate.png');
|
||||||
}
|
}
|
||||||
&--meleeAttack {
|
&--meleeAttack {
|
||||||
background-image: url("#{$combat-values-icons-path}/melee-attack.png");
|
background-image: url('#{$combat-values-icons-path}/melee-attack.png');
|
||||||
}
|
}
|
||||||
&--rangedAttack {
|
&--rangedAttack {
|
||||||
background-image: url("#{$combat-values-icons-path}/ranged-attack.png");
|
background-image: url('#{$combat-values-icons-path}/ranged-attack.png');
|
||||||
}
|
}
|
||||||
&--spellcasting {
|
&--spellcasting {
|
||||||
background-image: url("#{$combat-values-icons-path}/spellcasting.png");
|
background-image: url('#{$combat-values-icons-path}/spellcasting.png');
|
||||||
}
|
}
|
||||||
&--targetedSpellcasting {
|
&--targetedSpellcasting {
|
||||||
background-image: url("#{$combat-values-icons-path}/targeted-spellcasting.png");
|
background-image: url('#{$combat-values-icons-path}/targeted-spellcasting.png');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-combat-values {
|
.ds4-combat-values {
|
||||||
border-bottom: variables.$border-groove;
|
border-bottom: variables.$border-groove;
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/colors";
|
@use '../../utils/colors';
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-core-value {
|
.ds4-core-value {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/colors";
|
@use '../../utils/colors';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-core-values {
|
.ds4-core-values {
|
||||||
column-gap: 0.5em;
|
column-gap: 0.5em;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-currency {
|
.ds4-currency {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/colors";
|
@use '../../utils/colors';
|
||||||
|
|
||||||
// Needs to be nested in .dice-roll to win against foundry's style.css with respect to specificity
|
// Needs to be nested in .dice-roll to win against foundry's style.css with respect to specificity
|
||||||
.dice-roll .ds4-dice-total {
|
.dice-roll .ds4-dice-total {
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/colors";
|
@use '../../utils/colors';
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
|
|
||||||
.ds4-item-header {
|
.ds4-item-header {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
@ -39,7 +39,7 @@
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__name-input[type="text"] {
|
&__name-input[type='text'] {
|
||||||
@include mixins.font-heading-upper;
|
@include mixins.font-heading-upper;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-item-properties {
|
.ds4-item-properties {
|
||||||
@include mixins.mark-invalid-or-disabled-input;
|
@include mixins.mark-invalid-or-disabled-input;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&__checkbox[type="checkbox"] {
|
&__checkbox[type='checkbox'] {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/mixins";
|
@use '../../utils/mixins';
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-embedded-document-list {
|
.ds4-embedded-document-list {
|
||||||
@include mixins.mark-invalid-or-disabled-input;
|
@include mixins.mark-invalid-or-disabled-input;
|
||||||
|
@ -105,8 +105,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&__editable {
|
&__editable {
|
||||||
&[type="text"],
|
&[type='text'],
|
||||||
&[type="number"] {
|
&[type='number'] {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&--checkbox {
|
&--checkbox {
|
||||||
&[type="checkbox"] {
|
&[type='checkbox'] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "../../utils/variables";
|
@use '../../utils/variables';
|
||||||
|
|
||||||
.ds4-sheet-tab-nav {
|
.ds4-sheet-tab-nav {
|
||||||
border-bottom: variables.$border-groove;
|
border-bottom: variables.$border-groove;
|
||||||
|
|
|
@ -7,43 +7,43 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// global
|
// global
|
||||||
@use "global/accessibility";
|
@use 'global/accessibility';
|
||||||
@use "global/fonts";
|
@use 'global/fonts';
|
||||||
@use "global/utils";
|
@use 'global/utils';
|
||||||
|
|
||||||
// shared
|
// shared
|
||||||
@use "components/shared/add_button";
|
@use 'components/shared/add_button';
|
||||||
@use "components/shared/control_button_group";
|
@use 'components/shared/control_button_group';
|
||||||
@use "components/shared/checkbox_grid";
|
@use 'components/shared/checkbox_grid';
|
||||||
@use "components/shared/editor";
|
@use 'components/shared/editor';
|
||||||
@use "components/shared/embedded_document_list";
|
@use 'components/shared/embedded_document_list';
|
||||||
@use "components/shared/form_group";
|
@use 'components/shared/form_group';
|
||||||
@use "components/shared/rollable_image";
|
@use 'components/shared/rollable_image';
|
||||||
@use "components/shared/sheet_body";
|
@use 'components/shared/sheet_body';
|
||||||
@use "components/shared/sheet_form";
|
@use 'components/shared/sheet_form';
|
||||||
@use "components/shared/sheet_tab_nav";
|
@use 'components/shared/sheet_tab_nav';
|
||||||
@use "components/shared/sheet_tab";
|
@use 'components/shared/sheet_tab';
|
||||||
|
|
||||||
// actor
|
// actor
|
||||||
@use "components/actor/actor_header";
|
@use 'components/actor/actor_header';
|
||||||
@use "components/actor/actor_progression";
|
@use 'components/actor/actor_progression';
|
||||||
@use "components/actor/actor_properties";
|
@use 'components/actor/actor_properties';
|
||||||
@use "components/actor/actor_sheet";
|
@use 'components/actor/actor_sheet';
|
||||||
@use "components/actor/biography";
|
@use 'components/actor/biography';
|
||||||
@use "components/actor/check";
|
@use 'components/actor/check';
|
||||||
@use "components/actor/checks";
|
@use 'components/actor/checks';
|
||||||
@use "components/actor/combat_value";
|
@use 'components/actor/combat_value';
|
||||||
@use "components/actor/combat_values";
|
@use 'components/actor/combat_values';
|
||||||
@use "components/actor/core_value";
|
@use 'components/actor/core_value';
|
||||||
@use "components/actor/core_values";
|
@use 'components/actor/core_values';
|
||||||
@use "components/actor/currency";
|
@use 'components/actor/currency';
|
||||||
@use "components/actor/description";
|
@use 'components/actor/description';
|
||||||
@use "components/actor/profile";
|
@use 'components/actor/profile';
|
||||||
|
|
||||||
// item
|
// item
|
||||||
@use "components/item/item_header";
|
@use 'components/item/item_header';
|
||||||
@use "components/item/item_properties";
|
@use 'components/item/item_properties';
|
||||||
@use "components/item/item_sheet";
|
@use 'components/item/item_sheet';
|
||||||
|
|
||||||
// dice
|
// dice
|
||||||
@use "components/dice/dice_total";
|
@use 'components/dice/dice_total';
|
||||||
|
|
|
@ -6,55 +6,55 @@
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: "Lora";
|
font-family: 'Lora';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src:
|
src:
|
||||||
local("Lora"),
|
local('Lora'),
|
||||||
url("../fonts/Lora/Lora.woff") format("woff");
|
url('../fonts/Lora/Lora.woff') format('woff');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: "Lora";
|
font-family: 'Lora';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src:
|
src:
|
||||||
local("Lora"),
|
local('Lora'),
|
||||||
url("../fonts/Lora/Lora-Bold.woff") format("woff");
|
url('../fonts/Lora/Lora-Bold.woff') format('woff');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: "Lora";
|
font-family: 'Lora';
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src:
|
src:
|
||||||
local("Lora"),
|
local('Lora'),
|
||||||
url("../fonts/Lora/Lora-Italic.woff") format("woff");
|
url('../fonts/Lora/Lora-Italic.woff') format('woff');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: "Lora";
|
font-family: 'Lora';
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
src:
|
src:
|
||||||
local("Lora"),
|
local('Lora'),
|
||||||
url("../fonts/Lora/Lora-BoldItalic.woff") format("woff");
|
url('../fonts/Lora/Lora-BoldItalic.woff') format('woff');
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-display: swap;
|
font-display: swap;
|
||||||
font-family: "Wood Stamp";
|
font-family: 'Wood Stamp';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
src:
|
src:
|
||||||
local("Wood Stamp"),
|
local('Wood Stamp'),
|
||||||
url("../fonts/Woodstamp/Woodstamp.woff") format("woff");
|
url('../fonts/Woodstamp/Woodstamp.woff') format('woff');
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--ds4-font-primary: Lora, serif;
|
--ds4-font-primary: Lora, serif;
|
||||||
--ds4-font-heading: "Wood Stamp", sans-serif;
|
--ds4-font-heading: 'Wood Stamp', sans-serif;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "./colors";
|
@use './colors';
|
||||||
|
|
||||||
@mixin centered-content {
|
@mixin centered-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* SPDX-License-Identifier: MIT
|
* SPDX-License-Identifier: MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@use "./colors";
|
@use './colors';
|
||||||
|
|
||||||
$padding-sm: 5px;
|
$padding-sm: 5px;
|
||||||
$padding-md: 10px;
|
$padding-md: 10px;
|
||||||
|
@ -13,6 +13,6 @@ $margin-sm: $padding-sm;
|
||||||
$margin-md: $padding-md;
|
$margin-md: $padding-md;
|
||||||
$margin-lg: $padding-lg;
|
$margin-lg: $padding-lg;
|
||||||
|
|
||||||
$official-icons-path: "../assets/icons/official";
|
$official-icons-path: '../assets/icons/official';
|
||||||
|
|
||||||
$border-groove: 2px groove colors.$c-border-groove;
|
$border-groove: 2px groove colors.$c-border-groove;
|
||||||
|
|
|
@ -3,38 +3,38 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { evaluateCheck } from "../../src/dice/check-evaluation";
|
import { evaluateCheck } from '../../src/dice/check-evaluation';
|
||||||
|
|
||||||
describe("evaluateCheck with no dice", () => {
|
describe('evaluateCheck with no dice', () => {
|
||||||
it("should throw an error.", () => {
|
it('should throw an error.', () => {
|
||||||
expect(() => evaluateCheck([], 10)).toThrow("Invalid number of dice.");
|
expect(() => evaluateCheck([], 10)).toThrow('Invalid number of dice.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with more dice than required by the checkTargetNumber", () => {
|
describe('evaluateCheck with more dice than required by the checkTargetNumber', () => {
|
||||||
it("should throw an error.", () => {
|
it('should throw an error.', () => {
|
||||||
expect(() => evaluateCheck([10, 10], 10)).toThrow("Invalid number of dice.");
|
expect(() => evaluateCheck([10, 10], 10)).toThrow('Invalid number of dice.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with less dice than required by the checkTargetNumber", () => {
|
describe('evaluateCheck with less dice than required by the checkTargetNumber', () => {
|
||||||
it("should throw an error.", () => {
|
it('should throw an error.', () => {
|
||||||
expect(() => evaluateCheck([10], 21)).toThrow("Invalid number of dice.");
|
expect(() => evaluateCheck([10], 21)).toThrow('Invalid number of dice.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with a single die", () => {
|
describe('evaluateCheck with a single die', () => {
|
||||||
it("should assign the checkTargetNumber to the single die and be successful.", () => {
|
it('should assign the checkTargetNumber to the single die and be successful.', () => {
|
||||||
expect(evaluateCheck([4], 12)).toEqual([{ result: 4, checkTargetNumber: 12, active: true, discarded: false }]);
|
expect(evaluateCheck([4], 12)).toEqual([{ result: 4, checkTargetNumber: 12, active: true, discarded: false }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber to the single die on upper edge case and be successful.", () => {
|
it('should assign the checkTargetNumber to the single die on upper edge case and be successful.', () => {
|
||||||
expect(evaluateCheck([4], 4)).toEqual([{ result: 4, checkTargetNumber: 4, active: true, discarded: false }]);
|
expect(evaluateCheck([4], 4)).toEqual([{ result: 4, checkTargetNumber: 4, active: true, discarded: false }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber to the single die on lower edge case not be successful.", () => {
|
it('should assign the checkTargetNumber to the single die on lower edge case not be successful.', () => {
|
||||||
expect(evaluateCheck([5], 4)).toEqual([{ result: 5, checkTargetNumber: 4, active: false, discarded: true }]);
|
expect(evaluateCheck([5], 4)).toEqual([{ result: 5, checkTargetNumber: 4, active: false, discarded: true }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -54,48 +54,44 @@ describe("evaluateCheck with a single die", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is 0 and coup on 1", () => {
|
it('should roll a die even when the checkTargetNumber is 0 and coup on 1', () => {
|
||||||
expect(evaluateCheck([1], 0)).toEqual([
|
expect(evaluateCheck([1], 0)).toEqual([
|
||||||
{ result: 1, checkTargetNumber: 0, active: true, discarded: false, success: true, count: 0 },
|
{ result: 1, checkTargetNumber: 0, active: true, discarded: false, success: true, count: 0 },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is 0 and fail on values > 1 and < 20", () => {
|
it('should roll a die even when the checkTargetNumber is 0 and fail on values > 1 and < 20', () => {
|
||||||
for (let i = 2; i < 20; i++) {
|
for (let i = 2; i < 20; i++) {
|
||||||
expect(evaluateCheck([i], 0)).toEqual([
|
expect(evaluateCheck([i], 0)).toEqual([{ result: i, checkTargetNumber: 0, active: false, discarded: true }]);
|
||||||
{ result: i, checkTargetNumber: 0, active: false, discarded: true },
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is 0 and fumble on 20", () => {
|
it('should roll a die even when the checkTargetNumber is 0 and fumble on 20', () => {
|
||||||
expect(evaluateCheck([20], 0)).toEqual([
|
expect(evaluateCheck([20], 0)).toEqual([
|
||||||
{ result: 20, checkTargetNumber: 0, active: false, discarded: true, failure: true },
|
{ result: 20, checkTargetNumber: 0, active: false, discarded: true, failure: true },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is < 0 and coup on 1", () => {
|
it('should roll a die even when the checkTargetNumber is < 0 and coup on 1', () => {
|
||||||
expect(evaluateCheck([1], -1)).toEqual([
|
expect(evaluateCheck([1], -1)).toEqual([
|
||||||
{ result: 1, checkTargetNumber: -1, active: true, discarded: false, success: true, count: -1 },
|
{ result: 1, checkTargetNumber: -1, active: true, discarded: false, success: true, count: -1 },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is < 0 and fail on values > 1 and < 20", () => {
|
it('should roll a die even when the checkTargetNumber is < 0 and fail on values > 1 and < 20', () => {
|
||||||
for (let i = 2; i < 20; i++) {
|
for (let i = 2; i < 20; i++) {
|
||||||
expect(evaluateCheck([i], -1)).toEqual([
|
expect(evaluateCheck([i], -1)).toEqual([{ result: i, checkTargetNumber: -1, active: false, discarded: true }]);
|
||||||
{ result: i, checkTargetNumber: -1, active: false, discarded: true },
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should roll a die even when the checkTargetNumber is < 0 and fumble on 20", () => {
|
it('should roll a die even when the checkTargetNumber is < 0 and fumble on 20', () => {
|
||||||
expect(evaluateCheck([20], -1)).toEqual([
|
expect(evaluateCheck([20], -1)).toEqual([
|
||||||
{ result: 20, checkTargetNumber: -1, active: false, discarded: true, failure: true },
|
{ result: 20, checkTargetNumber: -1, active: false, discarded: true, failure: true },
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with a single die and coup / fumble modification", () => {
|
describe('evaluateCheck with a single die and coup / fumble modification', () => {
|
||||||
const maximumCoupResult = 2;
|
const maximumCoupResult = 2;
|
||||||
const minimumFumbleResult = 19;
|
const minimumFumbleResult = 19;
|
||||||
|
|
||||||
|
@ -185,7 +181,7 @@ describe("evaluateCheck with a single die and coup / fumble modification", () =>
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with multiple dice", () => {
|
describe('evaluateCheck with multiple dice', () => {
|
||||||
it("should assign the checkTargetNumber for the last sub check to the lowest non coup, even if the first is '20'.", () => {
|
it("should assign the checkTargetNumber for the last sub check to the lowest non coup, even if the first is '20'.", () => {
|
||||||
expect(evaluateCheck([20, 6, 15], 48)).toEqual([
|
expect(evaluateCheck([20, 6, 15], 48)).toEqual([
|
||||||
{ result: 20, checkTargetNumber: 20, active: true, discarded: false, failure: true },
|
{ result: 20, checkTargetNumber: 20, active: true, discarded: false, failure: true },
|
||||||
|
@ -194,7 +190,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to the first coup if there are only coups.", () => {
|
it('should assign the checkTargetNumber for the last sub check to the first coup if there are only coups.', () => {
|
||||||
expect(evaluateCheck([1, 1, 1], 48)).toEqual([
|
expect(evaluateCheck([1, 1, 1], 48)).toEqual([
|
||||||
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
||||||
{ result: 1, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
{ result: 1, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
||||||
|
@ -202,7 +198,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to the first lowest die, even if it is higher than that value.", () => {
|
it('should assign the checkTargetNumber for the last sub check to the first lowest die, even if it is higher than that value.', () => {
|
||||||
expect(evaluateCheck([15, 15, 15], 48)).toEqual([
|
expect(evaluateCheck([15, 15, 15], 48)).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
|
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
|
@ -210,7 +206,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to the first coup if its sum with the lowest non coup is high enough.", () => {
|
it('should assign the checkTargetNumber for the last sub check to the first coup if its sum with the lowest non coup is high enough.', () => {
|
||||||
expect(evaluateCheck([15, 15, 1], 48)).toEqual([
|
expect(evaluateCheck([15, 15, 1], 48)).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
|
@ -226,7 +222,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to properly maximize the result when all dice are successes.", () => {
|
it('should assign the checkTargetNumber for the last sub check to properly maximize the result when all dice are successes.', () => {
|
||||||
expect(evaluateCheck([15, 4, 12], 46)).toEqual([
|
expect(evaluateCheck([15, 4, 12], 46)).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
{ result: 4, checkTargetNumber: 6, active: true, discarded: false },
|
{ result: 4, checkTargetNumber: 6, active: true, discarded: false },
|
||||||
|
@ -234,7 +230,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to properly maximize the result when one dice is a failure.", () => {
|
it('should assign the checkTargetNumber for the last sub check to properly maximize the result when one dice is a failure.', () => {
|
||||||
expect(evaluateCheck([15, 8, 12], 46)).toEqual([
|
expect(evaluateCheck([15, 8, 12], 46)).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
{ result: 8, checkTargetNumber: 6, active: false, discarded: true },
|
{ result: 8, checkTargetNumber: 6, active: false, discarded: true },
|
||||||
|
@ -264,7 +260,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to properly maximize the result when there is more than one coup and a coup is used for the last sub CTN", () => {
|
it('should assign the checkTargetNumber for the last sub check to properly maximize the result when there is more than one coup and a coup is used for the last sub CTN', () => {
|
||||||
expect(evaluateCheck([1, 1, 15], 48)).toEqual([
|
expect(evaluateCheck([1, 1, 15], 48)).toEqual([
|
||||||
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
||||||
{ result: 1, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
{ result: 1, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
||||||
|
@ -273,7 +269,7 @@ describe("evaluateCheck with multiple dice", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("evaluateCheck with multiple dice and coup / fumble modification", () => {
|
describe('evaluateCheck with multiple dice and coup / fumble modification', () => {
|
||||||
it("should assign the checkTargetNumber for the last sub check to the lowest non coup and fumble if the first is '19'.", () => {
|
it("should assign the checkTargetNumber for the last sub check to the lowest non coup and fumble if the first is '19'.", () => {
|
||||||
expect(evaluateCheck([19, 15, 6], 48, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
expect(evaluateCheck([19, 15, 6], 48, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
||||||
{ result: 19, checkTargetNumber: 20, active: true, discarded: false, failure: true },
|
{ result: 19, checkTargetNumber: 20, active: true, discarded: false, failure: true },
|
||||||
|
@ -290,7 +286,7 @@ describe("evaluateCheck with multiple dice and coup / fumble modification", () =
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to the first lowest die, even if it is higher than that value.", () => {
|
it('should assign the checkTargetNumber for the last sub check to the first lowest die, even if it is higher than that value.', () => {
|
||||||
expect(evaluateCheck([15, 15, 15], 48, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
expect(evaluateCheck([15, 15, 15], 48, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
|
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
|
@ -322,7 +318,7 @@ describe("evaluateCheck with multiple dice and coup / fumble modification", () =
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to properly maximize the result when all dice are successes.", () => {
|
it('should assign the checkTargetNumber for the last sub check to properly maximize the result when all dice are successes.', () => {
|
||||||
expect(evaluateCheck([15, 4, 12], 46, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
expect(evaluateCheck([15, 4, 12], 46, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
{ result: 4, checkTargetNumber: 6, active: true, discarded: false },
|
{ result: 4, checkTargetNumber: 6, active: true, discarded: false },
|
||||||
|
@ -330,7 +326,7 @@ describe("evaluateCheck with multiple dice and coup / fumble modification", () =
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should assign the checkTargetNumber for the last sub check to properly maximize the result when one dice is a failure.", () => {
|
it('should assign the checkTargetNumber for the last sub check to properly maximize the result when one dice is a failure.', () => {
|
||||||
expect(evaluateCheck([15, 8, 12], 46, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
expect(evaluateCheck([15, 8, 12], 46, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
|
||||||
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
|
||||||
{ result: 8, checkTargetNumber: 6, active: false, discarded: true },
|
{ result: 8, checkTargetNumber: 6, active: false, discarded: true },
|
||||||
|
@ -368,7 +364,7 @@ describe("evaluateCheck with multiple dice and coup / fumble modification", () =
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should use all the dice if they are coups, even if they are higher than the checkTargetNumber", () => {
|
it('should use all the dice if they are coups, even if they are higher than the checkTargetNumber', () => {
|
||||||
expect(evaluateCheck([18, 19, 17], 48, { maximumCoupResult: 19 })).toEqual([
|
expect(evaluateCheck([18, 19, 17], 48, { maximumCoupResult: 19 })).toEqual([
|
||||||
{ result: 18, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
{ result: 18, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
|
||||||
{ result: 19, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
{ result: 19, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { calculateSpellPrice } from "../../../../src/documents/item/spell/calculate-spell-price";
|
import { calculateSpellPrice } from '../../../../src/documents/item/spell/calculate-spell-price';
|
||||||
|
|
||||||
import type { CooldownDuration, DS4SpellDataSourceData } from "../../../../src/documents/item/spell/spell-data-source";
|
import type { CooldownDuration, DS4SpellDataSourceData } from '../../../../src/documents/item/spell/spell-data-source';
|
||||||
|
|
||||||
const defaultData: DS4SpellDataSourceData = {
|
const defaultData: DS4SpellDataSourceData = {
|
||||||
description: "",
|
description: '',
|
||||||
equipped: false,
|
equipped: false,
|
||||||
spellType: "spellcasting",
|
spellType: 'spellcasting',
|
||||||
spellModifier: {
|
spellModifier: {
|
||||||
numerical: 0,
|
numerical: 0,
|
||||||
complex: "",
|
complex: '',
|
||||||
},
|
},
|
||||||
allowsDefense: false,
|
allowsDefense: false,
|
||||||
spellGroups: {
|
spellGroups: {
|
||||||
|
@ -37,18 +37,18 @@ const defaultData: DS4SpellDataSourceData = {
|
||||||
area: false,
|
area: false,
|
||||||
},
|
},
|
||||||
maxDistance: {
|
maxDistance: {
|
||||||
value: "",
|
value: '',
|
||||||
unit: "meter",
|
unit: 'meter',
|
||||||
},
|
},
|
||||||
effectRadius: {
|
effectRadius: {
|
||||||
value: "",
|
value: '',
|
||||||
unit: "meter",
|
unit: 'meter',
|
||||||
},
|
},
|
||||||
duration: {
|
duration: {
|
||||||
value: "",
|
value: '',
|
||||||
unit: "custom",
|
unit: 'custom',
|
||||||
},
|
},
|
||||||
cooldownDuration: "0r",
|
cooldownDuration: '0r',
|
||||||
minimumLevels: {
|
minimumLevels: {
|
||||||
healer: null,
|
healer: null,
|
||||||
wizard: null,
|
wizard: null,
|
||||||
|
@ -62,12 +62,12 @@ type TestCase = {
|
||||||
};
|
};
|
||||||
|
|
||||||
type CombinedTestCase = {
|
type CombinedTestCase = {
|
||||||
minimumLevels: DS4SpellDataSourceData["minimumLevels"];
|
minimumLevels: DS4SpellDataSourceData['minimumLevels'];
|
||||||
expected: number | null;
|
expected: number | null;
|
||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const testCases: Record<keyof DS4SpellDataSourceData["minimumLevels"], TestCase[]> = {
|
const testCases: Record<keyof DS4SpellDataSourceData['minimumLevels'], TestCase[]> = {
|
||||||
healer: [
|
healer: [
|
||||||
{ minimumLevel: null, expected: null },
|
{ minimumLevel: null, expected: null },
|
||||||
{ minimumLevel: 1, expected: 10 },
|
{ minimumLevel: 1, expected: 10 },
|
||||||
|
@ -150,9 +150,7 @@ function buildCombinedTestCases(): CombinedTestCase[] {
|
||||||
for (const sorcererTestCase of testCases.sorcerer.filter(isRelevantPermutationTestCase)) {
|
for (const sorcererTestCase of testCases.sorcerer.filter(isRelevantPermutationTestCase)) {
|
||||||
for (const wizardTestCase of testCases.wizard.filter(isRelevantPermutationTestCase)) {
|
for (const wizardTestCase of testCases.wizard.filter(isRelevantPermutationTestCase)) {
|
||||||
const expected =
|
const expected =
|
||||||
healerTestCase.expected !== null ||
|
healerTestCase.expected !== null || sorcererTestCase.expected !== null || wizardTestCase.expected !== null
|
||||||
sorcererTestCase.expected !== null ||
|
|
||||||
wizardTestCase.expected !== null
|
|
||||||
? Math.min(
|
? Math.min(
|
||||||
healerTestCase.expected ?? Infinity,
|
healerTestCase.expected ?? Infinity,
|
||||||
sorcererTestCase.expected ?? Infinity,
|
sorcererTestCase.expected ?? Infinity,
|
||||||
|
@ -177,7 +175,7 @@ function buildCombinedTestCases(): CombinedTestCase[] {
|
||||||
// single test cases
|
// single test cases
|
||||||
const isRelevantSingleTestCase = (t: TestCase) => t.minimumLevel !== null;
|
const isRelevantSingleTestCase = (t: TestCase) => t.minimumLevel !== null;
|
||||||
|
|
||||||
for (const spellCasterClass of ["healer", "sorcerer", "wizard"] as const) {
|
for (const spellCasterClass of ['healer', 'sorcerer', 'wizard'] as const) {
|
||||||
for (const testCase of testCases[spellCasterClass].filter(isRelevantSingleTestCase)) {
|
for (const testCase of testCases[spellCasterClass].filter(isRelevantSingleTestCase)) {
|
||||||
const minimumLevels = {
|
const minimumLevels = {
|
||||||
...defaultData.minimumLevels,
|
...defaultData.minimumLevels,
|
||||||
|
@ -195,20 +193,20 @@ function buildCombinedTestCases(): CombinedTestCase[] {
|
||||||
return combinedTestCases;
|
return combinedTestCases;
|
||||||
}
|
}
|
||||||
|
|
||||||
describe("calculateSpellPrice", () => {
|
describe('calculateSpellPrice', () => {
|
||||||
const cooldownDurations: { cooldownDuration: CooldownDuration; factor: number }[] = [
|
const cooldownDurations: { cooldownDuration: CooldownDuration; factor: number }[] = [
|
||||||
{ cooldownDuration: "0r", factor: 1 },
|
{ cooldownDuration: '0r', factor: 1 },
|
||||||
{ cooldownDuration: "1r", factor: 1 },
|
{ cooldownDuration: '1r', factor: 1 },
|
||||||
{ cooldownDuration: "2r", factor: 1 },
|
{ cooldownDuration: '2r', factor: 1 },
|
||||||
{ cooldownDuration: "5r", factor: 1 },
|
{ cooldownDuration: '5r', factor: 1 },
|
||||||
{ cooldownDuration: "10r", factor: 1 },
|
{ cooldownDuration: '10r', factor: 1 },
|
||||||
{ cooldownDuration: "100r", factor: 1 },
|
{ cooldownDuration: '100r', factor: 1 },
|
||||||
{ cooldownDuration: "1d", factor: 2 },
|
{ cooldownDuration: '1d', factor: 2 },
|
||||||
{ cooldownDuration: "d20d", factor: 3 },
|
{ cooldownDuration: 'd20d', factor: 3 },
|
||||||
];
|
];
|
||||||
|
|
||||||
describe.each(cooldownDurations)(
|
describe.each(cooldownDurations)(
|
||||||
"with cooldown duration set to $cooldownDuration",
|
'with cooldown duration set to $cooldownDuration',
|
||||||
({ cooldownDuration, factor }) => {
|
({ cooldownDuration, factor }) => {
|
||||||
const dataWithCooldownDuration = {
|
const dataWithCooldownDuration = {
|
||||||
...defaultData,
|
...defaultData,
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { defaultEvaluator, Evaluator, mathEvaluator } from "../../src/expression-evaluation/evaluator";
|
import { defaultEvaluator, Evaluator, mathEvaluator } from '../../src/expression-evaluation/evaluator';
|
||||||
|
|
||||||
describe("Evaluator", () => {
|
describe('Evaluator', () => {
|
||||||
it("evaluates expressions that only use identifiers according to the given predicate", () => {
|
it('evaluates expressions that only use identifiers according to the given predicate', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "typeof 'foo' === 'string' ? 42 : null";
|
const expression = "typeof 'foo' === 'string' ? 42 : null";
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe("Evaluator", () => {
|
||||||
expect(result).toEqual(42);
|
expect(result).toEqual(42);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fails to evaluate expressions that contain identifiers that are not allowed by the predicate", () => {
|
it('fails to evaluate expressions that contain identifiers that are not allowed by the predicate', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "typeof 'foo' === 'string' ? 42 : function (){}";
|
const expression = "typeof 'foo' === 'string' ? 42 : function (){}";
|
||||||
|
|
||||||
|
@ -29,33 +29,33 @@ describe("Evaluator", () => {
|
||||||
expect(evaluate).toThrowError("'function' is not an allowed identifier.");
|
expect(evaluate).toThrowError("'function' is not an allowed identifier.");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fails to evaluate expressions that contain invalid tokens", () => {
|
it('fails to evaluate expressions that contain invalid tokens', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "1;";
|
const expression = '1;';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const evaluate = () => defaultEvaluator.evaluate(expression);
|
const evaluate = () => defaultEvaluator.evaluate(expression);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(evaluate).toThrowError("Invalid or unexpected token (1)");
|
expect(evaluate).toThrowError('Invalid or unexpected token (1)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("fails to evaluate expressions that contain arrow functions", () => {
|
it('fails to evaluate expressions that contain arrow functions', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "(() => 1)()";
|
const expression = '(() => 1)()';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const evaluate = () => defaultEvaluator.evaluate(expression);
|
const evaluate = () => defaultEvaluator.evaluate(expression);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(evaluate).toThrowError("Invalid or unexpected token (4)");
|
expect(evaluate).toThrowError('Invalid or unexpected token (4)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("makes the given context available", () => {
|
it('makes the given context available', () => {
|
||||||
// given
|
// given
|
||||||
const context = { floor: Math.floor };
|
const context = { floor: Math.floor };
|
||||||
const evaluator = new Evaluator({ context });
|
const evaluator = new Evaluator({ context });
|
||||||
const expression = "floor(0.5)";
|
const expression = 'floor(0.5)';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const result = evaluator.evaluate(expression);
|
const result = evaluator.evaluate(expression);
|
||||||
|
@ -64,10 +64,10 @@ describe("Evaluator", () => {
|
||||||
expect(result).toEqual(0);
|
expect(result).toEqual(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("mathEvaluator", () => {
|
describe('mathEvaluator', () => {
|
||||||
it("makes the given context available", () => {
|
it('makes the given context available', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "sqrt(sin(PI))";
|
const expression = 'sqrt(sin(PI))';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const result = mathEvaluator.evaluate(expression);
|
const result = mathEvaluator.evaluate(expression);
|
||||||
|
@ -76,9 +76,9 @@ describe("Evaluator", () => {
|
||||||
expect(result).toEqual(Math.sqrt(Math.sin(Math.PI)));
|
expect(result).toEqual(Math.sqrt(Math.sin(Math.PI)));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("does not give acces to the function constructor", () => {
|
it('does not give acces to the function constructor', () => {
|
||||||
// given
|
// given
|
||||||
const expression = "sqrt.constructor";
|
const expression = 'sqrt.constructor';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const evaluate = () => mathEvaluator.evaluate(expression);
|
const evaluate = () => mathEvaluator.evaluate(expression);
|
||||||
|
|
|
@ -2,574 +2,574 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { Lexer } from "../../src/expression-evaluation/lexer";
|
import { Lexer } from '../../src/expression-evaluation/lexer';
|
||||||
|
|
||||||
import type { Token } from "../../src/expression-evaluation/grammar";
|
import type { Token } from '../../src/expression-evaluation/grammar';
|
||||||
|
|
||||||
describe("Lexer", () => {
|
describe('Lexer', () => {
|
||||||
const singleOperatorTestCases: { input: string; expected: Token[] }[] = [
|
const singleOperatorTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: "+",
|
input: '+',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "+", pos: 0 },
|
{ type: '+', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "-",
|
input: '-',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "-", pos: 0 },
|
{ type: '-', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "*",
|
input: '*',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "*", pos: 0 },
|
{ type: '*', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "**",
|
input: '**',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "**", pos: 0 },
|
{ type: '**', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "/",
|
input: '/',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "/", pos: 0 },
|
{ type: '/', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "%",
|
input: '%',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "%", pos: 0 },
|
{ type: '%', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "===",
|
input: '===',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "===", pos: 0 },
|
{ type: '===', pos: 0 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "!==",
|
input: '!==',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "!==", pos: 0 },
|
{ type: '!==', pos: 0 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "==",
|
input: '==',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "==", pos: 0 },
|
{ type: '==', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "<",
|
input: '<',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "<", pos: 0 },
|
{ type: '<', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "<=",
|
input: '<=',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "<=", pos: 0 },
|
{ type: '<=', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ">",
|
input: '>',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ">", pos: 0 },
|
{ type: '>', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ">=",
|
input: '>=',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ">=", pos: 0 },
|
{ type: '>=', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "&&",
|
input: '&&',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "&&", pos: 0 },
|
{ type: '&&', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "||",
|
input: '||',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "||", pos: 0 },
|
{ type: '||', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "&",
|
input: '&',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "&", pos: 0 },
|
{ type: '&', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "|",
|
input: '|',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "|", pos: 0 },
|
{ type: '|', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "<<",
|
input: '<<',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "<<", pos: 0 },
|
{ type: '<<', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ">>>",
|
input: '>>>',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ">>>", pos: 0 },
|
{ type: '>>>', pos: 0 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ".",
|
input: '.',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ".", pos: 0 },
|
{ type: '.', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "?.",
|
input: '?.',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "?.", pos: 0 },
|
{ type: '?.', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "??",
|
input: '??',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "??", pos: 0 },
|
{ type: '??', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "?",
|
input: '?',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "?", pos: 0 },
|
{ type: '?', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ":",
|
input: ':',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ":", pos: 0 },
|
{ type: ':', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "(",
|
input: '(',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "(", pos: 0 },
|
{ type: '(', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ")",
|
input: ')',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ")", pos: 0 },
|
{ type: ')', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "[",
|
input: '[',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "[", pos: 0 },
|
{ type: '[', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "]",
|
input: ']',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "]", pos: 0 },
|
{ type: ']', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ",",
|
input: ',',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ",", pos: 0 },
|
{ type: ',', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "{",
|
input: '{',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "{", pos: 0 },
|
{ type: '{', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "}",
|
input: '}',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "}", pos: 0 },
|
{ type: '}', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const singleNumberTestCases: { input: string; expected: Token[] }[] = [
|
const singleNumberTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: "1",
|
input: '1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "1", pos: 0 },
|
{ type: 'number', symbol: '1', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "42",
|
input: '42',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "42", pos: 0 },
|
{ type: 'number', symbol: '42', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "42.9",
|
input: '42.9',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "42.9", pos: 0 },
|
{ type: 'number', symbol: '42.9', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ".9",
|
input: '.9',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: ".9", pos: 0 },
|
{ type: 'number', symbol: '.9', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "1_1",
|
input: '1_1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "1_1", pos: 0 },
|
{ type: 'number', symbol: '1_1', pos: 0 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "10_1",
|
input: '10_1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "10_1", pos: 0 },
|
{ type: 'number', symbol: '10_1', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "1_1_1",
|
input: '1_1_1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "1_1_1", pos: 0 },
|
{ type: 'number', symbol: '1_1_1', pos: 0 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: ".1_1",
|
input: '.1_1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: ".1_1", pos: 0 },
|
{ type: 'number', symbol: '.1_1', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const invalidNumberTestCases: { input: string; expected: Token[] }[] = [
|
const invalidNumberTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{ input: "1.1.1", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '1.1.1', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "1__1", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '1__1', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "1_", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '1_', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "1._1", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '1._1', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "0_1", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '0_1', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "00_1", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '00_1', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const singleIdentifierTestCases: { input: string; expected: Token[] }[] = [
|
const singleIdentifierTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: "foo",
|
input: 'foo',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "foo", pos: 0 },
|
{ type: 'iden', symbol: 'foo', pos: 0 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "_foo",
|
input: '_foo',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "_foo", pos: 0 },
|
{ type: 'iden', symbol: '_foo', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "$foo",
|
input: '$foo',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "$foo", pos: 0 },
|
{ type: 'iden', symbol: '$foo', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "foo1",
|
input: 'foo1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "foo1", pos: 0 },
|
{ type: 'iden', symbol: 'foo1', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "_foo1_",
|
input: '_foo1_',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "_foo1_", pos: 0 },
|
{ type: 'iden', symbol: '_foo1_', pos: 0 },
|
||||||
{ type: "eof", pos: 6 },
|
{ type: 'eof', pos: 6 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "μ",
|
input: 'μ',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "μ", pos: 0 },
|
{ type: 'iden', symbol: 'μ', pos: 0 },
|
||||||
{ type: "eof", pos: 1 },
|
{ type: 'eof', pos: 1 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "._1",
|
input: '._1',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: ".", pos: 0 },
|
{ type: '.', pos: 0 },
|
||||||
{ type: "iden", symbol: "_1", pos: 1 },
|
{ type: 'iden', symbol: '_1', pos: 1 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "true",
|
input: 'true',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "true", pos: 0 },
|
{ type: 'iden', symbol: 'true', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "false",
|
input: 'false',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "false", pos: 0 },
|
{ type: 'iden', symbol: 'false', pos: 0 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "null",
|
input: 'null',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "null", pos: 0 },
|
{ type: 'iden', symbol: 'null', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "undefined",
|
input: 'undefined',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "iden", symbol: "undefined", pos: 0 },
|
{ type: 'iden', symbol: 'undefined', pos: 0 },
|
||||||
{ type: "eof", pos: 9 },
|
{ type: 'eof', pos: 9 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const invalidIdentifierTestCases: { input: string; expected: Token[] }[] = [
|
const invalidIdentifierTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: "1foo",
|
input: '1foo',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "1", pos: 0 },
|
{ type: 'number', symbol: '1', pos: 0 },
|
||||||
{ type: "iden", symbol: "foo", pos: 1 },
|
{ type: 'iden', symbol: 'foo', pos: 1 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{ input: "↓", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '↓', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: '"', expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '"', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const singleStringTestCases: { input: string; expected: Token[] }[] = [
|
const singleStringTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: '""',
|
input: '""',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: '""', pos: 0 },
|
{ type: 'string', symbol: '""', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: '"foo"',
|
input: '"foo"',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: '"foo"', pos: 0 },
|
{ type: 'string', symbol: '"foo"', pos: 0 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: '"\\""',
|
input: '"\\""',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: '"\\""', pos: 0 },
|
{ type: 'string', symbol: '"\\""', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: '"\\\'"',
|
input: '"\\\'"',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: '"\\\'"', pos: 0 },
|
{ type: 'string', symbol: '"\\\'"', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "''",
|
input: "''",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "''", pos: 0 },
|
{ type: 'string', symbol: "''", pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "'foo'",
|
input: "'foo'",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "'foo'", pos: 0 },
|
{ type: 'string', symbol: "'foo'", pos: 0 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "'\\''",
|
input: "'\\''",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "'\\''", pos: 0 },
|
{ type: 'string', symbol: "'\\''", pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "'\\\"'",
|
input: "'\\\"'",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "'\\\"'", pos: 0 },
|
{ type: 'string', symbol: "'\\\"'", pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "``",
|
input: '``',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "``", pos: 0 },
|
{ type: 'string', symbol: '``', pos: 0 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "`foo`",
|
input: '`foo`',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "`foo`", pos: 0 },
|
{ type: 'string', symbol: '`foo`', pos: 0 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "`\\``",
|
input: '`\\``',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "`\\``", pos: 0 },
|
{ type: 'string', symbol: '`\\``', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: '`\\"`',
|
input: '`\\"`',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: '`\\"`', pos: 0 },
|
{ type: 'string', symbol: '`\\"`', pos: 0 },
|
||||||
{ type: "eof", pos: 4 },
|
{ type: 'eof', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const invalidStringTestCases: { input: string; expected: Token[] }[] = [
|
const invalidStringTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{ input: '"', expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '"', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: '"\\"', expected: [{ type: "invalid", pos: 0 }] },
|
{ input: '"\\"', expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "'", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: "'", expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
{ input: "'\\'", expected: [{ type: "invalid", pos: 0 }] },
|
{ input: "'\\'", expected: [{ type: 'invalid', pos: 0 }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const whiteSpaceTestCases: { input: string; expected: Token[] }[] = [
|
const whiteSpaceTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{ input: " ", expected: [{ type: "eof", pos: 1 }] },
|
{ input: ' ', expected: [{ type: 'eof', pos: 1 }] },
|
||||||
{ input: " ", expected: [{ type: "eof", pos: 3 }] },
|
{ input: ' ', expected: [{ type: 'eof', pos: 3 }] },
|
||||||
{ input: "\n", expected: [{ type: "eof", pos: 1 }] },
|
{ input: '\n', expected: [{ type: 'eof', pos: 1 }] },
|
||||||
{ input: " \n", expected: [{ type: "eof", pos: 2 }] },
|
{ input: ' \n', expected: [{ type: 'eof', pos: 2 }] },
|
||||||
{ input: " ", expected: [{ type: "eof", pos: 1 }] },
|
{ input: ' ', expected: [{ type: 'eof', pos: 1 }] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const complicatedTermTestCases: { input: string; expected: Token[] }[] = [
|
const complicatedTermTestCases: { input: string; expected: Token[] }[] = [
|
||||||
{
|
{
|
||||||
input: "5x",
|
input: '5x',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "5", pos: 0 },
|
{ type: 'number', symbol: '5', pos: 0 },
|
||||||
{ type: "iden", symbol: "x", pos: 1 },
|
{ type: 'iden', symbol: 'x', pos: 1 },
|
||||||
{ type: "eof", pos: 2 },
|
{ type: 'eof', pos: 2 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "5*x",
|
input: '5*x',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "5", pos: 0 },
|
{ type: 'number', symbol: '5', pos: 0 },
|
||||||
{ type: "*", pos: 1 },
|
{ type: '*', pos: 1 },
|
||||||
{ type: "iden", symbol: "x", pos: 2 },
|
{ type: 'iden', symbol: 'x', pos: 2 },
|
||||||
{ type: "eof", pos: 3 },
|
{ type: 'eof', pos: 3 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "5 * x",
|
input: '5 * x',
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "number", symbol: "5", pos: 0 },
|
{ type: 'number', symbol: '5', pos: 0 },
|
||||||
{ type: "*", pos: 2 },
|
{ type: '*', pos: 2 },
|
||||||
{ type: "iden", symbol: "x", pos: 4 },
|
{ type: 'iden', symbol: 'x', pos: 4 },
|
||||||
{ type: "eof", pos: 5 },
|
{ type: 'eof', pos: 5 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "(5 * 5 + 2) / 1.2 === 'foo'",
|
input: "(5 * 5 + 2) / 1.2 === 'foo'",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "(", pos: 0 },
|
{ type: '(', pos: 0 },
|
||||||
{ type: "number", symbol: "5", pos: 1 },
|
{ type: 'number', symbol: '5', pos: 1 },
|
||||||
{ type: "*", pos: 3 },
|
{ type: '*', pos: 3 },
|
||||||
{ type: "number", symbol: "5", pos: 5 },
|
{ type: 'number', symbol: '5', pos: 5 },
|
||||||
{ type: "+", pos: 7 },
|
{ type: '+', pos: 7 },
|
||||||
{ type: "number", symbol: "2", pos: 9 },
|
{ type: 'number', symbol: '2', pos: 9 },
|
||||||
{ type: ")", pos: 10 },
|
{ type: ')', pos: 10 },
|
||||||
{ type: "/", pos: 12 },
|
{ type: '/', pos: 12 },
|
||||||
{ type: "number", symbol: "1.2", pos: 14 },
|
{ type: 'number', symbol: '1.2', pos: 14 },
|
||||||
{ type: "===", pos: 18 },
|
{ type: '===', pos: 18 },
|
||||||
{ type: "string", symbol: "'foo'", pos: 22 },
|
{ type: 'string', symbol: "'foo'", pos: 22 },
|
||||||
{ type: "eof", pos: 27 },
|
{ type: 'eof', pos: 27 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "(() => {console.log('foo'); return 1;})()",
|
input: "(() => {console.log('foo'); return 1;})()",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "(", pos: 0 },
|
{ type: '(', pos: 0 },
|
||||||
{ type: "(", pos: 1 },
|
{ type: '(', pos: 1 },
|
||||||
{ type: ")", pos: 2 },
|
{ type: ')', pos: 2 },
|
||||||
{ type: "invalid", pos: 4 },
|
{ type: 'invalid', pos: 4 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "(function() {console.log('foo'); return 1;})()",
|
input: "(function() {console.log('foo'); return 1;})()",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "(", pos: 0 },
|
{ type: '(', pos: 0 },
|
||||||
{ type: "iden", symbol: "function", pos: 1 },
|
{ type: 'iden', symbol: 'function', pos: 1 },
|
||||||
{ type: "(", pos: 9 },
|
{ type: '(', pos: 9 },
|
||||||
{ type: ")", pos: 10 },
|
{ type: ')', pos: 10 },
|
||||||
{ type: "{", pos: 12 },
|
{ type: '{', pos: 12 },
|
||||||
{ type: "iden", symbol: "console", pos: 13 },
|
{ type: 'iden', symbol: 'console', pos: 13 },
|
||||||
{ type: ".", pos: 20 },
|
{ type: '.', pos: 20 },
|
||||||
{ type: "iden", symbol: "log", pos: 21 },
|
{ type: 'iden', symbol: 'log', pos: 21 },
|
||||||
{ type: "(", pos: 24 },
|
{ type: '(', pos: 24 },
|
||||||
{ type: "string", symbol: "'foo'", pos: 25 },
|
{ type: 'string', symbol: "'foo'", pos: 25 },
|
||||||
{ type: ")", pos: 30 },
|
{ type: ')', pos: 30 },
|
||||||
{ type: "invalid", pos: 31 },
|
{ type: 'invalid', pos: 31 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
input: "'ranged' === 'ranged'",
|
input: "'ranged' === 'ranged'",
|
||||||
expected: [
|
expected: [
|
||||||
{ type: "string", symbol: "'ranged'", pos: 0 },
|
{ type: 'string', symbol: "'ranged'", pos: 0 },
|
||||||
{ type: "===", pos: 9 },
|
{ type: '===', pos: 9 },
|
||||||
{ type: "string", symbol: "'ranged'", pos: 13 },
|
{ type: 'string', symbol: "'ranged'", pos: 13 },
|
||||||
{ type: "eof", pos: 21 },
|
{ type: 'eof', pos: 21 },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -584,7 +584,7 @@ describe("Lexer", () => {
|
||||||
...invalidStringTestCases,
|
...invalidStringTestCases,
|
||||||
...whiteSpaceTestCases,
|
...whiteSpaceTestCases,
|
||||||
...complicatedTermTestCases,
|
...complicatedTermTestCases,
|
||||||
])("lexes $input correctly", ({ input, expected }) => {
|
])('lexes $input correctly', ({ input, expected }) => {
|
||||||
// when
|
// when
|
||||||
const result = consume(new Lexer(input));
|
const result = consume(new Lexer(input));
|
||||||
|
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import { literals, safeOperators } from "../../src/expression-evaluation/grammar";
|
import { literals, safeOperators } from '../../src/expression-evaluation/grammar';
|
||||||
import { Validator } from "../../src/expression-evaluation/validator";
|
import { Validator } from '../../src/expression-evaluation/validator';
|
||||||
|
|
||||||
describe("Validator", () => {
|
describe('Validator', () => {
|
||||||
it("allows identifier according to the given predicate", () => {
|
it('allows identifier according to the given predicate', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => identifier === "true";
|
const predicate = (identifier: string) => identifier === 'true';
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "true";
|
const input = 'true';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
@ -21,11 +21,11 @@ describe("Validator", () => {
|
||||||
expect(validate).not.toThrow();
|
expect(validate).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disallows identifier according to the given predicate", () => {
|
it('disallows identifier according to the given predicate', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => identifier === "false";
|
const predicate = (identifier: string) => identifier === 'false';
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "true";
|
const input = 'true';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
@ -34,11 +34,11 @@ describe("Validator", () => {
|
||||||
expect(validate).toThrowError("'true' is not an allowed identifier");
|
expect(validate).toThrowError("'true' is not an allowed identifier");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows multiple identifiers according to the given predicate", () => {
|
it('allows multiple identifiers according to the given predicate', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
|
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "true null";
|
const input = 'true null';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
@ -47,11 +47,11 @@ describe("Validator", () => {
|
||||||
expect(validate).not.toThrow();
|
expect(validate).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows multiple identifiers in a more complex expression according to the given rule", () => {
|
it('allows multiple identifiers in a more complex expression according to the given rule', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
|
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "true === null";
|
const input = 'true === null';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
@ -60,11 +60,11 @@ describe("Validator", () => {
|
||||||
expect(validate).not.toThrow();
|
expect(validate).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("mentions the first not allowed identifier in the thrown errror", () => {
|
it('mentions the first not allowed identifier in the thrown errror', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
|
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "true === null && undefined === false";
|
const input = 'true === null && undefined === false';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
@ -73,22 +73,21 @@ describe("Validator", () => {
|
||||||
expect(validate).toThrowError("'undefined' is not an allowed identifier.");
|
expect(validate).toThrowError("'undefined' is not an allowed identifier.");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disallows invalid invalid tokens", () => {
|
it('disallows invalid invalid tokens', () => {
|
||||||
// given
|
// given
|
||||||
const validator = new Validator();
|
const validator = new Validator();
|
||||||
const input = ";";
|
const input = ';';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(validate).toThrowError("Invalid or unexpected token (0)");
|
expect(validate).toThrowError('Invalid or unexpected token (0)');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows a complicated valid expression", () => {
|
it('allows a complicated valid expression', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) =>
|
const predicate = (identifier: string) => [...safeOperators, ...literals, 'floor', 'random'].includes(identifier);
|
||||||
[...safeOperators, ...literals, "floor", "random"].includes(identifier);
|
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "typeof (floor(random() * 5) / 2) === 'number' ? 42 : 'foo'";
|
const input = "typeof (floor(random() * 5) / 2) === 'number' ? 42 : 'foo'";
|
||||||
|
|
||||||
|
@ -99,9 +98,9 @@ describe("Validator", () => {
|
||||||
expect(validate).not.toThrow();
|
expect(validate).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disallows a complicated expression if it contains a disallowed identifier", () => {
|
it('disallows a complicated expression if it contains a disallowed identifier', () => {
|
||||||
// given
|
// given
|
||||||
const predicate = (identifier: string) => [...safeOperators, ...literals, "ceil"].includes(identifier);
|
const predicate = (identifier: string) => [...safeOperators, ...literals, 'ceil'].includes(identifier);
|
||||||
const validator = new Validator(predicate);
|
const validator = new Validator(predicate);
|
||||||
const input = "ceil.constructor('alert(1); return 1;')()";
|
const input = "ceil.constructor('alert(1); return 1;')()";
|
||||||
|
|
||||||
|
@ -112,15 +111,15 @@ describe("Validator", () => {
|
||||||
expect(validate).toThrowError("'constructor' is not an allowed identifier.");
|
expect(validate).toThrowError("'constructor' is not an allowed identifier.");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("disallows arrow functions", () => {
|
it('disallows arrow functions', () => {
|
||||||
// given
|
// given
|
||||||
const validator = new Validator();
|
const validator = new Validator();
|
||||||
const input = "() => {}";
|
const input = '() => {}';
|
||||||
|
|
||||||
// when
|
// when
|
||||||
const validate = () => validator.validate(input);
|
const validate = () => validator.validate(input);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
expect(validate).toThrowError("Invalid or unexpected token (3)");
|
expect(validate).toThrowError('Invalid or unexpected token (3)');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from 'vitest';
|
||||||
|
|
||||||
import de from "../../lang/de.json";
|
import de from '../../lang/de.json';
|
||||||
import en from "../../lang/en.json";
|
import en from '../../lang/en.json';
|
||||||
|
|
||||||
describe("English and german localization files", () => {
|
describe('English and german localization files', () => {
|
||||||
it("should have the same keys.", () => {
|
it('should have the same keys.', () => {
|
||||||
const deKeys = Object.keys(de);
|
const deKeys = Object.keys(de);
|
||||||
const enKeys = Object.keys(en);
|
const enKeys = Object.keys(en);
|
||||||
expect(deKeys).toEqual(enKeys);
|
expect(deKeys).toEqual(enKeys);
|
||||||
|
|
|
@ -2,23 +2,23 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import en from "../lang/en.json";
|
import en from '../lang/en.json';
|
||||||
|
|
||||||
function setupPrimitives() {
|
function setupPrimitives() {
|
||||||
Object.defineProperties(Number, {
|
Object.defineProperties(Number, {
|
||||||
isNumeric: {
|
isNumeric: {
|
||||||
value: function (n: unknown) {
|
value: function (n: unknown) {
|
||||||
if (n instanceof Array) return false;
|
if (n instanceof Array) return false;
|
||||||
else if (([null, ""] as unknown[]).includes(n)) return false;
|
else if (([null, ''] as unknown[]).includes(n)) return false;
|
||||||
// @ts-expect-error Abusing JavaScript a bit here, but it's the implementation from foundry
|
// @ts-expect-error Abusing JavaScript a bit here, but it's the implementation from foundry
|
||||||
return +n === +n;
|
return +n === +n;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
fromString: {
|
fromString: {
|
||||||
value: function (str: unknown) {
|
value: function (str: unknown) {
|
||||||
if (typeof str !== "string" || !str.length) return NaN;
|
if (typeof str !== 'string' || !str.length) return NaN;
|
||||||
// Remove whitespace.
|
// Remove whitespace.
|
||||||
str = str.replace(/\s+/g, "");
|
str = str.replace(/\s+/g, '');
|
||||||
return Number(str);
|
return Number(str);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -6,7 +6,7 @@ export class DS4ActiveEffectConfig extends ActiveEffectConfig {
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
template: "systems/ds4/templates/sheets/active-effect/active-effect-config.hbs",
|
template: 'systems/ds4/templates/sheets/active-effect/active-effect-config.hbs',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ export class DS4ActiveEffectConfig extends ActiveEffectConfig {
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
const checkbox = html[0]?.querySelector('input[name="flags.ds4.itemEffectConfig.applyToItems"]');
|
const checkbox = html[0]?.querySelector('input[name="flags.ds4.itemEffectConfig.applyToItems"]');
|
||||||
checkbox?.addEventListener("change", () => this.#toggleItemEffectConfig(checkbox.checked));
|
checkbox?.addEventListener('change', () => this.#toggleItemEffectConfig(checkbox.checked));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,14 +25,14 @@ export class DS4ActiveEffectConfig extends ActiveEffectConfig {
|
||||||
* @param {boolean} active The target state
|
* @param {boolean} active The target state
|
||||||
*/
|
*/
|
||||||
#toggleItemEffectConfig(active) {
|
#toggleItemEffectConfig(active) {
|
||||||
const elements = this.element[0]?.querySelectorAll(".ds4-item-effect-config");
|
const elements = this.element[0]?.querySelectorAll('.ds4-item-effect-config');
|
||||||
elements?.forEach((element) => {
|
elements?.forEach((element) => {
|
||||||
if (active) {
|
if (active) {
|
||||||
element.classList.remove("ds4-hidden");
|
element.classList.remove('ds4-hidden');
|
||||||
} else {
|
} else {
|
||||||
element.classList.add("ds4-hidden");
|
element.classList.add('ds4-hidden');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.setPosition({ height: "auto" });
|
this.setPosition({ height: 'auto' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from '../../config';
|
||||||
import { DS4ActiveEffect } from "../../documents/active-effect";
|
import { DS4ActiveEffect } from '../../documents/active-effect';
|
||||||
import { isCheck } from "../../documents/actor/actor-data-properties-base";
|
import { isCheck } from '../../documents/actor/actor-data-properties-base';
|
||||||
import { getDS4Settings } from "../../settings";
|
import { getDS4Settings } from '../../settings';
|
||||||
import { notifications } from "../../ui/notifications";
|
import { notifications } from '../../ui/notifications';
|
||||||
import { enforce, getCanvas, getGame } from "../../utils/utils";
|
import { enforce, getCanvas, getGame } from '../../utils/utils';
|
||||||
import { disableOverriddenFields } from "../sheet-helpers";
|
import { disableOverriddenFields } from '../sheet-helpers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base sheet class for all {@link DS4Actor}s.
|
* The base sheet class for all {@link DS4Actor}s.
|
||||||
|
@ -20,14 +20,14 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
classes: ["sheet", "ds4-actor-sheet"],
|
classes: ['sheet', 'ds4-actor-sheet'],
|
||||||
height: 645,
|
height: 645,
|
||||||
scrollY: [".ds4-sheet-body"],
|
scrollY: ['.ds4-sheet-body'],
|
||||||
tabs: [{ navSelector: ".ds4-sheet-tab-nav", contentSelector: ".ds4-sheet-body", initial: "values" }],
|
tabs: [{ navSelector: '.ds4-sheet-tab-nav', contentSelector: '.ds4-sheet-body', initial: 'values' }],
|
||||||
dragDrop: [
|
dragDrop: [
|
||||||
{ dragSelector: ".item-list .item", dropSelector: null },
|
{ dragSelector: '.item-list .item', dropSelector: null },
|
||||||
{ dragSelector: ".effect-list .effect", dropSelector: null },
|
{ dragSelector: '.effect-list .effect', dropSelector: null },
|
||||||
{ dragSelector: ".ds4-check", dropSelector: null },
|
{ dragSelector: '.ds4-check', dropSelector: null },
|
||||||
],
|
],
|
||||||
width: 650,
|
width: 650,
|
||||||
});
|
});
|
||||||
|
@ -35,7 +35,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get template() {
|
get template() {
|
||||||
const basePath = "systems/ds4/templates/sheets/actor";
|
const basePath = 'systems/ds4/templates/sheets/actor';
|
||||||
if (!getGame().user?.isGM && this.actor.limited) return `${basePath}/limited-sheet.hbs`;
|
if (!getGame().user?.isGM && this.actor.limited) return `${basePath}/limited-sheet.hbs`;
|
||||||
return `${basePath}/${this.actor.type}-sheet.hbs`;
|
return `${basePath}/${this.actor.type}-sheet.hbs`;
|
||||||
}
|
}
|
||||||
|
@ -74,11 +74,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
addTooltipsToData(context) {
|
addTooltipsToData(context) {
|
||||||
const valueGroups = [
|
const valueGroups = [context.data.system.attributes, context.data.system.traits, context.data.system.combatValues];
|
||||||
context.data.system.attributes,
|
|
||||||
context.data.system.traits,
|
|
||||||
context.data.system.combatValues,
|
|
||||||
];
|
|
||||||
|
|
||||||
valueGroups.forEach((valueGroup) => {
|
valueGroups.forEach((valueGroup) => {
|
||||||
Object.values(valueGroup).forEach((attribute) => {
|
Object.values(valueGroup).forEach((attribute) => {
|
||||||
|
@ -95,9 +91,9 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
getTooltipForValue(value) {
|
getTooltipForValue(value) {
|
||||||
return `${value.base} (${getGame().i18n.localize("DS4.TooltipBaseValue")}) + ${
|
return `${value.base} (${getGame().i18n.localize('DS4.TooltipBaseValue')}) + ${
|
||||||
value.mod
|
value.mod
|
||||||
} (${getGame().i18n.localize("DS4.TooltipModifier")}) ➞ ${getGame().i18n.localize("DS4.TooltipEffects")} ➞ ${
|
} (${getGame().i18n.localize('DS4.TooltipModifier')}) ➞ ${getGame().i18n.localize('DS4.TooltipEffects')} ➞ ${
|
||||||
value.total
|
value.total
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
|
@ -111,16 +107,16 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
|
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
html.find(".control-item").on("click", this.onControlItem.bind(this));
|
html.find('.control-item').on('click', this.onControlItem.bind(this));
|
||||||
html.find(".change-item").on("change", this.onChangeItem.bind(this));
|
html.find('.change-item').on('change', this.onChangeItem.bind(this));
|
||||||
|
|
||||||
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
|
html.find('.control-effect').on('click', this.onControlEffect.bind(this));
|
||||||
html.find(".change-effect").on("change", this.onChangeEffect.bind(this));
|
html.find('.change-effect').on('change', this.onChangeEffect.bind(this));
|
||||||
|
|
||||||
html.find(".rollable-item").on("click", this.onRollItem.bind(this));
|
html.find('.rollable-item').on('click', this.onRollItem.bind(this));
|
||||||
html.find(".rollable-check").on("click", this.onRollCheck.bind(this));
|
html.find('.rollable-check').on('click', this.onRollCheck.bind(this));
|
||||||
|
|
||||||
html.find(".sort-items").on("click", this.onSortItems.bind(this));
|
html.find('.sort-items').on('click', this.onSortItems.bind(this));
|
||||||
|
|
||||||
disableOverriddenFields(this.form, this.actor.overrides, (key) => `[name="${key}"]`);
|
disableOverriddenFields(this.form, this.actor.overrides, (key) => `[name="${key}"]`);
|
||||||
for (const item of this.actor.items) {
|
for (const item of this.actor.items) {
|
||||||
|
@ -141,12 +137,12 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
onControlItem(event) {
|
onControlItem(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const a = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
switch (a.dataset["action"]) {
|
switch (a.dataset['action']) {
|
||||||
case "create":
|
case 'create':
|
||||||
return this.onCreateItem(event);
|
return this.onCreateItem(event);
|
||||||
case "edit":
|
case 'edit':
|
||||||
return this.onEditItem(event);
|
return this.onEditItem(event);
|
||||||
case "delete":
|
case 'delete':
|
||||||
return this.onDeleteItem(event);
|
return this.onDeleteItem(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,7 +172,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const item = await fromUuid(uuid);
|
const item = await fromUuid(uuid);
|
||||||
enforce(
|
enforce(
|
||||||
item && item.parent === this.actor,
|
item && item.parent === this.actor,
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveItem', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
item.sheet?.render(true);
|
item.sheet?.render(true);
|
||||||
}
|
}
|
||||||
|
@ -193,7 +189,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const item = await fromUuid(uuid);
|
const item = await fromUuid(uuid);
|
||||||
enforce(
|
enforce(
|
||||||
item && item.parent === this.actor,
|
item && item.parent === this.actor,
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveItem', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
item.delete();
|
item.delete();
|
||||||
$(li).slideUp(200, () => this.render(false));
|
$(li).slideUp(200, () => this.render(false));
|
||||||
|
@ -207,7 +203,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
onChangeItem(event) {
|
onChangeItem(event) {
|
||||||
return this.onChangeEmbeddedDocument(event, "Item");
|
return this.onChangeEmbeddedDocument(event, 'Item');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -220,12 +216,12 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
onControlEffect(event) {
|
onControlEffect(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const a = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
switch (a.dataset["action"]) {
|
switch (a.dataset['action']) {
|
||||||
case "create":
|
case 'create':
|
||||||
return this.onCreateEffect();
|
return this.onCreateEffect();
|
||||||
case "edit":
|
case 'edit':
|
||||||
return this.onEditEffect(event);
|
return this.onEditEffect(event);
|
||||||
case "delete":
|
case 'delete':
|
||||||
return this.onDeleteEffect(event);
|
return this.onDeleteEffect(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +248,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const effect = await fromUuid(uuid);
|
const effect = await fromUuid(uuid);
|
||||||
enforce(
|
enforce(
|
||||||
effect && (effect.parent === this.actor || effect.parent.parent === this.actor),
|
effect && (effect.parent === this.actor || effect.parent.parent === this.actor),
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveEffect", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveEffect', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
effect.sheet?.render(true);
|
effect.sheet?.render(true);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +265,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const effect = await fromUuid(uuid);
|
const effect = await fromUuid(uuid);
|
||||||
enforce(
|
enforce(
|
||||||
effect && (effect.parent === this.actor || effect.parent.parent === this.actor),
|
effect && (effect.parent === this.actor || effect.parent.parent === this.actor),
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveEffect", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveEffect', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
effect.delete();
|
effect.delete();
|
||||||
$(li).slideUp(200, () => this.render(false));
|
$(li).slideUp(200, () => this.render(false));
|
||||||
|
@ -283,7 +279,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
onChangeEffect(event) {
|
onChangeEffect(event) {
|
||||||
return this.onChangeEmbeddedDocument(event, "ActiveEffect");
|
return this.onChangeEmbeddedDocument(event, 'ActiveEffect');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -301,22 +297,22 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
|
|
||||||
const documentElement = element.closest(embeddedDocumentListEntryProperties[documentName].selector);
|
const documentElement = element.closest(embeddedDocumentListEntryProperties[documentName].selector);
|
||||||
const uuid = documentElement.dataset[embeddedDocumentListEntryProperties[documentName].uuidDataAttribute];
|
const uuid = documentElement.dataset[embeddedDocumentListEntryProperties[documentName].uuidDataAttribute];
|
||||||
const property = element.dataset["property"];
|
const property = element.dataset['property'];
|
||||||
enforce(property !== undefined, TypeError("HTML element does not provide 'data-property' attribute"));
|
enforce(property !== undefined, TypeError("HTML element does not provide 'data-property' attribute"));
|
||||||
|
|
||||||
const newValue = this.parseValue(element);
|
const newValue = this.parseValue(element);
|
||||||
|
|
||||||
const document = await fromUuid(uuid);
|
const document = await fromUuid(uuid);
|
||||||
|
|
||||||
if (documentName === "Item") {
|
if (documentName === 'Item') {
|
||||||
enforce(
|
enforce(
|
||||||
document && document.parent === this.actor,
|
document && document.parent === this.actor,
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveItem', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
enforce(
|
enforce(
|
||||||
document && (document.parent === this.actor || document.parent.parent === this.actor),
|
document && (document.parent === this.actor || document.parent.parent === this.actor),
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveEffect", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveEffect', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
document.update({ [property]: newValue });
|
document.update({ [property]: newValue });
|
||||||
|
@ -335,23 +331,21 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
*/
|
*/
|
||||||
parseValue(element) {
|
parseValue(element) {
|
||||||
switch (element.type) {
|
switch (element.type) {
|
||||||
case "checkbox": {
|
case 'checkbox': {
|
||||||
const inverted = Boolean(element.dataset["inverted"]);
|
const inverted = Boolean(element.dataset['inverted']);
|
||||||
const value = element.checked;
|
const value = element.checked;
|
||||||
return inverted ? !value : value;
|
return inverted ? !value : value;
|
||||||
}
|
}
|
||||||
case "text": {
|
case 'text': {
|
||||||
const value = element.value;
|
const value = element.value;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
case "number": {
|
case 'number': {
|
||||||
const value = Number(element.value.trim());
|
const value = Number(element.value.trim());
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
throw new TypeError(
|
throw new TypeError('Binding of item property to this type of HTML element not supported; given: ' + element);
|
||||||
"Binding of item property to this type of HTML element not supported; given: " + element,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,7 +362,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const item = await fromUuid(uuid);
|
const item = await fromUuid(uuid);
|
||||||
enforce(
|
enforce(
|
||||||
item && item.parent === this.actor,
|
item && item.parent === this.actor,
|
||||||
getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { uuid, actor: this.actor.name }),
|
getGame().i18n.format('DS4.ErrorActorDoesNotHaveItem', { uuid, actor: this.actor.name }),
|
||||||
);
|
);
|
||||||
item.roll().catch((e) => notifications.error(e, { log: true }));
|
item.roll().catch((e) => notifications.error(e, { log: true }));
|
||||||
}
|
}
|
||||||
|
@ -381,7 +375,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
onRollCheck(event) {
|
onRollCheck(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.currentTarget.blur();
|
event.currentTarget.blur();
|
||||||
const check = event.currentTarget.dataset["check"];
|
const check = event.currentTarget.dataset['check'];
|
||||||
this.actor.rollCheck(check).catch((e) => notifications.error(e, { log: true }));
|
this.actor.rollCheck(check).catch((e) => notifications.error(e, { log: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -396,17 +390,17 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const check = target.dataset.check;
|
const check = target.dataset.check;
|
||||||
if (!check) return super._onDragStart(event);
|
if (!check) return super._onDragStart(event);
|
||||||
|
|
||||||
enforce(isCheck(check), getGame().i18n.format("DS4.ErrorCannotDragMissingCheck", { check }));
|
enforce(isCheck(check), getGame().i18n.format('DS4.ErrorCannotDragMissingCheck', { check }));
|
||||||
|
|
||||||
const dragData = {
|
const dragData = {
|
||||||
actorId: this.actor.id,
|
actorId: this.actor.id,
|
||||||
sceneId: this.actor.isToken ? getCanvas().scene?.id : null,
|
sceneId: this.actor.isToken ? getCanvas().scene?.id : null,
|
||||||
tokenId: this.actor.isToken ? this.actor.token?.id : null,
|
tokenId: this.actor.isToken ? this.actor.token?.id : null,
|
||||||
type: "Check",
|
type: 'Check',
|
||||||
data: check,
|
data: check,
|
||||||
};
|
};
|
||||||
|
|
||||||
event.dataTransfer?.setData("text/plain", JSON.stringify(dragData));
|
event.dataTransfer?.setData('text/plain', JSON.stringify(dragData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -417,11 +411,11 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
onSortItems(event) {
|
onSortItems(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const target = event.currentTarget;
|
const target = event.currentTarget;
|
||||||
const type = target.parentElement?.dataset["type"];
|
const type = target.parentElement?.dataset['type'];
|
||||||
enforce(type !== undefined, `Could not find property 'type' in the dataset of the parent of ${target}`);
|
enforce(type !== undefined, `Could not find property 'type' in the dataset of the parent of ${target}`);
|
||||||
const dataPath = target.dataset["dataPath"];
|
const dataPath = target.dataset['dataPath'];
|
||||||
enforce(dataPath !== undefined, `Could not find property 'dataPath' in the dataset of ${target}`);
|
enforce(dataPath !== undefined, `Could not find property 'dataPath' in the dataset of ${target}`);
|
||||||
const dataPath2 = target.dataset["dataPath2"];
|
const dataPath2 = target.dataset['dataPath2'];
|
||||||
/** @type {import("../../documents/item/item").DS4Item[]}*/
|
/** @type {import("../../documents/item/item").DS4Item[]}*/
|
||||||
const items = this.actor.items.filter((item) => item.type === type);
|
const items = this.actor.items.filter((item) => item.type === type);
|
||||||
items.sort((a, b) => a.sort - b.sort);
|
items.sort((a, b) => a.sort - b.sort);
|
||||||
|
@ -434,14 +428,14 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const propertyA = getProperty(a, dataPath);
|
const propertyA = getProperty(a, dataPath);
|
||||||
const propertyB = getProperty(b, dataPath);
|
const propertyB = getProperty(b, dataPath);
|
||||||
const comparison =
|
const comparison =
|
||||||
typeof propertyA === "string" || typeof propertyB === "string"
|
typeof propertyA === 'string' || typeof propertyB === 'string'
|
||||||
? compareAsStrings(propertyA, propertyB, invert)
|
? compareAsStrings(propertyA, propertyB, invert)
|
||||||
: compareAsNumbers(propertyA, propertyB, invert);
|
: compareAsNumbers(propertyA, propertyB, invert);
|
||||||
|
|
||||||
if (comparison === 0 && dataPath2 !== undefined) {
|
if (comparison === 0 && dataPath2 !== undefined) {
|
||||||
const propertyA = getProperty(a, dataPath);
|
const propertyA = getProperty(a, dataPath);
|
||||||
const propertyB = getProperty(b, dataPath);
|
const propertyB = getProperty(b, dataPath);
|
||||||
return typeof propertyA === "string" || typeof propertyB === "string"
|
return typeof propertyA === 'string' || typeof propertyB === 'string'
|
||||||
? compareAsStrings(propertyA, propertyB, invert)
|
? compareAsStrings(propertyA, propertyB, invert)
|
||||||
: compareAsNumbers(propertyA, propertyB, invert);
|
: compareAsNumbers(propertyA, propertyB, invert);
|
||||||
}
|
}
|
||||||
|
@ -461,7 +455,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
sort: (i + 1) * CONST.SORT_INTEGER_DENSITY,
|
sort: (i + 1) * CONST.SORT_INTEGER_DENSITY,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.actor.updateEmbeddedDocuments("Item", updates);
|
this.actor.updateEmbeddedDocuments('Item', updates);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -473,7 +467,7 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
const item = await Item.implementation.fromDropData(data);
|
const item = await Item.implementation.fromDropData(data);
|
||||||
if (item && !this.actor.canOwnItemType(item.type)) {
|
if (item && !this.actor.canOwnItemType(item.type)) {
|
||||||
notifications.warn(
|
notifications.warn(
|
||||||
getGame().i18n.format("DS4.WarningActorCannotOwnItem", {
|
getGame().i18n.format('DS4.WarningActorCannotOwnItem', {
|
||||||
actorName: this.actor.name,
|
actorName: this.actor.name,
|
||||||
actorType: this.actor.type,
|
actorType: this.actor.type,
|
||||||
itemName: item.name,
|
itemName: item.name,
|
||||||
|
@ -491,12 +485,12 @@ export class DS4ActorSheet extends ActorSheet {
|
||||||
*/
|
*/
|
||||||
const embeddedDocumentListEntryProperties = Object.freeze({
|
const embeddedDocumentListEntryProperties = Object.freeze({
|
||||||
ActiveEffect: {
|
ActiveEffect: {
|
||||||
selector: ".effect",
|
selector: '.effect',
|
||||||
uuidDataAttribute: "effectUuid",
|
uuidDataAttribute: 'effectUuid',
|
||||||
},
|
},
|
||||||
Item: {
|
Item: {
|
||||||
selector: ".item",
|
selector: '.item',
|
||||||
uuidDataAttribute: "itemUuid",
|
uuidDataAttribute: 'itemUuid',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4ActorSheet } from "./base-sheet";
|
import { DS4ActorSheet } from './base-sheet';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Sheet class for DS4 Character Actors
|
* The Sheet class for DS4 Character Actors
|
||||||
|
@ -10,7 +10,7 @@ import { DS4ActorSheet } from "./base-sheet";
|
||||||
export class DS4CharacterActorSheet extends DS4ActorSheet {
|
export class DS4CharacterActorSheet extends DS4ActorSheet {
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
classes: ["sheet", "ds4-actor-sheet", "ds4-character-sheet"],
|
classes: ['sheet', 'ds4-actor-sheet', 'ds4-character-sheet'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4ActorSheet } from "./base-sheet";
|
import { DS4ActorSheet } from './base-sheet';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Sheet class for DS4 Creature Actors
|
* The Sheet class for DS4 Creature Actors
|
||||||
|
@ -10,17 +10,16 @@ import { DS4ActorSheet } from "./base-sheet";
|
||||||
export class DS4CreatureActorSheet extends DS4ActorSheet {
|
export class DS4CreatureActorSheet extends DS4ActorSheet {
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
classes: ["sheet", "ds4-actor-sheet", "ds4-creature-sheet"],
|
classes: ['sheet', 'ds4-actor-sheet', 'ds4-creature-sheet'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async getData(options = {}) {
|
async getData(options = {}) {
|
||||||
const context = await super.getData(options);
|
const context = await super.getData(options);
|
||||||
context.data.system.baseInfo.description = await TextEditor.enrichHTML(
|
context.data.system.baseInfo.description = await TextEditor.enrichHTML(context.data.system.baseInfo.description, {
|
||||||
context.data.system.baseInfo.description,
|
async: true,
|
||||||
{ async: true },
|
});
|
||||||
);
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from '../config';
|
||||||
import { DS4ActiveEffect } from "../documents/active-effect";
|
import { DS4ActiveEffect } from '../documents/active-effect';
|
||||||
import { enforce, getGame } from "../utils/utils";
|
import { enforce, getGame } from '../utils/utils';
|
||||||
import { disableOverriddenFields } from "./sheet-helpers";
|
import { disableOverriddenFields } from './sheet-helpers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Sheet class for DS4 Items
|
* The Sheet class for DS4 Items
|
||||||
|
@ -16,17 +16,17 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||||
classes: ["sheet", "ds4-item-sheet"],
|
classes: ['sheet', 'ds4-item-sheet'],
|
||||||
height: 400,
|
height: 400,
|
||||||
scrollY: [".ds4-sheet-body"],
|
scrollY: ['.ds4-sheet-body'],
|
||||||
tabs: [{ navSelector: ".ds4-sheet-tab-nav", contentSelector: ".ds4-sheet-body", initial: "description" }],
|
tabs: [{ navSelector: '.ds4-sheet-tab-nav', contentSelector: '.ds4-sheet-body', initial: 'description' }],
|
||||||
width: 540,
|
width: 540,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get template() {
|
get template() {
|
||||||
const basePath = "systems/ds4/templates/sheets/item";
|
const basePath = 'systems/ds4/templates/sheets/item';
|
||||||
return `${basePath}/${this.item.type}-sheet.hbs`;
|
return `${basePath}/${this.item.type}-sheet.hbs`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,9 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
setPosition(options = {}) {
|
setPosition(options = {}) {
|
||||||
const position = super.setPosition(options);
|
const position = super.setPosition(options);
|
||||||
if (position) {
|
if (position) {
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
const sheetBody = this.element.find('.sheet-body');
|
||||||
const bodyHeight = position.height - 192;
|
const bodyHeight = position.height - 192;
|
||||||
sheetBody.css("height", bodyHeight);
|
sheetBody.css('height', bodyHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
return position;
|
return position;
|
||||||
|
@ -77,7 +77,7 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
|
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
|
html.find('.control-effect').on('click', this.onControlEffect.bind(this));
|
||||||
|
|
||||||
disableOverriddenFields(this.form, this.item.overrides, (key) => `[name="${key}"]`);
|
disableOverriddenFields(this.form, this.item.overrides, (key) => `[name="${key}"]`);
|
||||||
}
|
}
|
||||||
|
@ -92,12 +92,12 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
onControlEffect(event) {
|
onControlEffect(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const a = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
switch (a.dataset["action"]) {
|
switch (a.dataset['action']) {
|
||||||
case "create":
|
case 'create':
|
||||||
return this.onCreateEffect();
|
return this.onCreateEffect();
|
||||||
case "edit":
|
case 'edit':
|
||||||
return this.onEditEffect(event);
|
return this.onEditEffect(event);
|
||||||
case "delete":
|
case 'delete':
|
||||||
return this.onDeleteEffect(event);
|
return this.onDeleteEffect(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,7 +121,7 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
.parents(embeddedDocumentListEntryProperties.ActiveEffect.selector)
|
.parents(embeddedDocumentListEntryProperties.ActiveEffect.selector)
|
||||||
.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
||||||
const effect = this.item.effects.get(id);
|
const effect = this.item.effects.get(id);
|
||||||
enforce(effect, getGame().i18n.format("DS4.ErrorItemDoesNotHaveEffect", { id, item: this.item.name }));
|
enforce(effect, getGame().i18n.format('DS4.ErrorItemDoesNotHaveEffect', { id, item: this.item.name }));
|
||||||
effect.sheet?.render(true);
|
effect.sheet?.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
onDeleteEffect(event) {
|
onDeleteEffect(event) {
|
||||||
const li = $(event.currentTarget).parents(embeddedDocumentListEntryProperties.ActiveEffect.selector);
|
const li = $(event.currentTarget).parents(embeddedDocumentListEntryProperties.ActiveEffect.selector);
|
||||||
const id = li.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
const id = li.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
||||||
this.item.deleteEmbeddedDocuments("ActiveEffect", [id]);
|
this.item.deleteEmbeddedDocuments('ActiveEffect', [id]);
|
||||||
li.slideUp(200, () => this.render(false));
|
li.slideUp(200, () => this.render(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ export class DS4ItemSheet extends ItemSheet {
|
||||||
*/
|
*/
|
||||||
const embeddedDocumentListEntryProperties = Object.freeze({
|
const embeddedDocumentListEntryProperties = Object.freeze({
|
||||||
ActiveEffect: {
|
ActiveEffect: {
|
||||||
selector: ".effect",
|
selector: '.effect',
|
||||||
idDataAttribute: "effectId",
|
idDataAttribute: 'effectId',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable elements in the given form that match the selector returned for overridden properties.
|
* Disable elements in the given form that match the selector returned for overridden properties.
|
||||||
|
@ -11,17 +11,17 @@ import { getGame } from "../utils/utils";
|
||||||
* @param {(key: string) => string} selector A function that generates a selector, based on a property key
|
* @param {(key: string) => string} selector A function that generates a selector, based on a property key
|
||||||
*/
|
*/
|
||||||
export function disableOverriddenFields(form, overrides, selector) {
|
export function disableOverriddenFields(form, overrides, selector) {
|
||||||
const inputs = ["INPUT", "SELECT", "TEXTAREA", "BUTTON"];
|
const inputs = ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'];
|
||||||
const titleAddition = `(${getGame().i18n.localize("DS4.TooltipNotEditableDueToEffects")})`;
|
const titleAddition = `(${getGame().i18n.localize('DS4.TooltipNotEditableDueToEffects')})`;
|
||||||
|
|
||||||
for (const key of Object.keys(foundry.utils.flattenObject(overrides))) {
|
for (const key of Object.keys(foundry.utils.flattenObject(overrides))) {
|
||||||
const elements = form?.querySelectorAll(selector(key));
|
const elements = form?.querySelectorAll(selector(key));
|
||||||
elements?.forEach((element) => {
|
elements?.forEach((element) => {
|
||||||
if (inputs.includes(element.tagName) && !element.hasAttribute("disabled")) {
|
if (inputs.includes(element.tagName) && !element.hasAttribute('disabled')) {
|
||||||
element.setAttribute("disabled", "");
|
element.setAttribute('disabled', '');
|
||||||
const title = element.getAttribute("title");
|
const title = element.getAttribute('title');
|
||||||
const newTitle = title === null ? titleAddition : `${title} ${titleAddition}`;
|
const newTitle = title === null ? titleAddition : `${title} ${titleAddition}`;
|
||||||
element.setAttribute("title", newTitle);
|
element.setAttribute('title', newTitle);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
462
src/config.ts
462
src/config.ts
|
@ -10,348 +10,348 @@ const i18nKeys = {
|
||||||
* Define the set of acttack types that can be performed with weapon items
|
* Define the set of acttack types that can be performed with weapon items
|
||||||
*/
|
*/
|
||||||
attackTypes: {
|
attackTypes: {
|
||||||
melee: "DS4.AttackTypeMelee",
|
melee: 'DS4.AttackTypeMelee',
|
||||||
ranged: "DS4.AttackTypeRanged",
|
ranged: 'DS4.AttackTypeRanged',
|
||||||
meleeRanged: "DS4.AttackTypeMeleeRanged",
|
meleeRanged: 'DS4.AttackTypeMeleeRanged',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of item availabilties
|
* Define the set of item availabilties
|
||||||
*/
|
*/
|
||||||
itemAvailabilities: {
|
itemAvailabilities: {
|
||||||
unset: "DS4.ItemAvailabilityUnset",
|
unset: 'DS4.ItemAvailabilityUnset',
|
||||||
hamlet: "DS4.ItemAvailabilityHamlet",
|
hamlet: 'DS4.ItemAvailabilityHamlet',
|
||||||
village: "DS4.ItemAvailabilityVilage",
|
village: 'DS4.ItemAvailabilityVilage',
|
||||||
city: "DS4.ItemAvailabilityCity",
|
city: 'DS4.ItemAvailabilityCity',
|
||||||
elves: "DS4.ItemAvailabilityElves",
|
elves: 'DS4.ItemAvailabilityElves',
|
||||||
dwarves: "DS4.ItemAvailabilityDwarves",
|
dwarves: 'DS4.ItemAvailabilityDwarves',
|
||||||
nowhere: "DS4.ItemAvailabilityNowhere",
|
nowhere: 'DS4.ItemAvailabilityNowhere',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of item types
|
* Define the set of item types
|
||||||
*/
|
*/
|
||||||
itemTypes: {
|
itemTypes: {
|
||||||
weapon: "DS4.ItemTypeWeapon",
|
weapon: 'DS4.ItemTypeWeapon',
|
||||||
armor: "DS4.ItemTypeArmor",
|
armor: 'DS4.ItemTypeArmor',
|
||||||
shield: "DS4.ItemTypeShield",
|
shield: 'DS4.ItemTypeShield',
|
||||||
spell: "DS4.ItemTypeSpell",
|
spell: 'DS4.ItemTypeSpell',
|
||||||
equipment: "DS4.ItemTypeEquipment",
|
equipment: 'DS4.ItemTypeEquipment',
|
||||||
loot: "DS4.ItemTypeLoot",
|
loot: 'DS4.ItemTypeLoot',
|
||||||
talent: "DS4.ItemTypeTalent",
|
talent: 'DS4.ItemTypeTalent',
|
||||||
racialAbility: "DS4.ItemTypeRacialAbility",
|
racialAbility: 'DS4.ItemTypeRacialAbility',
|
||||||
language: "DS4.ItemTypeLanguage",
|
language: 'DS4.ItemTypeLanguage',
|
||||||
alphabet: "DS4.ItemTypeAlphabet",
|
alphabet: 'DS4.ItemTypeAlphabet',
|
||||||
specialCreatureAbility: "DS4.ItemTypeSpecialCreatureAbility",
|
specialCreatureAbility: 'DS4.ItemTypeSpecialCreatureAbility',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of armor types, a character may only wear one item of each at any given time
|
* Define the set of armor types, a character may only wear one item of each at any given time
|
||||||
*/
|
*/
|
||||||
armorTypes: {
|
armorTypes: {
|
||||||
body: "DS4.ArmorTypeBody",
|
body: 'DS4.ArmorTypeBody',
|
||||||
helmet: "DS4.ArmorTypeHelmet",
|
helmet: 'DS4.ArmorTypeHelmet',
|
||||||
vambrace: "DS4.ArmorTypeVambrace",
|
vambrace: 'DS4.ArmorTypeVambrace',
|
||||||
greaves: "DS4.ArmorTypeGreaves",
|
greaves: 'DS4.ArmorTypeGreaves',
|
||||||
vambraceGreaves: "DS4.ArmorTypeVambraceGreaves",
|
vambraceGreaves: 'DS4.ArmorTypeVambraceGreaves',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define abbreviations for the armor types
|
* Define abbreviations for the armor types
|
||||||
*/
|
*/
|
||||||
armorTypesAbbr: {
|
armorTypesAbbr: {
|
||||||
body: "DS4.ArmorTypeBodyAbbr",
|
body: 'DS4.ArmorTypeBodyAbbr',
|
||||||
helmet: "DS4.ArmorTypeHelmetAbbr",
|
helmet: 'DS4.ArmorTypeHelmetAbbr',
|
||||||
vambrace: "DS4.ArmorTypeVambraceAbbr",
|
vambrace: 'DS4.ArmorTypeVambraceAbbr',
|
||||||
greaves: "DS4.ArmorTypeGreavesAbbr",
|
greaves: 'DS4.ArmorTypeGreavesAbbr',
|
||||||
vambraceGreaves: "DS4.ArmorTypeVambraceGreavesAbbr",
|
vambraceGreaves: 'DS4.ArmorTypeVambraceGreavesAbbr',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of armor materials, used to determine if a character 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',
|
||||||
leather: "DS4.ArmorMaterialTypeLeather",
|
leather: 'DS4.ArmorMaterialTypeLeather',
|
||||||
chain: "DS4.ArmorMaterialTypeChain",
|
chain: 'DS4.ArmorMaterialTypeChain',
|
||||||
plate: "DS4.ArmorMaterialTypePlate",
|
plate: 'DS4.ArmorMaterialTypePlate',
|
||||||
natural: "DS4.ArmorMaterialTypeNatural",
|
natural: 'DS4.ArmorMaterialTypeNatural',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the abbreviations of armor materials
|
* Define the abbreviations of armor materials
|
||||||
*/
|
*/
|
||||||
armorMaterialTypesAbbr: {
|
armorMaterialTypesAbbr: {
|
||||||
cloth: "DS4.ArmorMaterialTypeClothAbbr",
|
cloth: 'DS4.ArmorMaterialTypeClothAbbr',
|
||||||
leather: "DS4.ArmorMaterialTypeLeatherAbbr",
|
leather: 'DS4.ArmorMaterialTypeLeatherAbbr',
|
||||||
chain: "DS4.ArmorMaterialTypeChainAbbr",
|
chain: 'DS4.ArmorMaterialTypeChainAbbr',
|
||||||
plate: "DS4.ArmorMaterialTypePlateAbbr",
|
plate: 'DS4.ArmorMaterialTypePlateAbbr',
|
||||||
natural: "DS4.ArmorMaterialTypeNaturalAbbr",
|
natural: 'DS4.ArmorMaterialTypeNaturalAbbr',
|
||||||
},
|
},
|
||||||
|
|
||||||
spellTypes: {
|
spellTypes: {
|
||||||
spellcasting: "DS4.SpellTypeSpellcasting",
|
spellcasting: 'DS4.SpellTypeSpellcasting',
|
||||||
targetedSpellcasting: "DS4.SpellTypeTargetedSpellcasting",
|
targetedSpellcasting: 'DS4.SpellTypeTargetedSpellcasting',
|
||||||
},
|
},
|
||||||
|
|
||||||
spellGroups: {
|
spellGroups: {
|
||||||
lightning: "DS4.SpellGroupLightning",
|
lightning: 'DS4.SpellGroupLightning',
|
||||||
earth: "DS4.SpellGroupEarth",
|
earth: 'DS4.SpellGroupEarth',
|
||||||
water: "DS4.SpellGroupWater",
|
water: 'DS4.SpellGroupWater',
|
||||||
ice: "DS4.SpellGroupIce",
|
ice: 'DS4.SpellGroupIce',
|
||||||
fire: "DS4.SpellGroupFire",
|
fire: 'DS4.SpellGroupFire',
|
||||||
healing: "DS4.SpellGroupHealing",
|
healing: 'DS4.SpellGroupHealing',
|
||||||
light: "DS4.SpellGroupLight",
|
light: 'DS4.SpellGroupLight',
|
||||||
air: "DS4.SpellGroupAir",
|
air: 'DS4.SpellGroupAir',
|
||||||
transport: "DS4.SpellGroupTransport",
|
transport: 'DS4.SpellGroupTransport',
|
||||||
damage: "DS4.SpellGroupDamage",
|
damage: 'DS4.SpellGroupDamage',
|
||||||
shadow: "DS4.SpellGroupShadow",
|
shadow: 'DS4.SpellGroupShadow',
|
||||||
protection: "DS4.SpellGroupProtection",
|
protection: 'DS4.SpellGroupProtection',
|
||||||
mindAffecting: "DS4.SpellGroupMindAffecting",
|
mindAffecting: 'DS4.SpellGroupMindAffecting',
|
||||||
demonology: "DS4.SpellGroupDemonology",
|
demonology: 'DS4.SpellGroupDemonology',
|
||||||
necromancy: "DS4.SpellGroupNecromancy",
|
necromancy: 'DS4.SpellGroupNecromancy',
|
||||||
transmutation: "DS4.SpellGroupTransmutation",
|
transmutation: 'DS4.SpellGroupTransmutation',
|
||||||
area: "DS4.SpellGroupArea",
|
area: 'DS4.SpellGroupArea',
|
||||||
},
|
},
|
||||||
|
|
||||||
cooldownDurations: {
|
cooldownDurations: {
|
||||||
"0r": "DS4.CooldownDuration0R",
|
'0r': 'DS4.CooldownDuration0R',
|
||||||
"1r": "DS4.CooldownDuration1R",
|
'1r': 'DS4.CooldownDuration1R',
|
||||||
"2r": "DS4.CooldownDuration2R",
|
'2r': 'DS4.CooldownDuration2R',
|
||||||
"5r": "DS4.CooldownDuration5R",
|
'5r': 'DS4.CooldownDuration5R',
|
||||||
"10r": "DS4.CooldownDuration10R",
|
'10r': 'DS4.CooldownDuration10R',
|
||||||
"100r": "DS4.CooldownDuration100R",
|
'100r': 'DS4.CooldownDuration100R',
|
||||||
"1d": "DS4.CooldownDuration1D",
|
'1d': 'DS4.CooldownDuration1D',
|
||||||
d20d: "DS4.CooldownDurationD20D",
|
d20d: 'DS4.CooldownDurationD20D',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of actor types
|
* Define the set of actor types
|
||||||
*/
|
*/
|
||||||
actorTypes: {
|
actorTypes: {
|
||||||
character: "DS4.ActorTypeCharacter",
|
character: 'DS4.ActorTypeCharacter',
|
||||||
creature: "DS4.ActorTypeCreature",
|
creature: 'DS4.ActorTypeCreature',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of attributes an actor has
|
* Define the set of attributes an actor has
|
||||||
*/
|
*/
|
||||||
attributes: {
|
attributes: {
|
||||||
body: "DS4.AttributeBody",
|
body: 'DS4.AttributeBody',
|
||||||
mobility: "DS4.AttributeMobility",
|
mobility: 'DS4.AttributeMobility',
|
||||||
mind: "DS4.AttributeMind",
|
mind: 'DS4.AttributeMind',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of traits an actor has
|
* Define the set of traits an actor has
|
||||||
*/
|
*/
|
||||||
traits: {
|
traits: {
|
||||||
strength: "DS4.TraitStrength",
|
strength: 'DS4.TraitStrength',
|
||||||
agility: "DS4.TraitAgility",
|
agility: 'DS4.TraitAgility',
|
||||||
intellect: "DS4.TraitIntellect",
|
intellect: 'DS4.TraitIntellect',
|
||||||
constitution: "DS4.TraitConstitution",
|
constitution: 'DS4.TraitConstitution',
|
||||||
dexterity: "DS4.TraitDexterity",
|
dexterity: 'DS4.TraitDexterity',
|
||||||
aura: "DS4.TraitAura",
|
aura: 'DS4.TraitAura',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the set of combat values an actor has
|
* Define the set of combat values an actor has
|
||||||
*/
|
*/
|
||||||
combatValues: {
|
combatValues: {
|
||||||
hitPoints: "DS4.CombatValuesHitPoints",
|
hitPoints: 'DS4.CombatValuesHitPoints',
|
||||||
defense: "DS4.CombatValuesDefense",
|
defense: 'DS4.CombatValuesDefense',
|
||||||
initiative: "DS4.CombatValuesInitiative",
|
initiative: 'DS4.CombatValuesInitiative',
|
||||||
movement: "DS4.CombatValuesMovement",
|
movement: 'DS4.CombatValuesMovement',
|
||||||
meleeAttack: "DS4.CombatValuesMeleeAttack",
|
meleeAttack: 'DS4.CombatValuesMeleeAttack',
|
||||||
rangedAttack: "DS4.CombatValuesRangedAttack",
|
rangedAttack: 'DS4.CombatValuesRangedAttack',
|
||||||
spellcasting: "DS4.CombatValuesSpellcasting",
|
spellcasting: 'DS4.CombatValuesSpellcasting',
|
||||||
targetedSpellcasting: "DS4.CombatValuesTargetedSpellcasting",
|
targetedSpellcasting: 'DS4.CombatValuesTargetedSpellcasting',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The what do display in the actor sheets for the combat value text (in some languages, abbreviations are necessary)
|
* The what do display in the actor sheets for the combat value text (in some languages, abbreviations are necessary)
|
||||||
*/
|
*/
|
||||||
combatValuesSheet: {
|
combatValuesSheet: {
|
||||||
hitPoints: "DS4.CombatValuesHitPointsSheet",
|
hitPoints: 'DS4.CombatValuesHitPointsSheet',
|
||||||
defense: "DS4.CombatValuesDefenseSheet",
|
defense: 'DS4.CombatValuesDefenseSheet',
|
||||||
initiative: "DS4.CombatValuesInitiativeSheet",
|
initiative: 'DS4.CombatValuesInitiativeSheet',
|
||||||
movement: "DS4.CombatValuesMovementSheet",
|
movement: 'DS4.CombatValuesMovementSheet',
|
||||||
meleeAttack: "DS4.CombatValuesMeleeAttackSheet",
|
meleeAttack: 'DS4.CombatValuesMeleeAttackSheet',
|
||||||
rangedAttack: "DS4.CombatValuesRangedAttackSheet",
|
rangedAttack: 'DS4.CombatValuesRangedAttackSheet',
|
||||||
spellcasting: "DS4.CombatValuesSpellcastingSheet",
|
spellcasting: 'DS4.CombatValuesSpellcastingSheet',
|
||||||
targetedSpellcasting: "DS4.CombatValuesTargetedSpellcastingSheet",
|
targetedSpellcasting: 'DS4.CombatValuesTargetedSpellcastingSheet',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the base info of a character
|
* Define the base info of a character
|
||||||
*/
|
*/
|
||||||
characterBaseInfo: {
|
characterBaseInfo: {
|
||||||
race: "DS4.CharacterBaseInfoRace",
|
race: 'DS4.CharacterBaseInfoRace',
|
||||||
class: "DS4.CharacterBaseInfoClass",
|
class: 'DS4.CharacterBaseInfoClass',
|
||||||
heroClass: "DS4.CharacterBaseInfoHeroClass",
|
heroClass: 'DS4.CharacterBaseInfoHeroClass',
|
||||||
culture: "DS4.CharacterBaseInfoCulture",
|
culture: 'DS4.CharacterBaseInfoCulture',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the progression info of a character
|
* Define the progression info of a character
|
||||||
*/
|
*/
|
||||||
characterProgression: {
|
characterProgression: {
|
||||||
level: "DS4.CharacterProgressionLevel",
|
level: 'DS4.CharacterProgressionLevel',
|
||||||
experiencePoints: "DS4.CharacterProgressionExperiencePoints",
|
experiencePoints: 'DS4.CharacterProgressionExperiencePoints',
|
||||||
talentPoints: "DS4.CharacterProgressionTalentPoints",
|
talentPoints: 'DS4.CharacterProgressionTalentPoints',
|
||||||
progressPoints: "DS4.CharacterProgressionProgressPoints",
|
progressPoints: 'DS4.CharacterProgressionProgressPoints',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the language info of a character
|
* Define the language info of a character
|
||||||
*/
|
*/
|
||||||
characterLanguage: {
|
characterLanguage: {
|
||||||
languages: "DS4.CharacterLanguageLanguages",
|
languages: 'DS4.CharacterLanguageLanguages',
|
||||||
alphabets: "DS4.CharacterLanguageAlphabets",
|
alphabets: 'DS4.CharacterLanguageAlphabets',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the profile info of a character
|
* Define the profile info of a character
|
||||||
*/
|
*/
|
||||||
characterProfile: {
|
characterProfile: {
|
||||||
biography: "DS4.CharacterProfileBiography",
|
biography: 'DS4.CharacterProfileBiography',
|
||||||
gender: "DS4.CharacterProfileGender",
|
gender: 'DS4.CharacterProfileGender',
|
||||||
birthday: "DS4.CharacterProfileBirthday",
|
birthday: 'DS4.CharacterProfileBirthday',
|
||||||
birthplace: "DS4.CharacterProfileBirthplace",
|
birthplace: 'DS4.CharacterProfileBirthplace',
|
||||||
age: "DS4.CharacterProfileAge",
|
age: 'DS4.CharacterProfileAge',
|
||||||
height: "DS4.CharacterProfileHeight",
|
height: 'DS4.CharacterProfileHeight',
|
||||||
hairColor: "DS4.CharacterProfileHairColor",
|
hairColor: 'DS4.CharacterProfileHairColor',
|
||||||
weight: "DS4.CharacterProfileWeight",
|
weight: 'DS4.CharacterProfileWeight',
|
||||||
eyeColor: "DS4.CharacterProfileEyeColor",
|
eyeColor: 'DS4.CharacterProfileEyeColor',
|
||||||
specialCharacteristics: "DS4.CharacterProfileSpecialCharacteristics",
|
specialCharacteristics: 'DS4.CharacterProfileSpecialCharacteristics',
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Define currency elements of a character
|
* Define currency elements of a character
|
||||||
*/
|
*/
|
||||||
characterCurrency: {
|
characterCurrency: {
|
||||||
gold: "DS4.CharacterCurrencyGold",
|
gold: 'DS4.CharacterCurrencyGold',
|
||||||
silver: "DS4.CharacterCurrencySilver",
|
silver: 'DS4.CharacterCurrencySilver',
|
||||||
copper: "DS4.CharacterCurrencyCopper",
|
copper: 'DS4.CharacterCurrencyCopper',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the different creature types a creature can be
|
* Define the different creature types a creature can be
|
||||||
*/
|
*/
|
||||||
creatureTypes: {
|
creatureTypes: {
|
||||||
animal: "DS4.CreatureTypeAnimal",
|
animal: 'DS4.CreatureTypeAnimal',
|
||||||
construct: "DS4.CreatureTypeConstruct",
|
construct: 'DS4.CreatureTypeConstruct',
|
||||||
humanoid: "DS4.CreatureTypeHumanoid",
|
humanoid: 'DS4.CreatureTypeHumanoid',
|
||||||
magicalEntity: "DS4.CreatureTypeMagicalEntity",
|
magicalEntity: 'DS4.CreatureTypeMagicalEntity',
|
||||||
plantBeing: "DS4.CreatureTypePlantBeing",
|
plantBeing: 'DS4.CreatureTypePlantBeing',
|
||||||
undead: "DS4.CreatureTypeUndead",
|
undead: 'DS4.CreatureTypeUndead',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the different size categories creatures fall into
|
* Define the different size categories creatures fall into
|
||||||
*/
|
*/
|
||||||
creatureSizeCategories: {
|
creatureSizeCategories: {
|
||||||
tiny: "DS4.CreatureSizeCategoryTiny",
|
tiny: 'DS4.CreatureSizeCategoryTiny',
|
||||||
small: "DS4.CreatureSizeCategorySmall",
|
small: 'DS4.CreatureSizeCategorySmall',
|
||||||
normal: "DS4.CreatureSizeCategoryNormal",
|
normal: 'DS4.CreatureSizeCategoryNormal',
|
||||||
large: "DS4.CreatureSizeCategoryLarge",
|
large: 'DS4.CreatureSizeCategoryLarge',
|
||||||
huge: "DS4.CreatureSizeCategoryHuge",
|
huge: 'DS4.CreatureSizeCategoryHuge',
|
||||||
colossal: "DS4.CreatureSizeCategoryColossal",
|
colossal: 'DS4.CreatureSizeCategoryColossal',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the base info of a creature
|
* Define the base info of a creature
|
||||||
*/
|
*/
|
||||||
creatureBaseInfo: {
|
creatureBaseInfo: {
|
||||||
loot: "DS4.CreatureBaseInfoLoot",
|
loot: 'DS4.CreatureBaseInfoLoot',
|
||||||
foeFactor: "DS4.CreatureBaseInfoFoeFactor",
|
foeFactor: 'DS4.CreatureBaseInfoFoeFactor',
|
||||||
creatureType: "DS4.CreatureBaseInfoCreatureType",
|
creatureType: 'DS4.CreatureBaseInfoCreatureType',
|
||||||
sizeCategory: "DS4.CreatureBaseInfoSizeCategory",
|
sizeCategory: 'DS4.CreatureBaseInfoSizeCategory',
|
||||||
experiencePoints: "DS4.CreatureBaseInfoExperiencePoints",
|
experiencePoints: 'DS4.CreatureBaseInfoExperiencePoints',
|
||||||
description: "DS4.CreatureBaseInfoDescription",
|
description: 'DS4.CreatureBaseInfoDescription',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define translations for available distance units
|
* Define translations for available distance units
|
||||||
*/
|
*/
|
||||||
distanceUnits: {
|
distanceUnits: {
|
||||||
meter: "DS4.UnitMeters",
|
meter: 'DS4.UnitMeters',
|
||||||
kilometer: "DS4.UnitKilometers",
|
kilometer: 'DS4.UnitKilometers',
|
||||||
custom: "DS4.UnitCustom",
|
custom: 'DS4.UnitCustom',
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Define abbreviations for available distance units
|
* Define abbreviations for available distance units
|
||||||
*/
|
*/
|
||||||
distanceUnitsAbbr: {
|
distanceUnitsAbbr: {
|
||||||
meter: "DS4.UnitMetersAbbr",
|
meter: 'DS4.UnitMetersAbbr',
|
||||||
kilometer: "DS4.UnitKilometersAbbr",
|
kilometer: 'DS4.UnitKilometersAbbr',
|
||||||
custom: "DS4.UnitCustomAbbr",
|
custom: 'DS4.UnitCustomAbbr',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define translations for available duration units
|
* Define translations for available duration units
|
||||||
*/
|
*/
|
||||||
temporalUnits: {
|
temporalUnits: {
|
||||||
rounds: "DS4.UnitRounds",
|
rounds: 'DS4.UnitRounds',
|
||||||
minutes: "DS4.UnitMinutes",
|
minutes: 'DS4.UnitMinutes',
|
||||||
hours: "DS4.UnitHours",
|
hours: 'DS4.UnitHours',
|
||||||
days: "DS4.UnitDays",
|
days: 'DS4.UnitDays',
|
||||||
custom: "DS4.UnitCustom",
|
custom: 'DS4.UnitCustom',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define abbreviations for available duration units
|
* Define abbreviations for available duration units
|
||||||
*/
|
*/
|
||||||
temporalUnitsAbbr: {
|
temporalUnitsAbbr: {
|
||||||
rounds: "DS4.UnitRoundsAbbr",
|
rounds: 'DS4.UnitRoundsAbbr',
|
||||||
minutes: "DS4.UnitMinutesAbbr",
|
minutes: 'DS4.UnitMinutesAbbr',
|
||||||
hours: "DS4.UnitHoursAbbr",
|
hours: 'DS4.UnitHoursAbbr',
|
||||||
days: "DS4.UnitDaysAbbr",
|
days: 'DS4.UnitDaysAbbr',
|
||||||
custom: "DS4.UnitCustomAbbr",
|
custom: 'DS4.UnitCustomAbbr',
|
||||||
},
|
},
|
||||||
|
|
||||||
checks: {
|
checks: {
|
||||||
appraise: "DS4.ChecksAppraise",
|
appraise: 'DS4.ChecksAppraise',
|
||||||
changeSpell: "DS4.ChecksChangeSpell",
|
changeSpell: 'DS4.ChecksChangeSpell',
|
||||||
climb: "DS4.ChecksClimb",
|
climb: 'DS4.ChecksClimb',
|
||||||
communicate: "DS4.ChecksCommunicate",
|
communicate: 'DS4.ChecksCommunicate',
|
||||||
decipherScript: "DS4.ChecksDecipherScript",
|
decipherScript: 'DS4.ChecksDecipherScript',
|
||||||
defend: "DS4.ChecksDefend",
|
defend: 'DS4.ChecksDefend',
|
||||||
defyPoison: "DS4.ChecksDefyPoison",
|
defyPoison: 'DS4.ChecksDefyPoison',
|
||||||
disableTraps: "DS4.ChecksDisableTraps",
|
disableTraps: 'DS4.ChecksDisableTraps',
|
||||||
featOfStrength: "DS4.ChecksFeatOfStrength",
|
featOfStrength: 'DS4.ChecksFeatOfStrength',
|
||||||
flirt: "DS4.ChecksFlirt",
|
flirt: 'DS4.ChecksFlirt',
|
||||||
haggle: "DS4.ChecksHaggle",
|
haggle: 'DS4.ChecksHaggle',
|
||||||
hide: "DS4.ChecksHide",
|
hide: 'DS4.ChecksHide',
|
||||||
identifyMagic: "DS4.ChecksIdentifyMagic",
|
identifyMagic: 'DS4.ChecksIdentifyMagic',
|
||||||
jump: "DS4.ChecksJump",
|
jump: 'DS4.ChecksJump',
|
||||||
knowledge: "DS4.ChecksKnowledge",
|
knowledge: 'DS4.ChecksKnowledge',
|
||||||
openLock: "DS4.ChecksOpenLock",
|
openLock: 'DS4.ChecksOpenLock',
|
||||||
perception: "DS4.ChecksPerception",
|
perception: 'DS4.ChecksPerception',
|
||||||
pickPocket: "DS4.ChecksPickPocket",
|
pickPocket: 'DS4.ChecksPickPocket',
|
||||||
readTracks: "DS4.ChecksReadTracks",
|
readTracks: 'DS4.ChecksReadTracks',
|
||||||
resistDisease: "DS4.ChecksResistDisease",
|
resistDisease: 'DS4.ChecksResistDisease',
|
||||||
ride: "DS4.ChecksRide",
|
ride: 'DS4.ChecksRide',
|
||||||
search: "DS4.ChecksSearch",
|
search: 'DS4.ChecksSearch',
|
||||||
senseMagic: "DS4.ChecksSenseMagic",
|
senseMagic: 'DS4.ChecksSenseMagic',
|
||||||
sneak: "DS4.ChecksSneak",
|
sneak: 'DS4.ChecksSneak',
|
||||||
startFire: "DS4.ChecksStartFire",
|
startFire: 'DS4.ChecksStartFire',
|
||||||
swim: "DS4.ChecksSwim",
|
swim: 'DS4.ChecksSwim',
|
||||||
wakeUp: "DS4.ChecksWakeUp",
|
wakeUp: 'DS4.ChecksWakeUp',
|
||||||
workMechanism: "DS4.ChecksWorkMechanism",
|
workMechanism: 'DS4.ChecksWorkMechanism',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translations for the standard check modifiers
|
* Translations for the standard check modifiers
|
||||||
*/
|
*/
|
||||||
checkModifiers: {
|
checkModifiers: {
|
||||||
routine: "DS4.CheckModifierRoutine",
|
routine: 'DS4.CheckModifierRoutine',
|
||||||
veryEasy: "DS4.CheckModifierVeryEasy",
|
veryEasy: 'DS4.CheckModifierVeryEasy',
|
||||||
easy: "DS4.CheckModifierEasy",
|
easy: 'DS4.CheckModifierEasy',
|
||||||
normal: "DS4.CheckModifierMormal",
|
normal: 'DS4.CheckModifierMormal',
|
||||||
difficult: "DS4.CheckModifierDifficult",
|
difficult: 'DS4.CheckModifierDifficult',
|
||||||
veryDifficult: "DS4.CheckModifierVeryDifficult",
|
veryDifficult: 'DS4.CheckModifierVeryDifficult',
|
||||||
extremelyDifficult: "DS4.CheckModifierExtremelyDifficult",
|
extremelyDifficult: 'DS4.CheckModifierExtremelyDifficult',
|
||||||
custom: "DS4.CheckModifierCustom",
|
custom: 'DS4.CheckModifierCustom',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -385,51 +385,51 @@ export const DS4 = {
|
||||||
* Define the file paths to icon images
|
* Define the file paths to icon images
|
||||||
*/
|
*/
|
||||||
attackTypes: {
|
attackTypes: {
|
||||||
melee: "systems/ds4/assets/icons/official/combat-values/melee-attack.png",
|
melee: 'systems/ds4/assets/icons/official/combat-values/melee-attack.png',
|
||||||
meleeRanged: "systems/ds4/assets/icons/official/combat-values/melee-ranged-attack.png",
|
meleeRanged: 'systems/ds4/assets/icons/official/combat-values/melee-ranged-attack.png',
|
||||||
ranged: "systems/ds4/assets/icons/official/combat-values/ranged-attack.png",
|
ranged: 'systems/ds4/assets/icons/official/combat-values/ranged-attack.png',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the file paths to icon images
|
* Define the file paths to icon images
|
||||||
*/
|
*/
|
||||||
spellTypes: {
|
spellTypes: {
|
||||||
spellcasting: "systems/ds4/assets/icons/official/combat-values/spellcasting.png",
|
spellcasting: 'systems/ds4/assets/icons/official/combat-values/spellcasting.png',
|
||||||
targetedSpellcasting: "systems/ds4/assets/icons/official/combat-values/targeted-spellcasting.png",
|
targetedSpellcasting: 'systems/ds4/assets/icons/official/combat-values/targeted-spellcasting.png',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the file paths to check images
|
* Define the file paths to check images
|
||||||
*/
|
*/
|
||||||
checks: {
|
checks: {
|
||||||
appraise: "systems/ds4/assets/icons/game-icons/delapouite/two-coins.svg",
|
appraise: 'systems/ds4/assets/icons/game-icons/delapouite/two-coins.svg',
|
||||||
changeSpell: "systems/ds4/assets/icons/game-icons/delapouite/card-exchange.svg",
|
changeSpell: 'systems/ds4/assets/icons/game-icons/delapouite/card-exchange.svg',
|
||||||
climb: "systems/ds4/assets/icons/game-icons/caro-asercion/mountain-climbing.svg",
|
climb: 'systems/ds4/assets/icons/game-icons/caro-asercion/mountain-climbing.svg',
|
||||||
communicate: "systems/ds4/assets/icons/game-icons/delapouite/discussion.svg",
|
communicate: 'systems/ds4/assets/icons/game-icons/delapouite/discussion.svg',
|
||||||
decipherScript: "systems/ds4/assets/icons/game-icons/lorc/rune-stone.svg",
|
decipherScript: 'systems/ds4/assets/icons/game-icons/lorc/rune-stone.svg',
|
||||||
defend: "systems/ds4/assets/icons/game-icons/sbed/shield.svg",
|
defend: 'systems/ds4/assets/icons/game-icons/sbed/shield.svg',
|
||||||
defyPoison: "systems/ds4/assets/icons/game-icons/lorc/poison-bottle.svg",
|
defyPoison: 'systems/ds4/assets/icons/game-icons/lorc/poison-bottle.svg',
|
||||||
disableTraps: "systems/ds4/assets/icons/game-icons/lorc/wolf-trap.svg",
|
disableTraps: 'systems/ds4/assets/icons/game-icons/lorc/wolf-trap.svg',
|
||||||
featOfStrength: "systems/ds4/assets/icons/game-icons/delapouite/biceps.svg",
|
featOfStrength: 'systems/ds4/assets/icons/game-icons/delapouite/biceps.svg',
|
||||||
flirt: "systems/ds4/assets/icons/game-icons/lorc/charm.svg",
|
flirt: 'systems/ds4/assets/icons/game-icons/lorc/charm.svg',
|
||||||
haggle: "systems/ds4/assets/icons/game-icons/lorc/cash.svg",
|
haggle: 'systems/ds4/assets/icons/game-icons/lorc/cash.svg',
|
||||||
hide: "systems/ds4/assets/icons/game-icons/lorc/hidden.svg",
|
hide: 'systems/ds4/assets/icons/game-icons/lorc/hidden.svg',
|
||||||
identifyMagic: "systems/ds4/assets/icons/game-icons/lorc/uncertainty.svg",
|
identifyMagic: 'systems/ds4/assets/icons/game-icons/lorc/uncertainty.svg',
|
||||||
jump: "systems/ds4/assets/icons/game-icons/delapouite/jump-across.svg",
|
jump: 'systems/ds4/assets/icons/game-icons/delapouite/jump-across.svg',
|
||||||
knowledge: "systems/ds4/assets/icons/game-icons/delapouite/bookshelf.svg",
|
knowledge: 'systems/ds4/assets/icons/game-icons/delapouite/bookshelf.svg',
|
||||||
openLock: "systems/ds4/assets/icons/game-icons/delapouite/padlock-open.svg",
|
openLock: 'systems/ds4/assets/icons/game-icons/delapouite/padlock-open.svg',
|
||||||
perception: "systems/ds4/assets/icons/game-icons/lorc/awareness.svg",
|
perception: 'systems/ds4/assets/icons/game-icons/lorc/awareness.svg',
|
||||||
pickPocket: "systems/ds4/assets/icons/game-icons/darkzaitev/robber-hand.svg",
|
pickPocket: 'systems/ds4/assets/icons/game-icons/darkzaitev/robber-hand.svg',
|
||||||
readTracks: "systems/ds4/assets/icons/game-icons/delapouite/deer-track.svg",
|
readTracks: 'systems/ds4/assets/icons/game-icons/delapouite/deer-track.svg',
|
||||||
resistDisease: "systems/ds4/assets/icons/game-icons/lorc/virus.svg",
|
resistDisease: 'systems/ds4/assets/icons/game-icons/lorc/virus.svg',
|
||||||
ride: "systems/ds4/assets/icons/game-icons/delapouite/cavalry.svg",
|
ride: 'systems/ds4/assets/icons/game-icons/delapouite/cavalry.svg',
|
||||||
search: "systems/ds4/assets/icons/game-icons/lorc/magnifying-glass.svg",
|
search: 'systems/ds4/assets/icons/game-icons/lorc/magnifying-glass.svg',
|
||||||
senseMagic: "systems/ds4/assets/icons/game-icons/delapouite/sparkles.svg",
|
senseMagic: 'systems/ds4/assets/icons/game-icons/delapouite/sparkles.svg',
|
||||||
sneak: "systems/ds4/assets/icons/game-icons/delapouite/mute.svg",
|
sneak: 'systems/ds4/assets/icons/game-icons/delapouite/mute.svg',
|
||||||
startFire: "systems/ds4/assets/icons/game-icons/lorc/campfire.svg",
|
startFire: 'systems/ds4/assets/icons/game-icons/lorc/campfire.svg',
|
||||||
swim: "systems/ds4/assets/icons/game-icons/delapouite/pool-dive.svg",
|
swim: 'systems/ds4/assets/icons/game-icons/delapouite/pool-dive.svg',
|
||||||
wakeUp: "systems/ds4/assets/icons/game-icons/delapouite/alarm-clock.svg",
|
wakeUp: 'systems/ds4/assets/icons/game-icons/delapouite/alarm-clock.svg',
|
||||||
workMechanism: "systems/ds4/assets/icons/game-icons/lorc/lever.svg",
|
workMechanism: 'systems/ds4/assets/icons/game-icons/lorc/lever.svg',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -437,16 +437,16 @@ export const DS4 = {
|
||||||
* Profile info types for handlebars of a character
|
* Profile info types for handlebars of a character
|
||||||
*/
|
*/
|
||||||
characterProfileDTypes: {
|
characterProfileDTypes: {
|
||||||
biography: "String",
|
biography: 'String',
|
||||||
gender: "String",
|
gender: 'String',
|
||||||
birthday: "String",
|
birthday: 'String',
|
||||||
birthplace: "String",
|
birthplace: 'String',
|
||||||
age: "Number",
|
age: 'Number',
|
||||||
height: "Number",
|
height: 'Number',
|
||||||
hairColor: "String",
|
hairColor: 'String',
|
||||||
weight: "Number",
|
weight: 'Number',
|
||||||
eyeColor: "String",
|
eyeColor: 'String',
|
||||||
specialCharacteristics: "String",
|
specialCharacteristics: 'String',
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
|
|
||||||
export function evaluateCheck(
|
export function evaluateCheck(
|
||||||
dice: number[],
|
dice: number[],
|
||||||
|
@ -41,7 +41,7 @@ function assignSubChecksToDice(
|
||||||
const requiredNumberOfDice = getRequiredNumberOfDice(checkTargetNumber);
|
const requiredNumberOfDice = getRequiredNumberOfDice(checkTargetNumber);
|
||||||
|
|
||||||
if (dice.length !== requiredNumberOfDice || requiredNumberOfDice < 1) {
|
if (dice.length !== requiredNumberOfDice || requiredNumberOfDice < 1) {
|
||||||
throw new Error(getGame().i18n.localize("DS4.ErrorInvalidNumberOfDice"));
|
throw new Error(getGame().i18n.localize('DS4.ErrorInvalidNumberOfDice'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const checkTargetNumberForLastSubCheck = checkTargetNumber - 20 * (requiredNumberOfDice - 1);
|
const checkTargetNumberForLastSubCheck = checkTargetNumber - 20 * (requiredNumberOfDice - 1);
|
||||||
|
@ -68,8 +68,7 @@ function findIndexOfSmallestNonCoup(dice: number[], maximumCoupResult: number):
|
||||||
.map((die, index): [number, number] => [die, index])
|
.map((die, index): [number, number] => [die, index])
|
||||||
.filter((indexedDie) => indexedDie[0] > maximumCoupResult)
|
.filter((indexedDie) => indexedDie[0] > maximumCoupResult)
|
||||||
.reduce(
|
.reduce(
|
||||||
(smallestIndexedDie, indexedDie) =>
|
(smallestIndexedDie, indexedDie) => (indexedDie[0] < smallestIndexedDie[0] ? indexedDie : smallestIndexedDie),
|
||||||
indexedDie[0] < smallestIndexedDie[0] ? indexedDie : smallestIndexedDie,
|
|
||||||
[Infinity, -1],
|
[Infinity, -1],
|
||||||
)[1];
|
)[1];
|
||||||
}
|
}
|
||||||
|
@ -90,7 +89,7 @@ function shouldUseCoupForLastSubCheck(
|
||||||
!Number.isInteger(indexOfSmallestNonCoup) ||
|
!Number.isInteger(indexOfSmallestNonCoup) ||
|
||||||
smallestNonCoup === undefined
|
smallestNonCoup === undefined
|
||||||
) {
|
) {
|
||||||
throw new Error("Received an invalid value for the parameter indexOfSmallestNonCoup or indexOfFirstCoup,");
|
throw new Error('Received an invalid value for the parameter indexOfSmallestNonCoup or indexOfFirstCoup,');
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
indexOfFirstCoup !== -1 &&
|
indexOfFirstCoup !== -1 &&
|
||||||
|
|
|
@ -3,9 +3,9 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DialogWithListeners } from "../apps/dialog-with-listeners";
|
import { DialogWithListeners } from '../apps/dialog-with-listeners';
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from '../config';
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
|
|
||||||
/** @typedef {"publicroll" | "gmroll" | "gmroll" | "selfroll"} RollModes */
|
/** @typedef {"publicroll" | "gmroll" | "gmroll" | "selfroll"} RollModes */
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class CheckFactory {
|
||||||
maximumCoupResult: 1,
|
maximumCoupResult: 1,
|
||||||
minimumFumbleResult: 20,
|
minimumFumbleResult: 20,
|
||||||
useSlayingDice: false,
|
useSlayingDice: false,
|
||||||
rollMode: "publicroll",
|
rollMode: 'publicroll',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,7 @@ class CheckFactory {
|
||||||
* Execute this check factory.
|
* Execute this check factory.
|
||||||
* @returns {Promise<ChatMessage | undefined>} A promise that resolves to the created chat message for the roll */
|
* @returns {Promise<ChatMessage | undefined>} A promise that resolves to the created chat message for the roll */
|
||||||
async execute() {
|
async execute() {
|
||||||
const innerFormula = ["ds", this.createCheckTargetNumberModifier(), this.createCoupFumbleModifier()].filterJoin(
|
const innerFormula = ['ds', this.createCheckTargetNumberModifier(), this.createCoupFumbleModifier()].filterJoin('');
|
||||||
"",
|
|
||||||
);
|
|
||||||
const formula = this.#options.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
|
const formula = this.#options.useSlayingDice ? `{${innerFormula}}x` : innerFormula;
|
||||||
const roll = Roll.create(formula);
|
const roll = Roll.create(formula);
|
||||||
const speaker = this.#options.speaker ?? ChatMessage.getSpeaker();
|
const speaker = this.#options.speaker ?? ChatMessage.getSpeaker();
|
||||||
|
@ -82,7 +80,7 @@ class CheckFactory {
|
||||||
*/
|
*/
|
||||||
createCheckTargetNumberModifier() {
|
createCheckTargetNumberModifier() {
|
||||||
const totalCheckTargetNumber = this.#checkTargetNumber + this.#checkModifier;
|
const totalCheckTargetNumber = this.#checkTargetNumber + this.#checkModifier;
|
||||||
return totalCheckTargetNumber >= 0 ? `v${this.#checkTargetNumber + this.#checkModifier}` : "v0";
|
return totalCheckTargetNumber >= 0 ? `v${this.#checkTargetNumber + this.#checkModifier}` : 'v0';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -96,7 +94,7 @@ class CheckFactory {
|
||||||
this.#options.maximumCoupResult !== this.constructor.defaultOptions.maximumCoupResult;
|
this.#options.maximumCoupResult !== this.constructor.defaultOptions.maximumCoupResult;
|
||||||
|
|
||||||
if (isMinimumFumbleResultRequired || isMaximumCoupResultRequired) {
|
if (isMinimumFumbleResultRequired || isMaximumCoupResultRequired) {
|
||||||
return `c${this.#options.maximumCoupResult ?? ""}:${this.#options.minimumFumbleResult ?? ""}`;
|
return `c${this.#options.maximumCoupResult ?? ''}:${this.#options.minimumFumbleResult ?? ''}`;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -119,7 +117,7 @@ export async function createCheckRoll(checkTargetNumber, options = {}) {
|
||||||
const newOptions = {
|
const newOptions = {
|
||||||
maximumCoupResult: interactiveRollData.maximumCoupResult ?? options.maximumCoupResult,
|
maximumCoupResult: interactiveRollData.maximumCoupResult ?? options.maximumCoupResult,
|
||||||
minimumFumbleResult: interactiveRollData.minimumFumbleResult ?? options.minimumFumbleResult,
|
minimumFumbleResult: interactiveRollData.minimumFumbleResult ?? options.minimumFumbleResult,
|
||||||
useSlayingDice: getGame().settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
|
useSlayingDice: getGame().settings.get('ds4', 'useSlayingDiceForAutomatedChecks'),
|
||||||
rollMode: interactiveRollData.rollMode ?? options.rollMode,
|
rollMode: interactiveRollData.rollMode ?? options.rollMode,
|
||||||
flavor: options.flavor,
|
flavor: options.flavor,
|
||||||
flavorData: options.flavorData,
|
flavorData: options.flavorData,
|
||||||
|
@ -148,15 +146,15 @@ export async function createCheckRoll(checkTargetNumber, options = {}) {
|
||||||
* @returns {Promise<Partial<IntermediateInteractiveRollData>>} A promise that resolves to the data given by the user.
|
* @returns {Promise<Partial<IntermediateInteractiveRollData>>} A promise that resolves to the data given by the user.
|
||||||
*/
|
*/
|
||||||
async function askForInteractiveRollData(checkTargetNumber, options = {}, { template, title } = {}) {
|
async function askForInteractiveRollData(checkTargetNumber, options = {}, { template, title } = {}) {
|
||||||
const usedTemplate = template ?? "systems/ds4/templates/dialogs/roll-options.hbs";
|
const usedTemplate = template ?? 'systems/ds4/templates/dialogs/roll-options.hbs';
|
||||||
const usedTitle = title ?? getGame().i18n.localize("DS4.DialogRollOptionsDefaultTitle");
|
const usedTitle = title ?? getGame().i18n.localize('DS4.DialogRollOptionsDefaultTitle');
|
||||||
const id = foundry.utils.randomID();
|
const id = foundry.utils.randomID();
|
||||||
const templateData = {
|
const templateData = {
|
||||||
title: usedTitle,
|
title: usedTitle,
|
||||||
checkTargetNumber: checkTargetNumber,
|
checkTargetNumber: checkTargetNumber,
|
||||||
maximumCoupResult: options.maximumCoupResult ?? this.constructor.defaultOptions.maximumCoupResult,
|
maximumCoupResult: options.maximumCoupResult ?? this.constructor.defaultOptions.maximumCoupResult,
|
||||||
minimumFumbleResult: options.minimumFumbleResult ?? this.constructor.defaultOptions.minimumFumbleResult,
|
minimumFumbleResult: options.minimumFumbleResult ?? this.constructor.defaultOptions.minimumFumbleResult,
|
||||||
rollMode: options.rollMode ?? getGame().settings.get("core", "rollMode"),
|
rollMode: options.rollMode ?? getGame().settings.get('core', 'rollMode'),
|
||||||
rollModes: CONFIG.Dice.rollModes,
|
rollModes: CONFIG.Dice.rollModes,
|
||||||
checkModifiers: Object.entries(DS4.i18n.checkModifiers).map(([key, translation]) => {
|
checkModifiers: Object.entries(DS4.i18n.checkModifiers).map(([key, translation]) => {
|
||||||
if (key in DS4.checkModifiers) {
|
if (key in DS4.checkModifiers) {
|
||||||
|
@ -178,21 +176,21 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
|
||||||
buttons: {
|
buttons: {
|
||||||
ok: {
|
ok: {
|
||||||
icon: '<i class="fas fa-check"></i>',
|
icon: '<i class="fas fa-check"></i>',
|
||||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
label: getGame().i18n.localize('DS4.GenericOkButton'),
|
||||||
callback: (html) => {
|
callback: (html) => {
|
||||||
if (!("jquery" in html)) {
|
if (!('jquery' in html)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
getGame().i18n.format("DS4.ErrorUnexpectedHtmlType", {
|
getGame().i18n.format('DS4.ErrorUnexpectedHtmlType', {
|
||||||
exType: "JQuery",
|
exType: 'JQuery',
|
||||||
realType: "HTMLElement",
|
realType: 'HTMLElement',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const innerForm = html[0]?.querySelector("form");
|
const innerForm = html[0]?.querySelector('form');
|
||||||
if (!innerForm) {
|
if (!innerForm) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
getGame().i18n.format("DS4.ErrorCouldNotFindHtmlElement", {
|
getGame().i18n.format('DS4.ErrorCouldNotFindHtmlElement', {
|
||||||
htmlElement: "form",
|
htmlElement: 'form',
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -202,26 +200,21 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
|
||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
icon: '<i class="fas fa-times"></i>',
|
icon: '<i class="fas fa-times"></i>',
|
||||||
label: getGame().i18n.localize("DS4.GenericCancelButton"),
|
label: getGame().i18n.localize('DS4.GenericCancelButton'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
default: "ok",
|
default: 'ok',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
activateAdditionalListeners: (html, app) => {
|
activateAdditionalListeners: (html, app) => {
|
||||||
const checkModifierCustomFormGroup = html
|
const checkModifierCustomFormGroup = html.find(`#check-modifier-custom-${id}`).parent('.form-group');
|
||||||
.find(`#check-modifier-custom-${id}`)
|
html.find(`#check-modifier-${id}`).on('change', (event) => {
|
||||||
.parent(".form-group");
|
if (event.currentTarget.value === 'custom' && checkModifierCustomFormGroup.hasClass('ds4-hidden')) {
|
||||||
html.find(`#check-modifier-${id}`).on("change", (event) => {
|
checkModifierCustomFormGroup.removeClass('ds4-hidden');
|
||||||
if (
|
app.setPosition({ height: 'auto' });
|
||||||
event.currentTarget.value === "custom" &&
|
} else if (!checkModifierCustomFormGroup.hasClass('ds4-hidden')) {
|
||||||
checkModifierCustomFormGroup.hasClass("ds4-hidden")
|
checkModifierCustomFormGroup.addClass('ds4-hidden');
|
||||||
) {
|
app.setPosition({ height: 'auto' });
|
||||||
checkModifierCustomFormGroup.removeClass("ds4-hidden");
|
|
||||||
app.setPosition({ height: "auto" });
|
|
||||||
} else if (!checkModifierCustomFormGroup.hasClass("ds4-hidden")) {
|
|
||||||
checkModifierCustomFormGroup.addClass("ds4-hidden");
|
|
||||||
app.setPosition({ height: "auto" });
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -239,17 +232,17 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
|
||||||
* @returns {Partial<IntermediateInteractiveRollData>}
|
* @returns {Partial<IntermediateInteractiveRollData>}
|
||||||
*/
|
*/
|
||||||
function parseDialogFormData(formData) {
|
function parseDialogFormData(formData) {
|
||||||
const chosenCheckTargetNumber = parseInt(formData["check-target-number"]?.value);
|
const chosenCheckTargetNumber = parseInt(formData['check-target-number']?.value);
|
||||||
const chosenCheckModifier = formData["check-modifier"]?.value;
|
const chosenCheckModifier = formData['check-modifier']?.value;
|
||||||
|
|
||||||
const chosenCheckModifierValue =
|
const chosenCheckModifierValue =
|
||||||
chosenCheckModifier === "custom"
|
chosenCheckModifier === 'custom'
|
||||||
? parseInt(formData["check-modifier-custom"]?.value)
|
? parseInt(formData['check-modifier-custom']?.value)
|
||||||
: parseInt(chosenCheckModifier);
|
: parseInt(chosenCheckModifier);
|
||||||
|
|
||||||
const chosenMaximumCoupResult = parseInt(formData["maximum-coup-result"]?.value);
|
const chosenMaximumCoupResult = parseInt(formData['maximum-coup-result']?.value);
|
||||||
const chosenMinimumFumbleResult = parseInt(formData["minimum-fumble-result"]?.value);
|
const chosenMinimumFumbleResult = parseInt(formData['minimum-fumble-result']?.value);
|
||||||
const chosenRollMode = formData["roll-mode"]?.value;
|
const chosenRollMode = formData['roll-mode']?.value;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
checkTargetNumber: Number.isSafeInteger(chosenCheckTargetNumber) ? chosenCheckTargetNumber : undefined,
|
checkTargetNumber: Number.isSafeInteger(chosenCheckTargetNumber) ? chosenCheckTargetNumber : undefined,
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
import { evaluateCheck, getRequiredNumberOfDice } from "./check-evaluation";
|
import { evaluateCheck, getRequiredNumberOfDice } from './check-evaluation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements DS4 Checks as an emulated "dice throw".
|
* Implements DS4 Checks as an emulated "dice throw".
|
||||||
|
@ -25,8 +25,8 @@ export class DS4Check extends DiceTerm {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Parse and store check target number
|
// Parse and store check target number
|
||||||
const checkTargetNumberModifier = this.modifiers.filter((m) => m[0] === "v")[0];
|
const checkTargetNumberModifier = this.modifiers.filter((m) => m[0] === 'v')[0];
|
||||||
const ctnRgx = new RegExp("v([0-9]+)?");
|
const ctnRgx = new RegExp('v([0-9]+)?');
|
||||||
const ctnMatch = checkTargetNumberModifier?.match(ctnRgx);
|
const ctnMatch = checkTargetNumberModifier?.match(ctnRgx);
|
||||||
if (ctnMatch) {
|
if (ctnMatch) {
|
||||||
const [parseCheckTargetNumber] = ctnMatch.slice(1);
|
const [parseCheckTargetNumber] = ctnMatch.slice(1);
|
||||||
|
@ -38,8 +38,8 @@ export class DS4Check extends DiceTerm {
|
||||||
this.number = getRequiredNumberOfDice(this.checkTargetNumber);
|
this.number = getRequiredNumberOfDice(this.checkTargetNumber);
|
||||||
|
|
||||||
// Parse and store maximumCoupResult and minimumFumbleResult
|
// Parse and store maximumCoupResult and minimumFumbleResult
|
||||||
const coupFumbleModifier = this.modifiers.filter((m) => m[0] === "c")[0];
|
const coupFumbleModifier = this.modifiers.filter((m) => m[0] === 'c')[0];
|
||||||
const cfmRgx = new RegExp("c([0-9]+)?(:([0-9]+))?");
|
const cfmRgx = new RegExp('c([0-9]+)?(:([0-9]+))?');
|
||||||
const cfmMatch = coupFumbleModifier?.match(cfmRgx);
|
const cfmMatch = coupFumbleModifier?.match(cfmRgx);
|
||||||
if (cfmMatch) {
|
if (cfmMatch) {
|
||||||
const parseMaximumCoupResult = cfmMatch[1];
|
const parseMaximumCoupResult = cfmMatch[1];
|
||||||
|
@ -51,11 +51,11 @@ export class DS4Check extends DiceTerm {
|
||||||
? parseInt(parseMinimumFumbleResult)
|
? parseInt(parseMinimumFumbleResult)
|
||||||
: DS4Check.DEFAULT_MINIMUM_FUMBLE_RESULT;
|
: DS4Check.DEFAULT_MINIMUM_FUMBLE_RESULT;
|
||||||
if (this.minimumFumbleResult <= this.maximumCoupResult)
|
if (this.minimumFumbleResult <= this.maximumCoupResult)
|
||||||
throw new SyntaxError(getGame().i18n.localize("DS4.ErrorDiceCoupFumbleOverlap"));
|
throw new SyntaxError(getGame().i18n.localize('DS4.ErrorDiceCoupFumbleOverlap'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse and store no fumble
|
// Parse and store no fumble
|
||||||
const noFumbleModifier = this.modifiers.filter((m) => m[0] === "n")[0];
|
const noFumbleModifier = this.modifiers.filter((m) => m[0] === 'n')[0];
|
||||||
if (noFumbleModifier) {
|
if (noFumbleModifier) {
|
||||||
this.canFumble = false;
|
this.canFumble = false;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ export class DS4Check extends DiceTerm {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get expression() {
|
get expression() {
|
||||||
return `ds${this.modifiers.join("")}`;
|
return `ds${this.modifiers.join('')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
|
@ -121,13 +121,13 @@ export class DS4Check extends DiceTerm {
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
getResultCSS(result) {
|
getResultCSS(result) {
|
||||||
return super.getResultCSS(result).filter((cssClass) => cssClass !== "min" && cssClass !== "max");
|
return super.getResultCSS(result).filter((cssClass) => cssClass !== 'min' && cssClass !== 'max');
|
||||||
}
|
}
|
||||||
|
|
||||||
static DEFAULT_CHECK_TARGET_NUMBER = 10;
|
static DEFAULT_CHECK_TARGET_NUMBER = 10;
|
||||||
static DEFAULT_MAXIMUM_COUP_RESULT = 1;
|
static DEFAULT_MAXIMUM_COUP_RESULT = 1;
|
||||||
static DEFAULT_MINIMUM_FUMBLE_RESULT = 20;
|
static DEFAULT_MINIMUM_FUMBLE_RESULT = 20;
|
||||||
static DENOMINATION = "s";
|
static DENOMINATION = 's';
|
||||||
static MODIFIERS = {
|
static MODIFIERS = {
|
||||||
c: () => undefined, // Modifier is consumed in constructor for maximumCoupResult / minimumFumbleResult
|
c: () => undefined, // Modifier is consumed in constructor for maximumCoupResult / minimumFumbleResult
|
||||||
v: () => undefined, // Modifier is consumed in constructor for checkTargetNumber
|
v: () => undefined, // Modifier is consumed in constructor for checkTargetNumber
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
import { DS4Check } from "./check";
|
import { DS4Check } from './check';
|
||||||
|
|
||||||
export class DS4Roll extends Roll {
|
export class DS4Roll extends Roll {
|
||||||
/** @override */
|
/** @override */
|
||||||
static CHAT_TEMPLATE = "systems/ds4/templates/dice/roll.hbs";
|
static CHAT_TEMPLATE = 'systems/ds4/templates/dice/roll.hbs';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
|
@ -21,11 +21,11 @@ export class DS4Roll extends Roll {
|
||||||
const isCoup = firstDiceTerm instanceof DS4Check && firstDiceTerm.coup;
|
const isCoup = firstDiceTerm instanceof DS4Check && firstDiceTerm.coup;
|
||||||
const isFumble = firstDiceTerm instanceof DS4Check && firstDiceTerm.fumble;
|
const isFumble = firstDiceTerm instanceof DS4Check && firstDiceTerm.fumble;
|
||||||
const chatData = {
|
const chatData = {
|
||||||
formula: isPrivate ? "???" : this._formula,
|
formula: isPrivate ? '???' : this._formula,
|
||||||
flavor: isPrivate ? null : flavor,
|
flavor: isPrivate ? null : flavor,
|
||||||
user: getGame().user?.id,
|
user: getGame().user?.id,
|
||||||
tooltip: isPrivate ? "" : await this.getTooltip(),
|
tooltip: isPrivate ? '' : await this.getTooltip(),
|
||||||
total: isPrivate ? "?" : Math.round((this.total ?? 0) * 100) / 100,
|
total: isPrivate ? '?' : Math.round((this.total ?? 0) * 100) / 100,
|
||||||
isCoup: isPrivate ? null : isCoup,
|
isCoup: isPrivate ? null : isCoup,
|
||||||
isFumble: isPrivate ? null : isFumble,
|
isFumble: isPrivate ? null : isFumble,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
import { DS4Check } from "./check";
|
import { DS4Check } from './check';
|
||||||
|
|
||||||
export function registerSlayingDiceModifier() {
|
export function registerSlayingDiceModifier() {
|
||||||
PoolTerm.MODIFIERS.x = slay;
|
PoolTerm.MODIFIERS.x = slay;
|
||||||
|
@ -31,6 +31,6 @@ function slay(modifier) {
|
||||||
this.results.push({ result: additionalRoll.total ?? 0, active: true });
|
this.results.push({ result: additionalRoll.total ?? 0, active: true });
|
||||||
this.terms.push(formula);
|
this.terms.push(formula);
|
||||||
}
|
}
|
||||||
if (checked > 1000) throw new Error(getGame().i18n.localize("DS4.ErrorSlayingDiceRecursionLimitExceeded"));
|
if (checked > 1000) throw new Error(getGame().i18n.localize('DS4.ErrorSlayingDiceRecursionLimitExceeded'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { mathEvaluator } from "../expression-evaluation/evaluator";
|
import { mathEvaluator } from '../expression-evaluation/evaluator';
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} ItemEffectConfig
|
* @typedef {object} ItemEffectConfig
|
||||||
|
@ -26,7 +26,7 @@ export class DS4ActiveEffect extends ActiveEffect {
|
||||||
/**
|
/**
|
||||||
* A fallback icon that can be used if no icon is defined for the effect.
|
* A fallback icon that can be used if no icon is defined for the effect.
|
||||||
*/
|
*/
|
||||||
static FALLBACK_ICON = "icons/svg/aura.svg";
|
static FALLBACK_ICON = 'icons/svg/aura.svg';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cached reference to the source document to avoid recurring database lookups
|
* A cached reference to the source document to avoid recurring database lookups
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from '../../config';
|
||||||
|
|
||||||
import type { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from "../common/common-data";
|
import type { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from '../common/common-data';
|
||||||
|
|
||||||
export interface DS4ActorDataPropertiesDataBase {
|
export interface DS4ActorDataPropertiesDataBase {
|
||||||
attributes: DS4ActorDataPropertiesDataAttributes;
|
attributes: DS4ActorDataPropertiesDataAttributes;
|
||||||
|
@ -25,7 +25,7 @@ type DS4ActorDataPropertiesDataAttributes = {
|
||||||
type DS4ActorDataPropertiesDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBaseTotal<number> };
|
type DS4ActorDataPropertiesDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBaseTotal<number> };
|
||||||
|
|
||||||
type DS4ActorDataPropertiesDataCombatValues = {
|
type DS4ActorDataPropertiesDataCombatValues = {
|
||||||
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
|
[Key in keyof typeof DS4.i18n.combatValues]: Key extends 'hitPoints'
|
||||||
? ResourceDataBaseTotalMax<number>
|
? ResourceDataBaseTotalMax<number>
|
||||||
: ModifiableDataBaseTotal<number>;
|
: ModifiableDataBaseTotal<number>;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4CharacterDataProperties } from "./character/character-data-properties";
|
import type { DS4CharacterDataProperties } from './character/character-data-properties';
|
||||||
import type { DS4CreatureDataProperties } from "./creature/creature-data-properties";
|
import type { DS4CreatureDataProperties } from './creature/creature-data-properties';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface DataConfig {
|
interface DataConfig {
|
||||||
|
|
|
@ -5,9 +5,9 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from '../../config';
|
||||||
|
|
||||||
import type { ModifiableData, ModifiableDataBase, ResourceData } from "../common/common-data";
|
import type { ModifiableData, ModifiableDataBase, ResourceData } from '../common/common-data';
|
||||||
|
|
||||||
export interface DS4ActorDataSourceDataBase {
|
export interface DS4ActorDataSourceDataBase {
|
||||||
attributes: DS4ActorDataSourceDataAttributes;
|
attributes: DS4ActorDataSourceDataAttributes;
|
||||||
|
@ -32,9 +32,7 @@ export function isTrait(value: unknown): value is Trait {
|
||||||
}
|
}
|
||||||
|
|
||||||
type DS4ActorDataSourceDataCombatValues = {
|
type DS4ActorDataSourceDataCombatValues = {
|
||||||
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
|
[Key in keyof typeof DS4.i18n.combatValues]: Key extends 'hitPoints' ? ResourceData<number> : ModifiableData<number>;
|
||||||
? ResourceData<number>
|
|
||||||
: ModifiableData<number>;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type CombatValue = keyof DS4ActorDataSourceDataCombatValues;
|
type CombatValue = keyof DS4ActorDataSourceDataCombatValues;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4CharacterDataSource } from "./character/character-data-source";
|
import type { DS4CharacterDataSource } from './character/character-data-source';
|
||||||
import type { DS4CreatureDataSource } from "./creature/creature-data-source";
|
import type { DS4CreatureDataSource } from './creature/creature-data-source';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface SourceConfig {
|
interface SourceConfig {
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from '../../config';
|
||||||
import { createCheckRoll } from "../../dice/check-factory";
|
import { createCheckRoll } from '../../dice/check-factory';
|
||||||
import { mathEvaluator } from "../../expression-evaluation/evaluator";
|
import { mathEvaluator } from '../../expression-evaluation/evaluator';
|
||||||
import { logger } from "../../utils/logger";
|
import { logger } from '../../utils/logger';
|
||||||
import { getGame } from "../../utils/utils";
|
import { getGame } from '../../utils/utils';
|
||||||
import { DS4ActiveEffect } from "../active-effect";
|
import { DS4ActiveEffect } from '../active-effect';
|
||||||
import { isAttribute, isTrait } from "./actor-data-source-base";
|
import { isAttribute, isTrait } from './actor-data-source-base';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Actor class for DS4
|
* The Actor class for DS4
|
||||||
|
@ -39,9 +39,7 @@ export class DS4Actor extends Actor {
|
||||||
maximumCoupResult: 1,
|
maximumCoupResult: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.values(this.system.attributes).forEach(
|
Object.values(this.system.attributes).forEach((attribute) => (attribute.total = attribute.base + attribute.mod));
|
||||||
(attribute) => (attribute.total = attribute.base + attribute.mod),
|
|
||||||
);
|
|
||||||
|
|
||||||
Object.values(this.system.traits).forEach((trait) => (trait.total = trait.base + trait.mod));
|
Object.values(this.system.traits).forEach((trait) => (trait.total = trait.base + trait.mod));
|
||||||
}
|
}
|
||||||
|
@ -85,11 +83,11 @@ export class DS4Actor extends Actor {
|
||||||
const shouldEffectBeAppliedToItem = (effect, item) => {
|
const shouldEffectBeAppliedToItem = (effect, item) => {
|
||||||
const { applyToItems, itemName, condition } = effect.flags.ds4?.itemEffectConfig ?? {};
|
const { applyToItems, itemName, condition } = effect.flags.ds4?.itemEffectConfig ?? {};
|
||||||
|
|
||||||
if (!applyToItems || (itemName !== undefined && itemName !== "" && itemName !== item.name)) {
|
if (!applyToItems || (itemName !== undefined && itemName !== '' && itemName !== item.name)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (condition !== undefined && condition !== "") {
|
if (condition !== undefined && condition !== '') {
|
||||||
try {
|
try {
|
||||||
const replacedCondition = DS4Actor.replaceFormulaData(condition, { item, actor: this, effect });
|
const replacedCondition = DS4Actor.replaceFormulaData(condition, { item, actor: this, effect });
|
||||||
return replacedCondition !== undefined ? Boolean(mathEvaluator.evaluate(replacedCondition)) : false;
|
return replacedCondition !== undefined ? Boolean(mathEvaluator.evaluate(replacedCondition)) : false;
|
||||||
|
@ -158,7 +156,7 @@ export class DS4Actor extends Actor {
|
||||||
this.applyActiveEffectsToItem(item);
|
this.applyActiveEffectsToItem(item);
|
||||||
}
|
}
|
||||||
for (const item of this.items) {
|
for (const item of this.items) {
|
||||||
if (item.type === "talent") continue;
|
if (item.type === 'talent') continue;
|
||||||
this.applyActiveEffectsToItem(item);
|
this.applyActiveEffectsToItem(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,8 +182,7 @@ export class DS4Actor extends Actor {
|
||||||
this,
|
this,
|
||||||
this.actorEffects,
|
this.actorEffects,
|
||||||
(change) =>
|
(change) =>
|
||||||
!this.derivedDataProperties.includes(change.key) &&
|
!this.derivedDataProperties.includes(change.key) && !this.finalDerivedDataProperties.includes(change.key),
|
||||||
!this.finalDerivedDataProperties.includes(change.key),
|
|
||||||
).forEach(this.newStatuses.add.bind(this.newStatuses));
|
).forEach(this.newStatuses.add.bind(this.newStatuses));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +215,7 @@ export class DS4Actor extends Actor {
|
||||||
(combatValue) => `system.combatValues.${combatValue}.total`,
|
(combatValue) => `system.combatValues.${combatValue}.total`,
|
||||||
);
|
);
|
||||||
const checkProperties = Object.keys(DS4.i18n.checks)
|
const checkProperties = Object.keys(DS4.i18n.checks)
|
||||||
.filter((check) => check !== "defend")
|
.filter((check) => check !== 'defend')
|
||||||
.map((check) => `system.checks.${check}`);
|
.map((check) => `system.checks.${check}`);
|
||||||
return combatValueProperties.concat(checkProperties);
|
return combatValueProperties.concat(checkProperties);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +251,7 @@ export class DS4Actor extends Actor {
|
||||||
Object.values(this.system.attributes).forEach((attribute) => (attribute.total = Math.ceil(attribute.total)));
|
Object.values(this.system.attributes).forEach((attribute) => (attribute.total = Math.ceil(attribute.total)));
|
||||||
Object.values(this.system.traits).forEach((trait) => (trait.total = Math.ceil(trait.total)));
|
Object.values(this.system.traits).forEach((trait) => (trait.total = Math.ceil(trait.total)));
|
||||||
Object.entries(this.system.combatValues)
|
Object.entries(this.system.combatValues)
|
||||||
.filter(([key]) => key !== "movement")
|
.filter(([key]) => key !== 'movement')
|
||||||
.forEach(([, combatValue]) => (combatValue.total = Math.ceil(combatValue.total)));
|
.forEach(([, combatValue]) => (combatValue.total = Math.ceil(combatValue.total)));
|
||||||
Object.keys(this.system.checks).forEach((key) => {
|
Object.keys(this.system.checks).forEach((key) => {
|
||||||
this.system.checks[key] = Math.ceil(this.system.checks[key]);
|
this.system.checks[key] = Math.ceil(this.system.checks[key]);
|
||||||
|
@ -270,7 +267,7 @@ export class DS4Actor extends Actor {
|
||||||
* @type {string[]}
|
* @type {string[]}
|
||||||
*/
|
*/
|
||||||
get finalDerivedDataProperties() {
|
get finalDerivedDataProperties() {
|
||||||
return ["system.combatValues.hitPoints.max", "system.checks.defend"];
|
return ['system.combatValues.hitPoints.max', 'system.checks.defend'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,7 +275,7 @@ export class DS4Actor extends Actor {
|
||||||
* @type {import("../item/item-data-source").ItemType[]}
|
* @type {import("../item/item-data-source").ItemType[]}
|
||||||
*/
|
*/
|
||||||
get ownableItemTypes() {
|
get ownableItemTypes() {
|
||||||
return ["weapon", "armor", "shield", "equipment", "loot", "spell"];
|
return ['weapon', 'armor', 'shield', 'equipment', 'loot', 'spell'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -330,7 +327,7 @@ export class DS4Actor extends Actor {
|
||||||
*/
|
*/
|
||||||
get armorValueSpellMalusOfEquippedItems() {
|
get armorValueSpellMalusOfEquippedItems() {
|
||||||
return this.equippedItemsWithArmor
|
return this.equippedItemsWithArmor
|
||||||
.filter((item) => !(item.type === "armor" && ["cloth", "natural"].includes(item.system.armorMaterialType)))
|
.filter((item) => !(item.type === 'armor' && ['cloth', 'natural'].includes(item.system.armorMaterialType)))
|
||||||
.reduce((sum, item) => sum + item.system.armorValue, 0);
|
.reduce((sum, item) => sum + item.system.armorValue, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +337,7 @@ export class DS4Actor extends Actor {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
get equippedItemsWithArmor() {
|
get equippedItemsWithArmor() {
|
||||||
return this.items.filter((item) => (item.type === "armor" || item.type === "shield") && item.system.equipped);
|
return this.items.filter((item) => (item.type === 'armor' || item.type === 'shield') && item.system.equipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -360,8 +357,7 @@ export class DS4Actor extends Actor {
|
||||||
disableTraps: system.attributes.mind.total + system.traits.dexterity.total,
|
disableTraps: system.attributes.mind.total + system.traits.dexterity.total,
|
||||||
featOfStrength: system.attributes.body.total + system.traits.strength.total,
|
featOfStrength: system.attributes.body.total + system.traits.strength.total,
|
||||||
flirt: system.attributes.mind.total + system.traits.aura.total,
|
flirt: system.attributes.mind.total + system.traits.aura.total,
|
||||||
haggle:
|
haggle: system.attributes.mind.total + Math.max(system.traits.intellect.total, system.traits.intellect.total),
|
||||||
system.attributes.mind.total + Math.max(system.traits.intellect.total, system.traits.intellect.total),
|
|
||||||
hide: system.attributes.mobility.total + system.traits.agility.total,
|
hide: system.attributes.mobility.total + system.traits.agility.total,
|
||||||
identifyMagic: system.attributes.mind.total + system.traits.intellect.total,
|
identifyMagic: system.attributes.mind.total + system.traits.intellect.total,
|
||||||
jump: system.attributes.mobility.total + system.traits.agility.total,
|
jump: system.attributes.mobility.total + system.traits.agility.total,
|
||||||
|
@ -408,7 +404,7 @@ export class DS4Actor extends Actor {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call a hook to handle token resource bar updates
|
// Call a hook to handle token resource bar updates
|
||||||
const allowed = Hooks.call("modifyTokenAttribute", { attribute, value, isDelta, isBar }, updates);
|
const allowed = Hooks.call('modifyTokenAttribute', { attribute, value, isDelta, isBar }, updates);
|
||||||
return allowed !== false ? this.update(updates) : this;
|
return allowed !== false ? this.update(updates) : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,10 +417,10 @@ export class DS4Actor extends Actor {
|
||||||
async rollCheck(check, options = {}) {
|
async rollCheck(check, options = {}) {
|
||||||
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
||||||
await createCheckRoll(this.system.checks[check], {
|
await createCheckRoll(this.system.checks[check], {
|
||||||
rollMode: getGame().settings.get("core", "rollMode"),
|
rollMode: getGame().settings.get('core', 'rollMode'),
|
||||||
maximumCoupResult: this.system.rolling.maximumCoupResult,
|
maximumCoupResult: this.system.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
|
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
|
||||||
flavor: "DS4.ActorCheckFlavor",
|
flavor: 'DS4.ActorCheckFlavor',
|
||||||
flavorData: { actor: speaker.alias ?? this.name, check: DS4.i18nKeys.checks[check] },
|
flavorData: { actor: speaker.alias ?? this.name, check: DS4.i18nKeys.checks[check] },
|
||||||
speaker,
|
speaker,
|
||||||
});
|
});
|
||||||
|
@ -445,10 +441,10 @@ export class DS4Actor extends Actor {
|
||||||
const checkTargetNumber = this.system.attributes[attribute].total + this.system.traits[trait].total;
|
const checkTargetNumber = this.system.attributes[attribute].total + this.system.traits[trait].total;
|
||||||
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
|
||||||
await createCheckRoll(checkTargetNumber, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: getGame().settings.get("core", "rollMode"),
|
rollMode: getGame().settings.get('core', 'rollMode'),
|
||||||
maximumCoupResult: this.system.rolling.maximumCoupResult,
|
maximumCoupResult: this.system.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
|
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
|
||||||
flavor: "DS4.ActorGenericCheckFlavor",
|
flavor: 'DS4.ActorGenericCheckFlavor',
|
||||||
flavorData: {
|
flavorData: {
|
||||||
actor: speaker.alias ?? this.name,
|
actor: speaker.alias ?? this.name,
|
||||||
attribute: DS4.i18n.attributes[attribute],
|
attribute: DS4.i18n.attributes[attribute],
|
||||||
|
@ -464,14 +460,14 @@ export class DS4Actor extends Actor {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
async selectAttributeAndTrait() {
|
async selectAttributeAndTrait() {
|
||||||
const attributeIdentifier = "attribute-trait-selection-attribute";
|
const attributeIdentifier = 'attribute-trait-selection-attribute';
|
||||||
const traitIdentifier = "attribute-trait-selection-trait";
|
const traitIdentifier = 'attribute-trait-selection-trait';
|
||||||
return Dialog.prompt({
|
return Dialog.prompt({
|
||||||
title: getGame().i18n.localize("DS4.DialogAttributeTraitSelection"),
|
title: getGame().i18n.localize('DS4.DialogAttributeTraitSelection'),
|
||||||
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
content: await renderTemplate('systems/ds4/templates/dialogs/simple-select-form.hbs', {
|
||||||
selects: [
|
selects: [
|
||||||
{
|
{
|
||||||
label: getGame().i18n.localize("DS4.Attribute"),
|
label: getGame().i18n.localize('DS4.Attribute'),
|
||||||
identifier: attributeIdentifier,
|
identifier: attributeIdentifier,
|
||||||
options: Object.fromEntries(
|
options: Object.fromEntries(
|
||||||
Object.entries(DS4.i18n.attributes).map(([attribute, translation]) => [
|
Object.entries(DS4.i18n.attributes).map(([attribute, translation]) => [
|
||||||
|
@ -481,7 +477,7 @@ export class DS4Actor extends Actor {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: getGame().i18n.localize("DS4.Trait"),
|
label: getGame().i18n.localize('DS4.Trait'),
|
||||||
identifier: traitIdentifier,
|
identifier: traitIdentifier,
|
||||||
options: Object.fromEntries(
|
options: Object.fromEntries(
|
||||||
Object.entries(DS4.i18n.traits).map(([trait, translation]) => [
|
Object.entries(DS4.i18n.traits).map(([trait, translation]) => [
|
||||||
|
@ -492,27 +488,27 @@ export class DS4Actor extends Actor {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
label: getGame().i18n.localize('DS4.GenericOkButton'),
|
||||||
callback: (html) => {
|
callback: (html) => {
|
||||||
const selectedAttribute = html.find(`#${attributeIdentifier}`).val();
|
const selectedAttribute = html.find(`#${attributeIdentifier}`).val();
|
||||||
if (!isAttribute(selectedAttribute)) {
|
if (!isAttribute(selectedAttribute)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
getGame().i18n.format("DS4.ErrorUnexpectedAttribute", {
|
getGame().i18n.format('DS4.ErrorUnexpectedAttribute', {
|
||||||
actualAttribute: selectedAttribute,
|
actualAttribute: selectedAttribute,
|
||||||
expectedTypes: Object.keys(DS4.i18n.attributes)
|
expectedTypes: Object.keys(DS4.i18n.attributes)
|
||||||
.map((attribute) => `'${attribute}'`)
|
.map((attribute) => `'${attribute}'`)
|
||||||
.join(", "),
|
.join(', '),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const selectedTrait = html.find(`#${traitIdentifier}`).val();
|
const selectedTrait = html.find(`#${traitIdentifier}`).val();
|
||||||
if (!isTrait(selectedTrait)) {
|
if (!isTrait(selectedTrait)) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
getGame().i18n.format("DS4.ErrorUnexpectedTrait", {
|
getGame().i18n.format('DS4.ErrorUnexpectedTrait', {
|
||||||
actualTrait: selectedTrait,
|
actualTrait: selectedTrait,
|
||||||
expectedTypes: Object.keys(DS4.i18n.traits)
|
expectedTypes: Object.keys(DS4.i18n.traits)
|
||||||
.map((attribute) => `'${attribute}'`)
|
.map((attribute) => `'${attribute}'`)
|
||||||
.join(", "),
|
.join(', '),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
|
import type { DS4ActorDataPropertiesDataBase } from '../actor-data-properties-base';
|
||||||
import type {
|
import type {
|
||||||
DS4CharacterDataSourceDataBaseInfo,
|
DS4CharacterDataSourceDataBaseInfo,
|
||||||
DS4CharacterDataSourceDataCurrency,
|
DS4CharacterDataSourceDataCurrency,
|
||||||
DS4CharacterDataSourceDataProfile,
|
DS4CharacterDataSourceDataProfile,
|
||||||
DS4CharacterDataSourceDataProgression,
|
DS4CharacterDataSourceDataProgression,
|
||||||
DS4CharacterDataSourceDataSlayerPoints,
|
DS4CharacterDataSourceDataSlayerPoints,
|
||||||
} from "./character-data-source";
|
} from './character-data-source';
|
||||||
|
|
||||||
export interface DS4CharacterDataProperties {
|
export interface DS4CharacterDataProperties {
|
||||||
type: "character";
|
type: 'character';
|
||||||
data: DS4CharacterDataPropertiesData;
|
data: DS4CharacterDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { UsableResource } from "../../common/common-data";
|
import type { UsableResource } from '../../common/common-data';
|
||||||
import type { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
|
import type { DS4ActorDataSourceDataBase } from '../actor-data-source-base';
|
||||||
|
|
||||||
export interface DS4CharacterDataSource {
|
export interface DS4CharacterDataSource {
|
||||||
type: "character";
|
type: 'character';
|
||||||
data: DS4CharacterDataSourceData;
|
data: DS4CharacterDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Actor } from "../actor";
|
import { DS4Actor } from '../actor';
|
||||||
|
|
||||||
export class DS4Character extends DS4Actor {
|
export class DS4Character extends DS4Actor {
|
||||||
/** @override */
|
/** @override */
|
||||||
|
@ -13,11 +13,11 @@ export class DS4Character extends DS4Actor {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get finalDerivedDataProperties() {
|
get finalDerivedDataProperties() {
|
||||||
return [...super.finalDerivedDataProperties, "system.slayerPoints.max"];
|
return [...super.finalDerivedDataProperties, 'system.slayerPoints.max'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
get ownableItemTypes() {
|
get ownableItemTypes() {
|
||||||
return [...super.ownableItemTypes, "talent", "racialAbility", "language", "alphabet"];
|
return [...super.ownableItemTypes, 'talent', 'racialAbility', 'language', 'alphabet'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
|
import type { DS4ActorDataPropertiesDataBase } from '../actor-data-properties-base';
|
||||||
import type { DS4CreatureDataSourceDataBaseInfo } from "./creature-data-source";
|
import type { DS4CreatureDataSourceDataBaseInfo } from './creature-data-source';
|
||||||
|
|
||||||
export interface DS4CreatureDataProperties {
|
export interface DS4CreatureDataProperties {
|
||||||
type: "creature";
|
type: 'creature';
|
||||||
data: DS4CreatureDataPropertiesData;
|
data: DS4CreatureDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../../config";
|
import type { DS4 } from '../../../config';
|
||||||
import type { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
|
import type { DS4ActorDataSourceDataBase } from '../actor-data-source-base';
|
||||||
|
|
||||||
export interface DS4CreatureDataSource {
|
export interface DS4CreatureDataSource {
|
||||||
type: "creature";
|
type: 'creature';
|
||||||
data: DS4CreatureDataSourceData;
|
data: DS4CreatureDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Actor } from "../actor";
|
import { DS4Actor } from '../actor';
|
||||||
|
|
||||||
import type { ItemType } from "../../item/item-data-source";
|
import type { ItemType } from '../../item/item-data-source';
|
||||||
|
|
||||||
export class DS4Creature extends DS4Actor {
|
export class DS4Creature extends DS4Actor {
|
||||||
override get ownableItemTypes(): Array<ItemType> {
|
override get ownableItemTypes(): Array<ItemType> {
|
||||||
return [...super.ownableItemTypes, "specialCreatureAbility"];
|
return [...super.ownableItemTypes, 'specialCreatureAbility'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../../utils/utils";
|
import { getGame } from '../../utils/utils';
|
||||||
import { DS4Actor } from "./actor";
|
import { DS4Actor } from './actor';
|
||||||
import { DS4Character } from "./character/character";
|
import { DS4Character } from './character/character';
|
||||||
import { DS4Creature } from "./creature/creature";
|
import { DS4Creature } from './creature/creature';
|
||||||
|
|
||||||
const handler = {
|
const handler = {
|
||||||
/**
|
/**
|
||||||
|
@ -14,12 +14,12 @@ const handler = {
|
||||||
*/
|
*/
|
||||||
construct(_, args) {
|
construct(_, args) {
|
||||||
switch (args[0]?.type) {
|
switch (args[0]?.type) {
|
||||||
case "character":
|
case 'character':
|
||||||
return new DS4Character(...args);
|
return new DS4Character(...args);
|
||||||
case "creature":
|
case 'creature':
|
||||||
return new DS4Creature(...args);
|
return new DS4Creature(...args);
|
||||||
default:
|
default:
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorInvalidActorType", { type: args[0]?.type }));
|
throw new Error(getGame().i18n.format('DS4.ErrorInvalidActorType', { type: args[0]?.type }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {object} DS4ChatMessageFlags
|
* @typedef {object} DS4ChatMessageFlags
|
||||||
|
@ -22,7 +22,7 @@ export class DS4ChatMessage extends ChatMessage {
|
||||||
const flavorData = Object.fromEntries(
|
const flavorData = Object.fromEntries(
|
||||||
Object.entries(this.flags.ds4?.flavorData ?? {}).map(([key, value]) => [
|
Object.entries(this.flags.ds4?.flavorData ?? {}).map(([key, value]) => [
|
||||||
key,
|
key,
|
||||||
typeof value === "string" ? game.i18n.localize(value) : value,
|
typeof value === 'string' ? game.i18n.localize(value) : value,
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
this.flavor = game.i18n.format(this.flavor, flavorData);
|
this.flavor = game.i18n.format(this.flavor, flavorData);
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4AlphabetDataSourceData } from "./alphabet-data-source";
|
import type { DS4AlphabetDataSourceData } from './alphabet-data-source';
|
||||||
|
|
||||||
export interface DS4AlphabetDataProperties {
|
export interface DS4AlphabetDataProperties {
|
||||||
type: "alphabet";
|
type: 'alphabet';
|
||||||
data: DS4AlphabetDataPropertiesData;
|
data: DS4AlphabetDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4AlphabetDataSource {
|
export interface DS4AlphabetDataSource {
|
||||||
type: "alphabet";
|
type: 'alphabet';
|
||||||
data: DS4AlphabetDataSourceData;
|
data: DS4AlphabetDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Alphabet extends DS4Item {}
|
export class DS4Alphabet extends DS4Item {}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4ArmorDataSourceData } from "./armor-data-source";
|
import type { DS4ArmorDataSourceData } from './armor-data-source';
|
||||||
|
|
||||||
export interface DS4ArmorDataProperties {
|
export interface DS4ArmorDataProperties {
|
||||||
type: "armor";
|
type: 'armor';
|
||||||
data: DS4ArmorDataPropertiesData;
|
data: DS4ArmorDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../../config";
|
import type { DS4 } from '../../../config';
|
||||||
import type {
|
import type {
|
||||||
DS4ItemDataSourceDataBase,
|
DS4ItemDataSourceDataBase,
|
||||||
DS4ItemDataSourceDataEquipable,
|
DS4ItemDataSourceDataEquipable,
|
||||||
DS4ItemDataSourceDataPhysical,
|
DS4ItemDataSourceDataPhysical,
|
||||||
DS4ItemDataSourceDataProtective,
|
DS4ItemDataSourceDataProtective,
|
||||||
} from "../item-data-source-base";
|
} from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4ArmorDataSource {
|
export interface DS4ArmorDataSource {
|
||||||
type: "armor";
|
type: 'armor';
|
||||||
data: DS4ArmorDataSourceData;
|
data: DS4ArmorDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Armor extends DS4Item {}
|
export class DS4Armor extends DS4Item {}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4EquipmentDataSourceData } from "./equipment-data-source";
|
import type { DS4EquipmentDataSourceData } from './equipment-data-source';
|
||||||
|
|
||||||
export interface DS4EquipmentDataProperties {
|
export interface DS4EquipmentDataProperties {
|
||||||
type: "equipment";
|
type: 'equipment';
|
||||||
data: DS4EquipmentDataPropertiesData;
|
data: DS4EquipmentDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,10 @@ import type {
|
||||||
DS4ItemDataSourceDataBase,
|
DS4ItemDataSourceDataBase,
|
||||||
DS4ItemDataSourceDataEquipable,
|
DS4ItemDataSourceDataEquipable,
|
||||||
DS4ItemDataSourceDataPhysical,
|
DS4ItemDataSourceDataPhysical,
|
||||||
} from "../item-data-source-base";
|
} from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4EquipmentDataSource {
|
export interface DS4EquipmentDataSource {
|
||||||
type: "equipment";
|
type: 'equipment';
|
||||||
data: DS4EquipmentDataSourceData;
|
data: DS4EquipmentDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Equipment extends DS4Item {}
|
export class DS4Equipment extends DS4Item {}
|
||||||
|
|
|
@ -2,17 +2,17 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4AlphabetDataProperties } from "./alphabet/alphabet-data-properties";
|
import type { DS4AlphabetDataProperties } from './alphabet/alphabet-data-properties';
|
||||||
import type { DS4ArmorDataProperties } from "./armor/armor-data-properties";
|
import type { DS4ArmorDataProperties } from './armor/armor-data-properties';
|
||||||
import type { DS4EquipmentDataProperties } from "./equipment/equipment-data-properties";
|
import type { DS4EquipmentDataProperties } from './equipment/equipment-data-properties';
|
||||||
import type { DS4LanguageDataProperties } from "./language/language-data-properties";
|
import type { DS4LanguageDataProperties } from './language/language-data-properties';
|
||||||
import type { DS4LootDataProperties } from "./loot/loot-data-properties";
|
import type { DS4LootDataProperties } from './loot/loot-data-properties';
|
||||||
import type { DS4RacialAbilityDataProperties } from "./racial-ability/racial-ability-data-properties";
|
import type { DS4RacialAbilityDataProperties } from './racial-ability/racial-ability-data-properties';
|
||||||
import type { DS4ShieldDataProperties } from "./shield/shield-data-properties";
|
import type { DS4ShieldDataProperties } from './shield/shield-data-properties';
|
||||||
import type { DS4SpecialCreatureAbilityDataProperties } from "./special-creature-ability/special-creature-ability-data-properties";
|
import type { DS4SpecialCreatureAbilityDataProperties } from './special-creature-ability/special-creature-ability-data-properties';
|
||||||
import type { DS4SpellDataProperties } from "./spell/spell-data-properties";
|
import type { DS4SpellDataProperties } from './spell/spell-data-properties';
|
||||||
import type { DS4TalentDataProperties } from "./talent/talent-data-properties";
|
import type { DS4TalentDataProperties } from './talent/talent-data-properties';
|
||||||
import type { DS4WeaponDataProperties } from "./weapon/weapon-data-properties";
|
import type { DS4WeaponDataProperties } from './weapon/weapon-data-properties';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface DataConfig {
|
interface DataConfig {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../config";
|
import type { DS4 } from '../../config';
|
||||||
|
|
||||||
export interface DS4ItemDataSourceDataBase {
|
export interface DS4ItemDataSourceDataBase {
|
||||||
description: string;
|
description: string;
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../config";
|
import type { DS4 } from '../../config';
|
||||||
import type { DS4AlphabetDataSource } from "./alphabet/alphabet-data-source";
|
import type { DS4AlphabetDataSource } from './alphabet/alphabet-data-source';
|
||||||
import type { DS4ArmorDataSource } from "./armor/armor-data-source";
|
import type { DS4ArmorDataSource } from './armor/armor-data-source';
|
||||||
import type { DS4EquipmentDataSource } from "./equipment/equipment-data-source";
|
import type { DS4EquipmentDataSource } from './equipment/equipment-data-source';
|
||||||
import type { DS4LanguageDataSource } from "./language/language-data-source";
|
import type { DS4LanguageDataSource } from './language/language-data-source';
|
||||||
import type { DS4LootDataSource } from "./loot/loot-data-source";
|
import type { DS4LootDataSource } from './loot/loot-data-source';
|
||||||
import type { DS4RacialAbilityDataSource } from "./racial-ability/racial-ability-data-source";
|
import type { DS4RacialAbilityDataSource } from './racial-ability/racial-ability-data-source';
|
||||||
import type { DS4ShieldDataSource } from "./shield/shield-data-source";
|
import type { DS4ShieldDataSource } from './shield/shield-data-source';
|
||||||
import type { DS4SpecialCreatureAbilityDataSource } from "./special-creature-ability/special-creature-ability-data-source";
|
import type { DS4SpecialCreatureAbilityDataSource } from './special-creature-ability/special-creature-ability-data-source';
|
||||||
import type { DS4SpellDataSource } from "./spell/spell-data-source";
|
import type { DS4SpellDataSource } from './spell/spell-data-source';
|
||||||
import type { DS4TalentDataSource } from "./talent/talent-data-source";
|
import type { DS4TalentDataSource } from './talent/talent-data-source';
|
||||||
import type { DS4WeaponDataSource } from "./weapon/weapon-data-source";
|
import type { DS4WeaponDataSource } from './weapon/weapon-data-source';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface SourceConfig {
|
interface SourceConfig {
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../../utils/utils";
|
import { getGame } from '../../utils/utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Item class for DS4
|
* The Item class for DS4
|
||||||
|
@ -25,7 +25,7 @@ export class DS4Item extends Item {
|
||||||
* @returns {boolean} Whether the item is a non-equpped equibale or not
|
* @returns {boolean} Whether the item is a non-equpped equibale or not
|
||||||
*/
|
*/
|
||||||
isNonEquippedEuipable() {
|
isNonEquippedEuipable() {
|
||||||
return "equipped" in this.system && !this.system.equipped;
|
return 'equipped' in this.system && !this.system.equipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,7 @@ export class DS4Item extends Item {
|
||||||
* @returns {import("../item/item-data-source").ItemType[]} The rollable item types
|
* @returns {import("../item/item-data-source").ItemType[]} The rollable item types
|
||||||
*/
|
*/
|
||||||
static get rollableItemTypes() {
|
static get rollableItemTypes() {
|
||||||
return ["weapon", "spell"];
|
return ['weapon', 'spell'];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,6 +52,6 @@ export class DS4Item extends Item {
|
||||||
*/
|
*/
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
async roll(options = {}) {
|
async roll(options = {}) {
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorRollingForItemTypeNotPossible", { type: this.type }));
|
throw new Error(getGame().i18n.format('DS4.ErrorRollingForItemTypeNotPossible', { type: this.type }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4LanguageDataSourceData } from "./language-data-source";
|
import type { DS4LanguageDataSourceData } from './language-data-source';
|
||||||
|
|
||||||
export interface DS4LanguageDataProperties {
|
export interface DS4LanguageDataProperties {
|
||||||
type: "language";
|
type: 'language';
|
||||||
data: DS4LanguageDataPropertiesData;
|
data: DS4LanguageDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4LanguageDataSource {
|
export interface DS4LanguageDataSource {
|
||||||
type: "language";
|
type: 'language';
|
||||||
data: DS4LanguageDataSourceData;
|
data: DS4LanguageDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Language extends DS4Item {}
|
export class DS4Language extends DS4Item {}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4LootDataSourceData } from "./loot-data-source";
|
import type { DS4LootDataSourceData } from './loot-data-source';
|
||||||
|
|
||||||
export interface DS4LootDataProperties {
|
export interface DS4LootDataProperties {
|
||||||
type: "loot";
|
type: 'loot';
|
||||||
data: DS4LootDataPropertiesData;
|
data: DS4LootDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataPhysical } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataPhysical } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4LootDataSource {
|
export interface DS4LootDataSource {
|
||||||
type: "loot";
|
type: 'loot';
|
||||||
data: DS4LootDataSourceData;
|
data: DS4LootDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Loot extends DS4Item {}
|
export class DS4Loot extends DS4Item {}
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../../utils/utils";
|
import { getGame } from '../../utils/utils';
|
||||||
import { DS4Alphabet } from "./alphabet/alphabet";
|
import { DS4Alphabet } from './alphabet/alphabet';
|
||||||
import { DS4Armor } from "./armor/armor";
|
import { DS4Armor } from './armor/armor';
|
||||||
import { DS4Equipment } from "./equipment/equipment";
|
import { DS4Equipment } from './equipment/equipment';
|
||||||
import { DS4Item } from "./item";
|
import { DS4Item } from './item';
|
||||||
import { DS4Language } from "./language/language";
|
import { DS4Language } from './language/language';
|
||||||
import { DS4Loot } from "./loot/loot";
|
import { DS4Loot } from './loot/loot';
|
||||||
import { DS4RacialAbility } from "./racial-ability/racial-ability";
|
import { DS4RacialAbility } from './racial-ability/racial-ability';
|
||||||
import { DS4Shield } from "./shield/shield";
|
import { DS4Shield } from './shield/shield';
|
||||||
import { DS4SpecialCreatureAbility } from "./special-creature-ability/special-creature-ability";
|
import { DS4SpecialCreatureAbility } from './special-creature-ability/special-creature-ability';
|
||||||
import { DS4Spell } from "./spell/spell";
|
import { DS4Spell } from './spell/spell';
|
||||||
import { DS4Talent } from "./talent/talent";
|
import { DS4Talent } from './talent/talent';
|
||||||
import { DS4Weapon } from "./weapon/weapon";
|
import { DS4Weapon } from './weapon/weapon';
|
||||||
|
|
||||||
const handler = {
|
const handler = {
|
||||||
/**
|
/**
|
||||||
|
@ -23,30 +23,30 @@ const handler = {
|
||||||
*/
|
*/
|
||||||
construct(_, args) {
|
construct(_, args) {
|
||||||
switch (args[0]?.type) {
|
switch (args[0]?.type) {
|
||||||
case "alphabet":
|
case 'alphabet':
|
||||||
return new DS4Alphabet(...args);
|
return new DS4Alphabet(...args);
|
||||||
case "armor":
|
case 'armor':
|
||||||
return new DS4Armor(...args);
|
return new DS4Armor(...args);
|
||||||
case "equipment":
|
case 'equipment':
|
||||||
return new DS4Equipment(...args);
|
return new DS4Equipment(...args);
|
||||||
case "language":
|
case 'language':
|
||||||
return new DS4Language(...args);
|
return new DS4Language(...args);
|
||||||
case "loot":
|
case 'loot':
|
||||||
return new DS4Loot(...args);
|
return new DS4Loot(...args);
|
||||||
case "racialAbility":
|
case 'racialAbility':
|
||||||
return new DS4RacialAbility(...args);
|
return new DS4RacialAbility(...args);
|
||||||
case "shield":
|
case 'shield':
|
||||||
return new DS4Shield(...args);
|
return new DS4Shield(...args);
|
||||||
case "specialCreatureAbility":
|
case 'specialCreatureAbility':
|
||||||
return new DS4SpecialCreatureAbility(...args);
|
return new DS4SpecialCreatureAbility(...args);
|
||||||
case "spell":
|
case 'spell':
|
||||||
return new DS4Spell(...args);
|
return new DS4Spell(...args);
|
||||||
case "talent":
|
case 'talent':
|
||||||
return new DS4Talent(...args);
|
return new DS4Talent(...args);
|
||||||
case "weapon":
|
case 'weapon':
|
||||||
return new DS4Weapon(...args);
|
return new DS4Weapon(...args);
|
||||||
default:
|
default:
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorInvalidItemType", { type: args[0]?.type }));
|
throw new Error(getGame().i18n.format('DS4.ErrorInvalidItemType', { type: args[0]?.type }));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4RacialAbilityDataSourceData } from "./racial-ability-data-source";
|
import type { DS4RacialAbilityDataSourceData } from './racial-ability-data-source';
|
||||||
|
|
||||||
export interface DS4RacialAbilityDataProperties {
|
export interface DS4RacialAbilityDataProperties {
|
||||||
type: "racialAbility";
|
type: 'racialAbility';
|
||||||
data: DS4RacialAbilityDataPropertiesData;
|
data: DS4RacialAbilityDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4RacialAbilityDataSource {
|
export interface DS4RacialAbilityDataSource {
|
||||||
type: "racialAbility";
|
type: 'racialAbility';
|
||||||
data: DS4RacialAbilityDataSourceData;
|
data: DS4RacialAbilityDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4RacialAbility extends DS4Item {}
|
export class DS4RacialAbility extends DS4Item {}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4ShieldDataSourceData } from "./shield-data-source";
|
import type { DS4ShieldDataSourceData } from './shield-data-source';
|
||||||
|
|
||||||
export interface DS4ShieldDataProperties {
|
export interface DS4ShieldDataProperties {
|
||||||
type: "shield";
|
type: 'shield';
|
||||||
data: DS4ShieldDataPropertiesData;
|
data: DS4ShieldDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,10 +7,10 @@ import type {
|
||||||
DS4ItemDataSourceDataEquipable,
|
DS4ItemDataSourceDataEquipable,
|
||||||
DS4ItemDataSourceDataPhysical,
|
DS4ItemDataSourceDataPhysical,
|
||||||
DS4ItemDataSourceDataProtective,
|
DS4ItemDataSourceDataProtective,
|
||||||
} from "../item-data-source-base";
|
} from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4ShieldDataSource {
|
export interface DS4ShieldDataSource {
|
||||||
type: "shield";
|
type: 'shield';
|
||||||
data: DS4ShieldDataSourceData;
|
data: DS4ShieldDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Shield extends DS4Item {}
|
export class DS4Shield extends DS4Item {}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4SpecialCreatureAbilityDataSourceData } from "./special-creature-ability-data-source";
|
import type { DS4SpecialCreatureAbilityDataSourceData } from './special-creature-ability-data-source';
|
||||||
|
|
||||||
export interface DS4SpecialCreatureAbilityDataProperties {
|
export interface DS4SpecialCreatureAbilityDataProperties {
|
||||||
type: "specialCreatureAbility";
|
type: 'specialCreatureAbility';
|
||||||
data: DS4SpecialCreatureAbilityDataPropertiesData;
|
data: DS4SpecialCreatureAbilityDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4SpecialCreatureAbilityDataSource {
|
export interface DS4SpecialCreatureAbilityDataSource {
|
||||||
type: "specialCreatureAbility";
|
type: 'specialCreatureAbility';
|
||||||
data: DS4SpecialCreatureAbilityDataSourceData;
|
data: DS4SpecialCreatureAbilityDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,6 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4SpecialCreatureAbility extends DS4Item {}
|
export class DS4SpecialCreatureAbility extends DS4Item {}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { CooldownDuration, DS4SpellDataSourceData } from "./spell-data-source";
|
import type { CooldownDuration, DS4SpellDataSourceData } from './spell-data-source';
|
||||||
|
|
||||||
export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null {
|
export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null {
|
||||||
const spellPriceFactor = calculateSpellPriceFactor(data.cooldownDuration);
|
const spellPriceFactor = calculateSpellPriceFactor(data.cooldownDuration);
|
||||||
|
@ -17,16 +17,16 @@ export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null
|
||||||
|
|
||||||
function calculateSpellPriceFactor(cooldownDuration: CooldownDuration): number {
|
function calculateSpellPriceFactor(cooldownDuration: CooldownDuration): number {
|
||||||
switch (cooldownDuration) {
|
switch (cooldownDuration) {
|
||||||
case "0r":
|
case '0r':
|
||||||
case "1r":
|
case '1r':
|
||||||
case "2r":
|
case '2r':
|
||||||
case "5r":
|
case '5r':
|
||||||
case "10r":
|
case '10r':
|
||||||
case "100r":
|
case '100r':
|
||||||
return 1;
|
return 1;
|
||||||
case "1d":
|
case '1d':
|
||||||
return 2;
|
return 2;
|
||||||
case "d20d":
|
case 'd20d':
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4SpellDataSourceData } from "./spell-data-source";
|
import type { DS4SpellDataSourceData } from './spell-data-source';
|
||||||
|
|
||||||
export interface DS4SpellDataProperties {
|
export interface DS4SpellDataProperties {
|
||||||
type: "spell";
|
type: 'spell';
|
||||||
data: DS4SpellDataPropertiesData;
|
data: DS4SpellDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../../config";
|
import type { DS4 } from '../../../config';
|
||||||
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataEquipable } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataEquipable } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4SpellDataSource {
|
export interface DS4SpellDataSource {
|
||||||
type: "spell";
|
type: 'spell';
|
||||||
data: DS4SpellDataSourceData;
|
data: DS4SpellDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { createCheckRoll } from "../../../dice/check-factory";
|
import { createCheckRoll } from '../../../dice/check-factory';
|
||||||
import { notifications } from "../../../ui/notifications";
|
import { notifications } from '../../../ui/notifications';
|
||||||
import { getGame } from "../../../utils/utils";
|
import { getGame } from '../../../utils/utils';
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
import { calculateSpellPrice } from "./calculate-spell-price";
|
import { calculateSpellPrice } from './calculate-spell-price';
|
||||||
|
|
||||||
export class DS4Spell extends DS4Item {
|
export class DS4Spell extends DS4Item {
|
||||||
/** @override */
|
/** @override */
|
||||||
|
@ -24,7 +24,7 @@ export class DS4Spell extends DS4Item {
|
||||||
|
|
||||||
if (!this.system.equipped) {
|
if (!this.system.equipped) {
|
||||||
return notifications.warn(
|
return notifications.warn(
|
||||||
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
|
game.i18n.format('DS4.WarningItemMustBeEquippedToBeRolled', {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
|
@ -33,14 +33,14 @@ export class DS4Spell extends DS4Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.actor) {
|
if (!this.actor) {
|
||||||
throw new Error(game.i18n.format("DS4.ErrorCannotRollUnownedItem", { name: this.name, id: this.id }));
|
throw new Error(game.i18n.format('DS4.ErrorCannotRollUnownedItem', { name: this.name, id: this.id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerSystemData = this.actor.system;
|
const ownerSystemData = this.actor.system;
|
||||||
const hasComplexModifier = this.system.spellModifier.complex !== "";
|
const hasComplexModifier = this.system.spellModifier.complex !== '';
|
||||||
if (hasComplexModifier === undefined) {
|
if (hasComplexModifier === undefined) {
|
||||||
notifications.info(
|
notifications.info(
|
||||||
game.i18n.format("DS4.InfoManuallyEnterSpellModifier", {
|
game.i18n.format('DS4.InfoManuallyEnterSpellModifier', {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
spellModifier: this.system.spellModifier.complex,
|
spellModifier: this.system.spellModifier.complex,
|
||||||
}),
|
}),
|
||||||
|
@ -49,24 +49,23 @@ export class DS4Spell extends DS4Item {
|
||||||
const spellType = this.system.spellType;
|
const spellType = this.system.spellType;
|
||||||
const opponentDefense = this.system.opponentDefense;
|
const opponentDefense = this.system.opponentDefense;
|
||||||
const checkTargetNumber =
|
const checkTargetNumber =
|
||||||
ownerSystemData.combatValues[spellType].total +
|
ownerSystemData.combatValues[spellType].total + (hasComplexModifier ? 0 : this.system.spellModifier.numerical);
|
||||||
(hasComplexModifier ? 0 : this.system.spellModifier.numerical);
|
|
||||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||||
const flavor =
|
const flavor =
|
||||||
opponentDefense !== undefined && opponentDefense !== 0
|
opponentDefense !== undefined && opponentDefense !== 0
|
||||||
? "DS4.ItemSpellCheckFlavorWithOpponentDefense"
|
? 'DS4.ItemSpellCheckFlavorWithOpponentDefense'
|
||||||
: "DS4.ItemSpellCheckFlavor";
|
: 'DS4.ItemSpellCheckFlavor';
|
||||||
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
|
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
|
||||||
const flavorData = {
|
const flavorData = {
|
||||||
actor: speaker.alias ?? this.actor.name,
|
actor: speaker.alias ?? this.actor.name,
|
||||||
spell: this.name,
|
spell: this.name,
|
||||||
};
|
};
|
||||||
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
||||||
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
|
flavorData.opponentDefense = (opponentDefense < 0 ? '' : '+') + opponentDefense;
|
||||||
}
|
}
|
||||||
|
|
||||||
await createCheckRoll(checkTargetNumber, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: game.settings.get('core', 'rollMode'),
|
||||||
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
|
||||||
flavor: flavor,
|
flavor: flavor,
|
||||||
|
@ -80,6 +79,6 @@ export class DS4Spell extends DS4Item {
|
||||||
* @memberof hookEvents
|
* @memberof hookEvents
|
||||||
* @param {DS4Item} item Item being rolled.
|
* @param {DS4Item} item Item being rolled.
|
||||||
*/
|
*/
|
||||||
Hooks.callAll("ds4.rollItem", this);
|
Hooks.callAll('ds4.rollItem', this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { ModifiableDataBaseTotalMax } from "../../common/common-data";
|
import type { ModifiableDataBaseTotalMax } from '../../common/common-data';
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4TalentDataSourceData } from "./talent-data-source";
|
import type { DS4TalentDataSourceData } from './talent-data-source';
|
||||||
|
|
||||||
export interface DS4TalentDataProperties {
|
export interface DS4TalentDataProperties {
|
||||||
type: "talent";
|
type: 'talent';
|
||||||
data: DS4TalentDataPropertiesData;
|
data: DS4TalentDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { ModifiableDataBaseMax } from "../../common/common-data";
|
import type { ModifiableDataBaseMax } from '../../common/common-data';
|
||||||
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
|
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4TalentDataSource {
|
export interface DS4TalentDataSource {
|
||||||
type: "talent";
|
type: 'talent';
|
||||||
data: DS4TalentDataSourceData;
|
data: DS4TalentDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Talent extends DS4Item {
|
export class DS4Talent extends DS4Item {
|
||||||
/** @override */
|
/** @override */
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
|
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
|
||||||
import type { DS4WeaponDataSourceData } from "./weapon-data-source";
|
import type { DS4WeaponDataSourceData } from './weapon-data-source';
|
||||||
|
|
||||||
interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDataPropertiesDataRollable {
|
interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDataPropertiesDataRollable {
|
||||||
opponentDefenseForAttackType: {
|
opponentDefenseForAttackType: {
|
||||||
|
@ -13,6 +13,6 @@ interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDa
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DS4WeaponDataProperties {
|
export interface DS4WeaponDataProperties {
|
||||||
type: "weapon";
|
type: 'weapon';
|
||||||
data: DS4WeaponDataPropertiesData;
|
data: DS4WeaponDataPropertiesData;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import type { DS4 } from "../../../config";
|
import type { DS4 } from '../../../config';
|
||||||
import type {
|
import type {
|
||||||
DS4ItemDataSourceDataBase,
|
DS4ItemDataSourceDataBase,
|
||||||
DS4ItemDataSourceDataEquipable,
|
DS4ItemDataSourceDataEquipable,
|
||||||
DS4ItemDataSourceDataPhysical,
|
DS4ItemDataSourceDataPhysical,
|
||||||
} from "../item-data-source-base";
|
} from '../item-data-source-base';
|
||||||
|
|
||||||
export interface DS4WeaponDataSource {
|
export interface DS4WeaponDataSource {
|
||||||
type: "weapon";
|
type: 'weapon';
|
||||||
data: DS4WeaponDataSourceData;
|
data: DS4WeaponDataSourceData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { DS4 } from "../../../config";
|
import { DS4 } from '../../../config';
|
||||||
import { createCheckRoll } from "../../../dice/check-factory";
|
import { createCheckRoll } from '../../../dice/check-factory';
|
||||||
import { notifications } from "../../../ui/notifications";
|
import { notifications } from '../../../ui/notifications';
|
||||||
import { getGame } from "../../../utils/utils";
|
import { getGame } from '../../../utils/utils';
|
||||||
import { DS4Item } from "../item";
|
import { DS4Item } from '../item';
|
||||||
|
|
||||||
export class DS4Weapon extends DS4Item {
|
export class DS4Weapon extends DS4Item {
|
||||||
/** @override */
|
/** @override */
|
||||||
|
@ -14,10 +14,10 @@ export class DS4Weapon extends DS4Item {
|
||||||
const system = this.system;
|
const system = this.system;
|
||||||
system.rollable = system.equipped;
|
system.rollable = system.equipped;
|
||||||
system.opponentDefenseForAttackType = {};
|
system.opponentDefenseForAttackType = {};
|
||||||
if (system.attackType === "melee" || system.attackType === "meleeRanged") {
|
if (system.attackType === 'melee' || system.attackType === 'meleeRanged') {
|
||||||
system.opponentDefenseForAttackType.melee = system.opponentDefense;
|
system.opponentDefenseForAttackType.melee = system.opponentDefense;
|
||||||
}
|
}
|
||||||
if (system.attackType === "ranged" || system.attackType === "meleeRanged") {
|
if (system.attackType === 'ranged' || system.attackType === 'meleeRanged') {
|
||||||
system.opponentDefenseForAttackType.ranged = system.opponentDefense;
|
system.opponentDefenseForAttackType.ranged = system.opponentDefense;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ export class DS4Weapon extends DS4Item {
|
||||||
const game = getGame();
|
const game = getGame();
|
||||||
if (!this.system.equipped) {
|
if (!this.system.equipped) {
|
||||||
return notifications.warn(
|
return notifications.warn(
|
||||||
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
|
game.i18n.format('DS4.WarningItemMustBeEquippedToBeRolled', {
|
||||||
name: this.name,
|
name: this.name,
|
||||||
id: this.id,
|
id: this.id,
|
||||||
type: this.type,
|
type: this.type,
|
||||||
|
@ -36,7 +36,7 @@ export class DS4Weapon extends DS4Item {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.actor) {
|
if (!this.actor) {
|
||||||
throw new Error(game.i18n.format("DS4.ErrorCannotRollUnownedItem", { name: this.name, id: this.id }));
|
throw new Error(game.i18n.format('DS4.ErrorCannotRollUnownedItem', { name: this.name, id: this.id }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerSystemData = this.actor.system;
|
const ownerSystemData = this.actor.system;
|
||||||
|
@ -48,19 +48,19 @@ export class DS4Weapon extends DS4Item {
|
||||||
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
|
||||||
const flavor =
|
const flavor =
|
||||||
opponentDefense !== undefined && opponentDefense !== 0
|
opponentDefense !== undefined && opponentDefense !== 0
|
||||||
? "DS4.ItemWeaponCheckFlavorWithOpponentDefense"
|
? 'DS4.ItemWeaponCheckFlavorWithOpponentDefense'
|
||||||
: "DS4.ItemWeaponCheckFlavor";
|
: 'DS4.ItemWeaponCheckFlavor';
|
||||||
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
|
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
|
||||||
const flavorData = {
|
const flavorData = {
|
||||||
actor: speaker.alias ?? this.actor.name,
|
actor: speaker.alias ?? this.actor.name,
|
||||||
weapon: this.name,
|
weapon: this.name,
|
||||||
};
|
};
|
||||||
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
if (opponentDefense !== undefined && opponentDefense !== 0) {
|
||||||
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
|
flavorData.opponentDefense = (opponentDefense < 0 ? '' : '+') + opponentDefense;
|
||||||
}
|
}
|
||||||
|
|
||||||
await createCheckRoll(checkTargetNumber, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: getGame().settings.get("core", "rollMode"),
|
rollMode: getGame().settings.get('core', 'rollMode'),
|
||||||
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
|
||||||
speaker,
|
speaker,
|
||||||
|
@ -68,7 +68,7 @@ export class DS4Weapon extends DS4Item {
|
||||||
flavorData,
|
flavorData,
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.callAll("ds4.rollItem", this);
|
Hooks.callAll('ds4.rollItem', this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,29 +77,29 @@ export class DS4Weapon extends DS4Item {
|
||||||
* @protected
|
* @protected
|
||||||
*/
|
*/
|
||||||
async getPerformedAttackType() {
|
async getPerformedAttackType() {
|
||||||
if (this.system.attackType !== "meleeRanged") {
|
if (this.system.attackType !== 'meleeRanged') {
|
||||||
return this.system.attackType;
|
return this.system.attackType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { melee, ranged } = { ...DS4.i18n.attackTypes };
|
const { melee, ranged } = { ...DS4.i18n.attackTypes };
|
||||||
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
|
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
|
||||||
return Dialog.prompt({
|
return Dialog.prompt({
|
||||||
title: getGame().i18n.localize("DS4.DialogAttackTypeSelection"),
|
title: getGame().i18n.localize('DS4.DialogAttackTypeSelection'),
|
||||||
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
|
content: await renderTemplate('systems/ds4/templates/dialogs/simple-select-form.hbs', {
|
||||||
selects: [
|
selects: [
|
||||||
{
|
{
|
||||||
label: getGame().i18n.localize("DS4.AttackType"),
|
label: getGame().i18n.localize('DS4.AttackType'),
|
||||||
identifier,
|
identifier,
|
||||||
options: { melee, ranged },
|
options: { melee, ranged },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
label: getGame().i18n.localize("DS4.GenericOkButton"),
|
label: getGame().i18n.localize('DS4.GenericOkButton'),
|
||||||
callback: (html) => {
|
callback: (html) => {
|
||||||
const selectedAttackType = html.find(`#${identifier}`).val();
|
const selectedAttackType = html.find(`#${identifier}`).val();
|
||||||
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
|
if (selectedAttackType !== 'melee' && selectedAttackType !== 'ranged') {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
getGame().i18n.format("DS4.ErrorUnexpectedAttackType", {
|
getGame().i18n.format('DS4.ErrorUnexpectedAttackType', {
|
||||||
actualType: selectedAttackType,
|
actualType: selectedAttackType,
|
||||||
expectedTypes: "'melee', 'ranged'",
|
expectedTypes: "'melee', 'ranged'",
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { getGame } from "../utils/utils";
|
import { getGame } from '../utils/utils';
|
||||||
import { DS4ActorProxy } from "./actor/proxy";
|
import { DS4ActorProxy } from './actor/proxy';
|
||||||
|
|
||||||
/** @type {object | undefined} */
|
/** @type {object | undefined} */
|
||||||
let fallbackData = undefined;
|
let fallbackData = undefined;
|
||||||
|
@ -12,7 +12,7 @@ function getFallbackData() {
|
||||||
if (!fallbackData) {
|
if (!fallbackData) {
|
||||||
fallbackData = {};
|
fallbackData = {};
|
||||||
for (const type of getGame().system.template.Actor?.types ?? []) {
|
for (const type of getGame().system.template.Actor?.types ?? []) {
|
||||||
foundry.utils.mergeObject(fallbackData, new DS4ActorProxy({ type, name: "temporary" }).system);
|
foundry.utils.mergeObject(fallbackData, new DS4ActorProxy({ type, name: 'temporary' }).system);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fallbackData;
|
return fallbackData;
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import "../scss/ds4.scss";
|
import '../scss/ds4.scss';
|
||||||
|
|
||||||
import { registerForHooks } from "./hooks/hooks";
|
import { registerForHooks } from './hooks/hooks';
|
||||||
|
|
||||||
registerForHooks();
|
registerForHooks();
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
import { Validator } from "./validator";
|
import { Validator } from './validator';
|
||||||
|
|
||||||
export class Evaluator<Context extends object> {
|
export class Evaluator<Context extends object> {
|
||||||
context?: Context;
|
context?: Context;
|
||||||
|
@ -28,7 +28,7 @@ export class Evaluator<Context extends object> {
|
||||||
this.validator.validate(expression);
|
this.validator.validate(expression);
|
||||||
|
|
||||||
const body = `with (sandbox) { return ${expression}; }`;
|
const body = `with (sandbox) { return ${expression}; }`;
|
||||||
const evaluate = new Function("sandbox", body);
|
const evaluate = new Function('sandbox', body);
|
||||||
return evaluate(this.context ?? {});
|
return evaluate(this.context ?? {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue