Compare commits

...

1 commit

Author SHA1 Message Date
3bc7c7819b
chore: reformat with 2 spaces and single quotes
Some checks failed
ci/woodpecker/pr/checks Pipeline failed
2023-07-10 22:23:33 +02:00
1590 changed files with 70381 additions and 70413 deletions

View file

@ -3,13 +3,13 @@
// SPDX-License-Identifier: MIT
module.exports = {
parser: "@typescript-eslint/parser",
parserOptions: { ecmaVersion: 2020, sourceType: "module" },
parser: '@typescript-eslint/parser',
parserOptions: { ecmaVersion: 2020, sourceType: 'module' },
env: { browser: true },
extends: ["plugin:@typescript-eslint/recommended", "prettier"],
plugins: ["@typescript-eslint"],
extends: ['plugin:@typescript-eslint/recommended', 'prettier'],
plugins: ['@typescript-eslint'],
overrides: [
{ files: ["./*.cjs"], rules: { "@typescript-eslint/no-var-requires": "off" } },
{ files: ["./spec/**/*"], env: { browser: false } },
{ files: ['./*.cjs'], rules: { '@typescript-eslint/no-var-requires': 'off' } },
{ files: ['./spec/**/*'], env: { browser: false } },
],
};

View file

@ -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
View 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,
};

View file

@ -2,4 +2,4 @@
//
// SPDX-License-Identifier: MIT
module.exports = { extends: ["@commitlint/config-conventional"] };
module.exports = { extends: ['@commitlint/config-conventional'] };

View file

@ -2,29 +2,29 @@
//
// SPDX-License-Identifier: MIT
import styles from "@ironkinoko/rollup-plugin-styles";
import { swc } from "rollup-plugin-swc3";
import styles from '@ironkinoko/rollup-plugin-styles';
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 = [
".reuse",
"assets",
"ATTRIBUTION.md",
"fonts",
"lang",
"LICENSE.md",
"LICENSES",
"README.md",
"system.json.license",
"system.json",
"template.json.license",
"template.json",
"templates",
'.reuse',
'assets',
'ATTRIBUTION.md',
'fonts',
'lang',
'LICENSE.md',
'LICENSES',
'README.md',
'system.json.license',
'system.json',
'template.json.license',
'template.json',
'templates',
];
const isProduction = process.env.NODE_ENV === "production";
const isProduction = process.env.NODE_ENV === 'production';
/**
* @type {import('rollup').RollupOptions}
@ -33,9 +33,9 @@ const config = {
input: { [name]: `${sourceDirectory}/${name}.ts` },
output: {
dir: distDirectory,
format: "es",
format: 'es',
sourcemap: true,
assetFileNames: "[name].[ext]",
assetFileNames: '[name].[ext]',
},
plugins: [
swc({
@ -51,7 +51,7 @@ const config = {
sourceMaps: true,
}),
styles({
mode: ["extract", `css/${name}.css`],
mode: ['extract', `css/${name}.css`],
url: false,
sourceMap: true,
minimize: isProduction,

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use '../../utils/mixins';
.ds4-actor-header {
display: flex;
@ -44,7 +44,7 @@
margin: 0;
}
&__name-input[type="text"] {
&__name-input[type='text'] {
@include mixins.font-heading-upper;
background-color: transparent;
border: none;

View file

@ -5,9 +5,9 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/colors";
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/colors';
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-actor-progression {
@include mixins.mark-invalid-or-disabled-input;

View file

@ -6,8 +6,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-actor-properties {
@include mixins.mark-invalid-or-disabled-input;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use '../../utils/mixins';
.ds4-check {
background: transparent;

View file

@ -4,8 +4,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-combat-value {
$size: 3.75rem;
@ -15,7 +15,7 @@
row-gap: 0.125em;
&__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;
background-position: center;
@ -26,28 +26,28 @@
width: $size;
&--hitPoints {
background-image: url("#{$combat-values-icons-path}/hit-points.png");
background-image: url('#{$combat-values-icons-path}/hit-points.png');
}
&--defense {
background-image: url("#{$combat-values-icons-path}/defense.png");
background-image: url('#{$combat-values-icons-path}/defense.png');
}
&--initiative {
background-image: url("#{$combat-values-icons-path}/initiative.png");
background-image: url('#{$combat-values-icons-path}/initiative.png');
}
&--movement {
background-image: url("#{$combat-values-icons-path}/movement-rate.png");
background-image: url('#{$combat-values-icons-path}/movement-rate.png');
}
&--meleeAttack {
background-image: url("#{$combat-values-icons-path}/melee-attack.png");
background-image: url('#{$combat-values-icons-path}/melee-attack.png');
}
&--rangedAttack {
background-image: url("#{$combat-values-icons-path}/ranged-attack.png");
background-image: url('#{$combat-values-icons-path}/ranged-attack.png');
}
&--spellcasting {
background-image: url("#{$combat-values-icons-path}/spellcasting.png");
background-image: url('#{$combat-values-icons-path}/spellcasting.png');
}
&--targetedSpellcasting {
background-image: url("#{$combat-values-icons-path}/targeted-spellcasting.png");
background-image: url('#{$combat-values-icons-path}/targeted-spellcasting.png');
}
}

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/variables";
@use '../../utils/variables';
.ds4-combat-values {
border-bottom: variables.$border-groove;

View file

@ -4,9 +4,9 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/colors";
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/colors';
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-core-value {
align-items: center;

View file

@ -4,8 +4,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/colors";
@use "../../utils/variables";
@use '../../utils/colors';
@use '../../utils/variables';
.ds4-core-values {
column-gap: 0.5em;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/variables";
@use '../../utils/variables';
.ds4-currency {
align-items: center;

View file

@ -4,7 +4,7 @@
* 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
.dice-roll .ds4-dice-total {

View file

@ -4,8 +4,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/colors";
@use "../../utils/mixins";
@use '../../utils/colors';
@use '../../utils/mixins';
.ds4-item-header {
align-items: center;
@ -39,7 +39,7 @@
display: none;
}
&__name-input[type="text"] {
&__name-input[type='text'] {
@include mixins.font-heading-upper;
background-color: transparent;
border: none;

View file

@ -5,8 +5,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-item-properties {
@include mixins.mark-invalid-or-disabled-input;

View file

@ -21,7 +21,7 @@
}
}
&__checkbox[type="checkbox"] {
&__checkbox[type='checkbox'] {
margin: 0;
}
}

View file

@ -5,8 +5,8 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/mixins";
@use "../../utils/variables";
@use '../../utils/mixins';
@use '../../utils/variables';
.ds4-embedded-document-list {
@include mixins.mark-invalid-or-disabled-input;
@ -105,8 +105,8 @@
}
&__editable {
&[type="text"],
&[type="number"] {
&[type='text'],
&[type='number'] {
background-color: transparent;
border: 0;
padding: 0;
@ -114,7 +114,7 @@
}
&--checkbox {
&[type="checkbox"] {
&[type='checkbox'] {
width: 100%;
height: 100%;
margin: 0px;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "../../utils/variables";
@use '../../utils/variables';
.ds4-sheet-tab-nav {
border-bottom: variables.$border-groove;

View file

@ -7,43 +7,43 @@
*/
// global
@use "global/accessibility";
@use "global/fonts";
@use "global/utils";
@use 'global/accessibility';
@use 'global/fonts';
@use 'global/utils';
// shared
@use "components/shared/add_button";
@use "components/shared/control_button_group";
@use "components/shared/checkbox_grid";
@use "components/shared/editor";
@use "components/shared/embedded_document_list";
@use "components/shared/form_group";
@use "components/shared/rollable_image";
@use "components/shared/sheet_body";
@use "components/shared/sheet_form";
@use "components/shared/sheet_tab_nav";
@use "components/shared/sheet_tab";
@use 'components/shared/add_button';
@use 'components/shared/control_button_group';
@use 'components/shared/checkbox_grid';
@use 'components/shared/editor';
@use 'components/shared/embedded_document_list';
@use 'components/shared/form_group';
@use 'components/shared/rollable_image';
@use 'components/shared/sheet_body';
@use 'components/shared/sheet_form';
@use 'components/shared/sheet_tab_nav';
@use 'components/shared/sheet_tab';
// actor
@use "components/actor/actor_header";
@use "components/actor/actor_progression";
@use "components/actor/actor_properties";
@use "components/actor/actor_sheet";
@use "components/actor/biography";
@use "components/actor/check";
@use "components/actor/checks";
@use "components/actor/combat_value";
@use "components/actor/combat_values";
@use "components/actor/core_value";
@use "components/actor/core_values";
@use "components/actor/currency";
@use "components/actor/description";
@use "components/actor/profile";
@use 'components/actor/actor_header';
@use 'components/actor/actor_progression';
@use 'components/actor/actor_properties';
@use 'components/actor/actor_sheet';
@use 'components/actor/biography';
@use 'components/actor/check';
@use 'components/actor/checks';
@use 'components/actor/combat_value';
@use 'components/actor/combat_values';
@use 'components/actor/core_value';
@use 'components/actor/core_values';
@use 'components/actor/currency';
@use 'components/actor/description';
@use 'components/actor/profile';
// item
@use "components/item/item_header";
@use "components/item/item_properties";
@use "components/item/item_sheet";
@use 'components/item/item_header';
@use 'components/item/item_properties';
@use 'components/item/item_sheet';
// dice
@use "components/dice/dice_total";
@use 'components/dice/dice_total';

View file

@ -6,55 +6,55 @@
@font-face {
font-display: swap;
font-family: "Lora";
font-family: 'Lora';
font-style: normal;
font-weight: normal;
src:
local("Lora"),
url("../fonts/Lora/Lora.woff") format("woff");
local('Lora'),
url('../fonts/Lora/Lora.woff') format('woff');
}
@font-face {
font-display: swap;
font-family: "Lora";
font-family: 'Lora';
font-style: normal;
font-weight: bold;
src:
local("Lora"),
url("../fonts/Lora/Lora-Bold.woff") format("woff");
local('Lora'),
url('../fonts/Lora/Lora-Bold.woff') format('woff');
}
@font-face {
font-display: swap;
font-family: "Lora";
font-family: 'Lora';
font-style: italic;
font-weight: normal;
src:
local("Lora"),
url("../fonts/Lora/Lora-Italic.woff") format("woff");
local('Lora'),
url('../fonts/Lora/Lora-Italic.woff') format('woff');
}
@font-face {
font-display: swap;
font-family: "Lora";
font-family: 'Lora';
font-style: italic;
font-weight: bold;
src:
local("Lora"),
url("../fonts/Lora/Lora-BoldItalic.woff") format("woff");
local('Lora'),
url('../fonts/Lora/Lora-BoldItalic.woff') format('woff');
}
@font-face {
font-display: swap;
font-family: "Wood Stamp";
font-family: 'Wood Stamp';
font-style: normal;
font-weight: normal;
src:
local("Wood Stamp"),
url("../fonts/Woodstamp/Woodstamp.woff") format("woff");
local('Wood Stamp'),
url('../fonts/Woodstamp/Woodstamp.woff') format('woff');
}
:root {
--ds4-font-primary: Lora, serif;
--ds4-font-heading: "Wood Stamp", sans-serif;
--ds4-font-heading: 'Wood Stamp', sans-serif;
}

View file

@ -5,7 +5,7 @@
* SPDX-License-Identifier: MIT
*/
@use "./colors";
@use './colors';
@mixin centered-content {
display: grid;

View file

@ -4,7 +4,7 @@
* SPDX-License-Identifier: MIT
*/
@use "./colors";
@use './colors';
$padding-sm: 5px;
$padding-md: 10px;
@ -13,6 +13,6 @@ $margin-sm: $padding-sm;
$margin-md: $padding-md;
$margin-lg: $padding-lg;
$official-icons-path: "../assets/icons/official";
$official-icons-path: '../assets/icons/official';
$border-groove: 2px groove colors.$c-border-groove;

View file

@ -3,38 +3,38 @@
//
// 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", () => {
it("should throw an error.", () => {
expect(() => evaluateCheck([], 10)).toThrow("Invalid number of dice.");
describe('evaluateCheck with no dice', () => {
it('should throw an error.', () => {
expect(() => evaluateCheck([], 10)).toThrow('Invalid number of dice.');
});
});
describe("evaluateCheck with more dice than required by the checkTargetNumber", () => {
it("should throw an error.", () => {
expect(() => evaluateCheck([10, 10], 10)).toThrow("Invalid number of dice.");
describe('evaluateCheck with more dice than required by the checkTargetNumber', () => {
it('should throw an error.', () => {
expect(() => evaluateCheck([10, 10], 10)).toThrow('Invalid number of dice.');
});
});
describe("evaluateCheck with less dice than required by the checkTargetNumber", () => {
it("should throw an error.", () => {
expect(() => evaluateCheck([10], 21)).toThrow("Invalid number of dice.");
describe('evaluateCheck with less dice than required by the checkTargetNumber', () => {
it('should throw an error.', () => {
expect(() => evaluateCheck([10], 21)).toThrow('Invalid number of dice.');
});
});
describe("evaluateCheck with a single die", () => {
it("should assign the checkTargetNumber to the single die and be successful.", () => {
describe('evaluateCheck with a single die', () => {
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 }]);
});
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 }]);
});
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 }]);
});
@ -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([
{ 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++) {
expect(evaluateCheck([i], 0)).toEqual([
{ result: i, checkTargetNumber: 0, active: false, discarded: true },
]);
expect(evaluateCheck([i], 0)).toEqual([{ 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([
{ 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([
{ 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++) {
expect(evaluateCheck([i], -1)).toEqual([
{ result: i, checkTargetNumber: -1, active: false, discarded: true },
]);
expect(evaluateCheck([i], -1)).toEqual([{ 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([
{ 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 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'.", () => {
expect(evaluateCheck([20, 6, 15], 48)).toEqual([
{ 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([
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
{ 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([
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
{ 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([
{ 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([
{ result: 15, checkTargetNumber: 20, 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([
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
{ 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([
{ result: 1, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
{ 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'.", () => {
expect(evaluateCheck([19, 15, 6], 48, { maximumCoupResult: 2, minimumFumbleResult: 19 })).toEqual([
{ 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([
{ result: 15, checkTargetNumber: 8, active: false, discarded: true },
{ 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([
{ result: 15, checkTargetNumber: 20, 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([
{ result: 15, checkTargetNumber: 20, active: true, discarded: false },
{ 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([
{ result: 18, checkTargetNumber: 8, active: true, discarded: false, success: true, count: 8 },
{ result: 19, checkTargetNumber: 20, active: true, discarded: false, success: true, count: 20 },

View file

@ -2,19 +2,19 @@
//
// 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 = {
description: "",
description: '',
equipped: false,
spellType: "spellcasting",
spellType: 'spellcasting',
spellModifier: {
numerical: 0,
complex: "",
complex: '',
},
allowsDefense: false,
spellGroups: {
@ -37,18 +37,18 @@ const defaultData: DS4SpellDataSourceData = {
area: false,
},
maxDistance: {
value: "",
unit: "meter",
value: '',
unit: 'meter',
},
effectRadius: {
value: "",
unit: "meter",
value: '',
unit: 'meter',
},
duration: {
value: "",
unit: "custom",
value: '',
unit: 'custom',
},
cooldownDuration: "0r",
cooldownDuration: '0r',
minimumLevels: {
healer: null,
wizard: null,
@ -62,12 +62,12 @@ type TestCase = {
};
type CombinedTestCase = {
minimumLevels: DS4SpellDataSourceData["minimumLevels"];
minimumLevels: DS4SpellDataSourceData['minimumLevels'];
expected: number | null;
description: string;
};
const testCases: Record<keyof DS4SpellDataSourceData["minimumLevels"], TestCase[]> = {
const testCases: Record<keyof DS4SpellDataSourceData['minimumLevels'], TestCase[]> = {
healer: [
{ minimumLevel: null, expected: null },
{ minimumLevel: 1, expected: 10 },
@ -150,9 +150,7 @@ function buildCombinedTestCases(): CombinedTestCase[] {
for (const sorcererTestCase of testCases.sorcerer.filter(isRelevantPermutationTestCase)) {
for (const wizardTestCase of testCases.wizard.filter(isRelevantPermutationTestCase)) {
const expected =
healerTestCase.expected !== null ||
sorcererTestCase.expected !== null ||
wizardTestCase.expected !== null
healerTestCase.expected !== null || sorcererTestCase.expected !== null || wizardTestCase.expected !== null
? Math.min(
healerTestCase.expected ?? Infinity,
sorcererTestCase.expected ?? Infinity,
@ -177,7 +175,7 @@ function buildCombinedTestCases(): CombinedTestCase[] {
// single test cases
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)) {
const minimumLevels = {
...defaultData.minimumLevels,
@ -195,20 +193,20 @@ function buildCombinedTestCases(): CombinedTestCase[] {
return combinedTestCases;
}
describe("calculateSpellPrice", () => {
describe('calculateSpellPrice', () => {
const cooldownDurations: { cooldownDuration: CooldownDuration; factor: number }[] = [
{ cooldownDuration: "0r", factor: 1 },
{ cooldownDuration: "1r", factor: 1 },
{ cooldownDuration: "2r", factor: 1 },
{ cooldownDuration: "5r", factor: 1 },
{ cooldownDuration: "10r", factor: 1 },
{ cooldownDuration: "100r", factor: 1 },
{ cooldownDuration: "1d", factor: 2 },
{ cooldownDuration: "d20d", factor: 3 },
{ cooldownDuration: '0r', factor: 1 },
{ cooldownDuration: '1r', factor: 1 },
{ cooldownDuration: '2r', factor: 1 },
{ cooldownDuration: '5r', factor: 1 },
{ cooldownDuration: '10r', factor: 1 },
{ cooldownDuration: '100r', factor: 1 },
{ cooldownDuration: '1d', factor: 2 },
{ cooldownDuration: 'd20d', factor: 3 },
];
describe.each(cooldownDurations)(
"with cooldown duration set to $cooldownDuration",
'with cooldown duration set to $cooldownDuration',
({ cooldownDuration, factor }) => {
const dataWithCooldownDuration = {
...defaultData,

View file

@ -2,12 +2,12 @@
//
// 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", () => {
it("evaluates expressions that only use identifiers according to the given predicate", () => {
describe('Evaluator', () => {
it('evaluates expressions that only use identifiers according to the given predicate', () => {
// given
const expression = "typeof 'foo' === 'string' ? 42 : null";
@ -18,7 +18,7 @@ describe("Evaluator", () => {
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
const expression = "typeof 'foo' === 'string' ? 42 : function (){}";
@ -29,33 +29,33 @@ describe("Evaluator", () => {
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
const expression = "1;";
const expression = '1;';
// when
const evaluate = () => defaultEvaluator.evaluate(expression);
// 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
const expression = "(() => 1)()";
const expression = '(() => 1)()';
// when
const evaluate = () => defaultEvaluator.evaluate(expression);
// 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
const context = { floor: Math.floor };
const evaluator = new Evaluator({ context });
const expression = "floor(0.5)";
const expression = 'floor(0.5)';
// when
const result = evaluator.evaluate(expression);
@ -64,10 +64,10 @@ describe("Evaluator", () => {
expect(result).toEqual(0);
});
describe("mathEvaluator", () => {
it("makes the given context available", () => {
describe('mathEvaluator', () => {
it('makes the given context available', () => {
// given
const expression = "sqrt(sin(PI))";
const expression = 'sqrt(sin(PI))';
// when
const result = mathEvaluator.evaluate(expression);
@ -76,9 +76,9 @@ describe("Evaluator", () => {
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
const expression = "sqrt.constructor";
const expression = 'sqrt.constructor';
// when
const evaluate = () => mathEvaluator.evaluate(expression);

View file

@ -2,574 +2,574 @@
//
// 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[] }[] = [
{
input: "+",
input: '+',
expected: [
{ type: "+", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '+', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "-",
input: '-',
expected: [
{ type: "-", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '-', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "*",
input: '*',
expected: [
{ type: "*", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '*', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "**",
input: '**',
expected: [
{ type: "**", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '**', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "/",
input: '/',
expected: [
{ type: "/", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '/', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "%",
input: '%',
expected: [
{ type: "%", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '%', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "===",
input: '===',
expected: [
{ type: "===", pos: 0 },
{ type: "eof", pos: 3 },
{ type: '===', pos: 0 },
{ type: 'eof', pos: 3 },
],
},
{
input: "!==",
input: '!==',
expected: [
{ type: "!==", pos: 0 },
{ type: "eof", pos: 3 },
{ type: '!==', pos: 0 },
{ type: 'eof', pos: 3 },
],
},
{
input: "==",
input: '==',
expected: [
{ type: "==", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '==', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "<",
input: '<',
expected: [
{ type: "<", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '<', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "<=",
input: '<=',
expected: [
{ type: "<=", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '<=', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: ">",
input: '>',
expected: [
{ type: ">", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '>', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: ">=",
input: '>=',
expected: [
{ type: ">=", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '>=', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "&&",
input: '&&',
expected: [
{ type: "&&", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '&&', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "||",
input: '||',
expected: [
{ type: "||", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '||', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "&",
input: '&',
expected: [
{ type: "&", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '&', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "|",
input: '|',
expected: [
{ type: "|", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '|', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "<<",
input: '<<',
expected: [
{ type: "<<", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '<<', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: ">>>",
input: '>>>',
expected: [
{ type: ">>>", pos: 0 },
{ type: "eof", pos: 3 },
{ type: '>>>', pos: 0 },
{ type: 'eof', pos: 3 },
],
},
{
input: ".",
input: '.',
expected: [
{ type: ".", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '.', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "?.",
input: '?.',
expected: [
{ type: "?.", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '?.', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "??",
input: '??',
expected: [
{ type: "??", pos: 0 },
{ type: "eof", pos: 2 },
{ type: '??', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "?",
input: '?',
expected: [
{ type: "?", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '?', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: ":",
input: ':',
expected: [
{ type: ":", pos: 0 },
{ type: "eof", pos: 1 },
{ type: ':', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "(",
input: '(',
expected: [
{ type: "(", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '(', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: ")",
input: ')',
expected: [
{ type: ")", pos: 0 },
{ type: "eof", pos: 1 },
{ type: ')', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "[",
input: '[',
expected: [
{ type: "[", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '[', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "]",
input: ']',
expected: [
{ type: "]", pos: 0 },
{ type: "eof", pos: 1 },
{ type: ']', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: ",",
input: ',',
expected: [
{ type: ",", pos: 0 },
{ type: "eof", pos: 1 },
{ type: ',', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "{",
input: '{',
expected: [
{ type: "{", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '{', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "}",
input: '}',
expected: [
{ type: "}", pos: 0 },
{ type: "eof", pos: 1 },
{ type: '}', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
];
const singleNumberTestCases: { input: string; expected: Token[] }[] = [
{
input: "1",
input: '1',
expected: [
{ type: "number", symbol: "1", pos: 0 },
{ type: "eof", pos: 1 },
{ type: 'number', symbol: '1', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "42",
input: '42',
expected: [
{ type: "number", symbol: "42", pos: 0 },
{ type: "eof", pos: 2 },
{ type: 'number', symbol: '42', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "42.9",
input: '42.9',
expected: [
{ type: "number", symbol: "42.9", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'number', symbol: '42.9', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: ".9",
input: '.9',
expected: [
{ type: "number", symbol: ".9", pos: 0 },
{ type: "eof", pos: 2 },
{ type: 'number', symbol: '.9', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "1_1",
input: '1_1',
expected: [
{ type: "number", symbol: "1_1", pos: 0 },
{ type: "eof", pos: 3 },
{ type: 'number', symbol: '1_1', pos: 0 },
{ type: 'eof', pos: 3 },
],
},
{
input: "10_1",
input: '10_1',
expected: [
{ type: "number", symbol: "10_1", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'number', symbol: '10_1', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "1_1_1",
input: '1_1_1',
expected: [
{ type: "number", symbol: "1_1_1", pos: 0 },
{ type: "eof", pos: 5 },
{ type: 'number', symbol: '1_1_1', pos: 0 },
{ type: 'eof', pos: 5 },
],
},
{
input: ".1_1",
input: '.1_1',
expected: [
{ type: "number", symbol: ".1_1", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'number', symbol: '.1_1', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
];
const invalidNumberTestCases: { input: string; expected: Token[] }[] = [
{ input: "1.1.1", expected: [{ type: "invalid", pos: 0 }] },
{ input: "1__1", expected: [{ type: "invalid", pos: 0 }] },
{ input: "1_", expected: [{ type: "invalid", pos: 0 }] },
{ input: "1._1", expected: [{ type: "invalid", pos: 0 }] },
{ input: "0_1", expected: [{ type: "invalid", pos: 0 }] },
{ input: "00_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_', expected: [{ type: 'invalid', pos: 0 }] },
{ input: '1._1', expected: [{ type: 'invalid', pos: 0 }] },
{ input: '0_1', expected: [{ type: 'invalid', pos: 0 }] },
{ input: '00_1', expected: [{ type: 'invalid', pos: 0 }] },
];
const singleIdentifierTestCases: { input: string; expected: Token[] }[] = [
{
input: "foo",
input: 'foo',
expected: [
{ type: "iden", symbol: "foo", pos: 0 },
{ type: "eof", pos: 3 },
{ type: 'iden', symbol: 'foo', pos: 0 },
{ type: 'eof', pos: 3 },
],
},
{
input: "_foo",
input: '_foo',
expected: [
{ type: "iden", symbol: "_foo", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'iden', symbol: '_foo', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "$foo",
input: '$foo',
expected: [
{ type: "iden", symbol: "$foo", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'iden', symbol: '$foo', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "foo1",
input: 'foo1',
expected: [
{ type: "iden", symbol: "foo1", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'iden', symbol: 'foo1', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "_foo1_",
input: '_foo1_',
expected: [
{ type: "iden", symbol: "_foo1_", pos: 0 },
{ type: "eof", pos: 6 },
{ type: 'iden', symbol: '_foo1_', pos: 0 },
{ type: 'eof', pos: 6 },
],
},
{
input: "μ",
input: 'μ',
expected: [
{ type: "iden", symbol: "μ", pos: 0 },
{ type: "eof", pos: 1 },
{ type: 'iden', symbol: 'μ', pos: 0 },
{ type: 'eof', pos: 1 },
],
},
{
input: "._1",
input: '._1',
expected: [
{ type: ".", pos: 0 },
{ type: "iden", symbol: "_1", pos: 1 },
{ type: "eof", pos: 3 },
{ type: '.', pos: 0 },
{ type: 'iden', symbol: '_1', pos: 1 },
{ type: 'eof', pos: 3 },
],
},
{
input: "true",
input: 'true',
expected: [
{ type: "iden", symbol: "true", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'iden', symbol: 'true', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "false",
input: 'false',
expected: [
{ type: "iden", symbol: "false", pos: 0 },
{ type: "eof", pos: 5 },
{ type: 'iden', symbol: 'false', pos: 0 },
{ type: 'eof', pos: 5 },
],
},
{
input: "null",
input: 'null',
expected: [
{ type: "iden", symbol: "null", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'iden', symbol: 'null', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "undefined",
input: 'undefined',
expected: [
{ type: "iden", symbol: "undefined", pos: 0 },
{ type: "eof", pos: 9 },
{ type: 'iden', symbol: 'undefined', pos: 0 },
{ type: 'eof', pos: 9 },
],
},
];
const invalidIdentifierTestCases: { input: string; expected: Token[] }[] = [
{
input: "1foo",
input: '1foo',
expected: [
{ type: "number", symbol: "1", pos: 0 },
{ type: "iden", symbol: "foo", pos: 1 },
{ type: "eof", pos: 4 },
{ type: 'number', symbol: '1', pos: 0 },
{ type: 'iden', symbol: 'foo', pos: 1 },
{ 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[] }[] = [
{
input: '""',
expected: [
{ type: "string", symbol: '""', pos: 0 },
{ type: "eof", pos: 2 },
{ type: 'string', symbol: '""', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: '"foo"',
expected: [
{ type: "string", symbol: '"foo"', pos: 0 },
{ type: "eof", pos: 5 },
{ type: 'string', symbol: '"foo"', pos: 0 },
{ type: 'eof', pos: 5 },
],
},
{
input: '"\\""',
expected: [
{ type: "string", symbol: '"\\""', pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: '"\\""', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: '"\\\'"',
expected: [
{ type: "string", symbol: '"\\\'"', pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: '"\\\'"', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "''",
expected: [
{ type: "string", symbol: "''", pos: 0 },
{ type: "eof", pos: 2 },
{ type: 'string', symbol: "''", pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "'foo'",
expected: [
{ type: "string", symbol: "'foo'", pos: 0 },
{ type: "eof", pos: 5 },
{ type: 'string', symbol: "'foo'", pos: 0 },
{ type: 'eof', pos: 5 },
],
},
{
input: "'\\''",
expected: [
{ type: "string", symbol: "'\\''", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: "'\\''", pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "'\\\"'",
expected: [
{ type: "string", symbol: "'\\\"'", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: "'\\\"'", pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: "``",
input: '``',
expected: [
{ type: "string", symbol: "``", pos: 0 },
{ type: "eof", pos: 2 },
{ type: 'string', symbol: '``', pos: 0 },
{ type: 'eof', pos: 2 },
],
},
{
input: "`foo`",
input: '`foo`',
expected: [
{ type: "string", symbol: "`foo`", pos: 0 },
{ type: "eof", pos: 5 },
{ type: 'string', symbol: '`foo`', pos: 0 },
{ type: 'eof', pos: 5 },
],
},
{
input: "`\\``",
input: '`\\``',
expected: [
{ type: "string", symbol: "`\\``", pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: '`\\``', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
{
input: '`\\"`',
expected: [
{ type: "string", symbol: '`\\"`', pos: 0 },
{ type: "eof", pos: 4 },
{ type: 'string', symbol: '`\\"`', pos: 0 },
{ type: 'eof', pos: 4 },
],
},
];
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[] }[] = [
{ input: " ", expected: [{ type: "eof", pos: 1 }] },
{ input: " ", expected: [{ type: "eof", pos: 3 }] },
{ input: "\n", expected: [{ type: "eof", pos: 1 }] },
{ input: " \n", expected: [{ type: "eof", pos: 2 }] },
{ input: " ", expected: [{ type: "eof", pos: 1 }] },
{ input: ' ', expected: [{ type: 'eof', pos: 1 }] },
{ input: ' ', expected: [{ type: 'eof', pos: 3 }] },
{ input: '\n', expected: [{ type: 'eof', pos: 1 }] },
{ input: ' \n', expected: [{ type: 'eof', pos: 2 }] },
{ input: ' ', expected: [{ type: 'eof', pos: 1 }] },
];
const complicatedTermTestCases: { input: string; expected: Token[] }[] = [
{
input: "5x",
input: '5x',
expected: [
{ type: "number", symbol: "5", pos: 0 },
{ type: "iden", symbol: "x", pos: 1 },
{ type: "eof", pos: 2 },
{ type: 'number', symbol: '5', pos: 0 },
{ type: 'iden', symbol: 'x', pos: 1 },
{ type: 'eof', pos: 2 },
],
},
{
input: "5*x",
input: '5*x',
expected: [
{ type: "number", symbol: "5", pos: 0 },
{ type: "*", pos: 1 },
{ type: "iden", symbol: "x", pos: 2 },
{ type: "eof", pos: 3 },
{ type: 'number', symbol: '5', pos: 0 },
{ type: '*', pos: 1 },
{ type: 'iden', symbol: 'x', pos: 2 },
{ type: 'eof', pos: 3 },
],
},
{
input: "5 * x",
input: '5 * x',
expected: [
{ type: "number", symbol: "5", pos: 0 },
{ type: "*", pos: 2 },
{ type: "iden", symbol: "x", pos: 4 },
{ type: "eof", pos: 5 },
{ type: 'number', symbol: '5', pos: 0 },
{ type: '*', pos: 2 },
{ type: 'iden', symbol: 'x', pos: 4 },
{ type: 'eof', pos: 5 },
],
},
{
input: "(5 * 5 + 2) / 1.2 === 'foo'",
expected: [
{ type: "(", pos: 0 },
{ type: "number", symbol: "5", pos: 1 },
{ type: "*", pos: 3 },
{ type: "number", symbol: "5", pos: 5 },
{ type: "+", pos: 7 },
{ type: "number", symbol: "2", pos: 9 },
{ type: ")", pos: 10 },
{ type: "/", pos: 12 },
{ type: "number", symbol: "1.2", pos: 14 },
{ type: "===", pos: 18 },
{ type: "string", symbol: "'foo'", pos: 22 },
{ type: "eof", pos: 27 },
{ type: '(', pos: 0 },
{ type: 'number', symbol: '5', pos: 1 },
{ type: '*', pos: 3 },
{ type: 'number', symbol: '5', pos: 5 },
{ type: '+', pos: 7 },
{ type: 'number', symbol: '2', pos: 9 },
{ type: ')', pos: 10 },
{ type: '/', pos: 12 },
{ type: 'number', symbol: '1.2', pos: 14 },
{ type: '===', pos: 18 },
{ type: 'string', symbol: "'foo'", pos: 22 },
{ type: 'eof', pos: 27 },
],
},
{
input: "(() => {console.log('foo'); return 1;})()",
expected: [
{ type: "(", pos: 0 },
{ type: "(", pos: 1 },
{ type: ")", pos: 2 },
{ type: "invalid", pos: 4 },
{ type: '(', pos: 0 },
{ type: '(', pos: 1 },
{ type: ')', pos: 2 },
{ type: 'invalid', pos: 4 },
],
},
{
input: "(function() {console.log('foo'); return 1;})()",
expected: [
{ type: "(", pos: 0 },
{ type: "iden", symbol: "function", pos: 1 },
{ type: "(", pos: 9 },
{ type: ")", pos: 10 },
{ type: "{", pos: 12 },
{ type: "iden", symbol: "console", pos: 13 },
{ type: ".", pos: 20 },
{ type: "iden", symbol: "log", pos: 21 },
{ type: "(", pos: 24 },
{ type: "string", symbol: "'foo'", pos: 25 },
{ type: ")", pos: 30 },
{ type: "invalid", pos: 31 },
{ type: '(', pos: 0 },
{ type: 'iden', symbol: 'function', pos: 1 },
{ type: '(', pos: 9 },
{ type: ')', pos: 10 },
{ type: '{', pos: 12 },
{ type: 'iden', symbol: 'console', pos: 13 },
{ type: '.', pos: 20 },
{ type: 'iden', symbol: 'log', pos: 21 },
{ type: '(', pos: 24 },
{ type: 'string', symbol: "'foo'", pos: 25 },
{ type: ')', pos: 30 },
{ type: 'invalid', pos: 31 },
],
},
{
input: "'ranged' === 'ranged'",
expected: [
{ type: "string", symbol: "'ranged'", pos: 0 },
{ type: "===", pos: 9 },
{ type: "string", symbol: "'ranged'", pos: 13 },
{ type: "eof", pos: 21 },
{ type: 'string', symbol: "'ranged'", pos: 0 },
{ type: '===', pos: 9 },
{ type: 'string', symbol: "'ranged'", pos: 13 },
{ type: 'eof', pos: 21 },
],
},
];
@ -584,7 +584,7 @@ describe("Lexer", () => {
...invalidStringTestCases,
...whiteSpaceTestCases,
...complicatedTermTestCases,
])("lexes $input correctly", ({ input, expected }) => {
])('lexes $input correctly', ({ input, expected }) => {
// when
const result = consume(new Lexer(input));

View file

@ -2,17 +2,17 @@
//
// 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 { Validator } from "../../src/expression-evaluation/validator";
import { literals, safeOperators } from '../../src/expression-evaluation/grammar';
import { Validator } from '../../src/expression-evaluation/validator';
describe("Validator", () => {
it("allows identifier according to the given predicate", () => {
describe('Validator', () => {
it('allows identifier according to the given predicate', () => {
// given
const predicate = (identifier: string) => identifier === "true";
const predicate = (identifier: string) => identifier === 'true';
const validator = new Validator(predicate);
const input = "true";
const input = 'true';
// when
const validate = () => validator.validate(input);
@ -21,11 +21,11 @@ describe("Validator", () => {
expect(validate).not.toThrow();
});
it("disallows identifier according to the given predicate", () => {
it('disallows identifier according to the given predicate', () => {
// given
const predicate = (identifier: string) => identifier === "false";
const predicate = (identifier: string) => identifier === 'false';
const validator = new Validator(predicate);
const input = "true";
const input = 'true';
// when
const validate = () => validator.validate(input);
@ -34,11 +34,11 @@ describe("Validator", () => {
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
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
const validator = new Validator(predicate);
const input = "true null";
const input = 'true null';
// when
const validate = () => validator.validate(input);
@ -47,11 +47,11 @@ describe("Validator", () => {
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
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
const validator = new Validator(predicate);
const input = "true === null";
const input = 'true === null';
// when
const validate = () => validator.validate(input);
@ -60,11 +60,11 @@ describe("Validator", () => {
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
const predicate = (identifier: string) => identifier === "true" || identifier === "null";
const predicate = (identifier: string) => identifier === 'true' || identifier === 'null';
const validator = new Validator(predicate);
const input = "true === null && undefined === false";
const input = 'true === null && undefined === false';
// when
const validate = () => validator.validate(input);
@ -73,22 +73,21 @@ describe("Validator", () => {
expect(validate).toThrowError("'undefined' is not an allowed identifier.");
});
it("disallows invalid invalid tokens", () => {
it('disallows invalid invalid tokens', () => {
// given
const validator = new Validator();
const input = ";";
const input = ';';
// when
const validate = () => validator.validate(input);
// 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
const predicate = (identifier: string) =>
[...safeOperators, ...literals, "floor", "random"].includes(identifier);
const predicate = (identifier: string) => [...safeOperators, ...literals, 'floor', 'random'].includes(identifier);
const validator = new Validator(predicate);
const input = "typeof (floor(random() * 5) / 2) === 'number' ? 42 : 'foo'";
@ -99,9 +98,9 @@ describe("Validator", () => {
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
const predicate = (identifier: string) => [...safeOperators, ...literals, "ceil"].includes(identifier);
const predicate = (identifier: string) => [...safeOperators, ...literals, 'ceil'].includes(identifier);
const validator = new Validator(predicate);
const input = "ceil.constructor('alert(1); return 1;')()";
@ -112,15 +111,15 @@ describe("Validator", () => {
expect(validate).toThrowError("'constructor' is not an allowed identifier.");
});
it("disallows arrow functions", () => {
it('disallows arrow functions', () => {
// given
const validator = new Validator();
const input = "() => {}";
const input = '() => {}';
// when
const validate = () => validator.validate(input);
// then
expect(validate).toThrowError("Invalid or unexpected token (3)");
expect(validate).toThrowError('Invalid or unexpected token (3)');
});
});

View file

@ -2,13 +2,13 @@
//
// SPDX-License-Identifier: MIT
import { describe, expect, it } from "vitest";
import { describe, expect, it } from 'vitest';
import de from "../../lang/de.json";
import en from "../../lang/en.json";
import de from '../../lang/de.json';
import en from '../../lang/en.json';
describe("English and german localization files", () => {
it("should have the same keys.", () => {
describe('English and german localization files', () => {
it('should have the same keys.', () => {
const deKeys = Object.keys(de);
const enKeys = Object.keys(en);
expect(deKeys).toEqual(enKeys);

View file

@ -2,23 +2,23 @@
//
// SPDX-License-Identifier: MIT
import en from "../lang/en.json";
import en from '../lang/en.json';
function setupPrimitives() {
Object.defineProperties(Number, {
isNumeric: {
value: function (n: unknown) {
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
return +n === +n;
},
},
fromString: {
value: function (str: unknown) {
if (typeof str !== "string" || !str.length) return NaN;
if (typeof str !== 'string' || !str.length) return NaN;
// Remove whitespace.
str = str.replace(/\s+/g, "");
str = str.replace(/\s+/g, '');
return Number(str);
},
},

View file

@ -6,7 +6,7 @@ export class DS4ActiveEffectConfig extends ActiveEffectConfig {
/** @override */
static get 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) {
super.activateListeners(html);
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
*/
#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) => {
if (active) {
element.classList.remove("ds4-hidden");
element.classList.remove('ds4-hidden');
} else {
element.classList.add("ds4-hidden");
element.classList.add('ds4-hidden');
}
});
this.setPosition({ height: "auto" });
this.setPosition({ height: 'auto' });
}
}

View file

@ -5,13 +5,13 @@
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../../config";
import { DS4ActiveEffect } from "../../documents/active-effect";
import { isCheck } from "../../documents/actor/actor-data-properties-base";
import { getDS4Settings } from "../../settings";
import { notifications } from "../../ui/notifications";
import { enforce, getCanvas, getGame } from "../../utils/utils";
import { disableOverriddenFields } from "../sheet-helpers";
import { DS4 } from '../../config';
import { DS4ActiveEffect } from '../../documents/active-effect';
import { isCheck } from '../../documents/actor/actor-data-properties-base';
import { getDS4Settings } from '../../settings';
import { notifications } from '../../ui/notifications';
import { enforce, getCanvas, getGame } from '../../utils/utils';
import { disableOverriddenFields } from '../sheet-helpers';
/**
* The base sheet class for all {@link DS4Actor}s.
@ -20,14 +20,14 @@ export class DS4ActorSheet extends ActorSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sheet", "ds4-actor-sheet"],
classes: ['sheet', 'ds4-actor-sheet'],
height: 645,
scrollY: [".ds4-sheet-body"],
tabs: [{ navSelector: ".ds4-sheet-tab-nav", contentSelector: ".ds4-sheet-body", initial: "values" }],
scrollY: ['.ds4-sheet-body'],
tabs: [{ navSelector: '.ds4-sheet-tab-nav', contentSelector: '.ds4-sheet-body', initial: 'values' }],
dragDrop: [
{ dragSelector: ".item-list .item", dropSelector: null },
{ dragSelector: ".effect-list .effect", dropSelector: null },
{ dragSelector: ".ds4-check", dropSelector: null },
{ dragSelector: '.item-list .item', dropSelector: null },
{ dragSelector: '.effect-list .effect', dropSelector: null },
{ dragSelector: '.ds4-check', dropSelector: null },
],
width: 650,
});
@ -35,7 +35,7 @@ export class DS4ActorSheet extends ActorSheet {
/** @override */
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`;
return `${basePath}/${this.actor.type}-sheet.hbs`;
}
@ -74,11 +74,7 @@ export class DS4ActorSheet extends ActorSheet {
* @protected
*/
addTooltipsToData(context) {
const valueGroups = [
context.data.system.attributes,
context.data.system.traits,
context.data.system.combatValues,
];
const valueGroups = [context.data.system.attributes, context.data.system.traits, context.data.system.combatValues];
valueGroups.forEach((valueGroup) => {
Object.values(valueGroup).forEach((attribute) => {
@ -95,9 +91,9 @@ export class DS4ActorSheet extends ActorSheet {
* @protected
*/
getTooltipForValue(value) {
return `${value.base} (${getGame().i18n.localize("DS4.TooltipBaseValue")}) + ${
return `${value.base} (${getGame().i18n.localize('DS4.TooltipBaseValue')}) + ${
value.mod
} (${getGame().i18n.localize("DS4.TooltipModifier")}) ${getGame().i18n.localize("DS4.TooltipEffects")} ${
} (${getGame().i18n.localize('DS4.TooltipModifier')}) ${getGame().i18n.localize('DS4.TooltipEffects')} ${
value.total
}`;
}
@ -111,16 +107,16 @@ export class DS4ActorSheet extends ActorSheet {
if (!this.options.editable) return;
html.find(".control-item").on("click", this.onControlItem.bind(this));
html.find(".change-item").on("change", this.onChangeItem.bind(this));
html.find('.control-item').on('click', this.onControlItem.bind(this));
html.find('.change-item').on('change', this.onChangeItem.bind(this));
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
html.find(".change-effect").on("change", this.onChangeEffect.bind(this));
html.find('.control-effect').on('click', this.onControlEffect.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-check").on("click", this.onRollCheck.bind(this));
html.find('.rollable-item').on('click', this.onRollItem.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}"]`);
for (const item of this.actor.items) {
@ -141,12 +137,12 @@ export class DS4ActorSheet extends ActorSheet {
onControlItem(event) {
event.preventDefault();
const a = event.currentTarget;
switch (a.dataset["action"]) {
case "create":
switch (a.dataset['action']) {
case 'create':
return this.onCreateItem(event);
case "edit":
case 'edit':
return this.onEditItem(event);
case "delete":
case 'delete':
return this.onDeleteItem(event);
}
}
@ -176,7 +172,7 @@ export class DS4ActorSheet extends ActorSheet {
const item = await fromUuid(uuid);
enforce(
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);
}
@ -193,7 +189,7 @@ export class DS4ActorSheet extends ActorSheet {
const item = await fromUuid(uuid);
enforce(
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();
$(li).slideUp(200, () => this.render(false));
@ -207,7 +203,7 @@ export class DS4ActorSheet extends ActorSheet {
* @protected
*/
onChangeItem(event) {
return this.onChangeEmbeddedDocument(event, "Item");
return this.onChangeEmbeddedDocument(event, 'Item');
}
/**
@ -220,12 +216,12 @@ export class DS4ActorSheet extends ActorSheet {
onControlEffect(event) {
event.preventDefault();
const a = event.currentTarget;
switch (a.dataset["action"]) {
case "create":
switch (a.dataset['action']) {
case 'create':
return this.onCreateEffect();
case "edit":
case 'edit':
return this.onEditEffect(event);
case "delete":
case 'delete':
return this.onDeleteEffect(event);
}
}
@ -252,7 +248,7 @@ export class DS4ActorSheet extends ActorSheet {
const effect = await fromUuid(uuid);
enforce(
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);
}
@ -269,7 +265,7 @@ export class DS4ActorSheet extends ActorSheet {
const effect = await fromUuid(uuid);
enforce(
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();
$(li).slideUp(200, () => this.render(false));
@ -283,7 +279,7 @@ export class DS4ActorSheet extends ActorSheet {
* @protected
*/
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 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"));
const newValue = this.parseValue(element);
const document = await fromUuid(uuid);
if (documentName === "Item") {
if (documentName === 'Item') {
enforce(
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 {
enforce(
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 });
@ -335,23 +331,21 @@ export class DS4ActorSheet extends ActorSheet {
*/
parseValue(element) {
switch (element.type) {
case "checkbox": {
const inverted = Boolean(element.dataset["inverted"]);
case 'checkbox': {
const inverted = Boolean(element.dataset['inverted']);
const value = element.checked;
return inverted ? !value : value;
}
case "text": {
case 'text': {
const value = element.value;
return value;
}
case "number": {
case 'number': {
const value = Number(element.value.trim());
return value;
}
default: {
throw new TypeError(
"Binding of item property to this type of HTML element not supported; given: " + element,
);
throw new TypeError('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);
enforce(
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 }));
}
@ -381,7 +375,7 @@ export class DS4ActorSheet extends ActorSheet {
onRollCheck(event) {
event.preventDefault();
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 }));
}
@ -396,17 +390,17 @@ export class DS4ActorSheet extends ActorSheet {
const check = target.dataset.check;
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 = {
actorId: this.actor.id,
sceneId: this.actor.isToken ? getCanvas().scene?.id : null,
tokenId: this.actor.isToken ? this.actor.token?.id : null,
type: "Check",
type: '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) {
event.preventDefault();
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}`);
const dataPath = target.dataset["dataPath"];
const dataPath = target.dataset['dataPath'];
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[]}*/
const items = this.actor.items.filter((item) => item.type === type);
items.sort((a, b) => a.sort - b.sort);
@ -434,14 +428,14 @@ export class DS4ActorSheet extends ActorSheet {
const propertyA = getProperty(a, dataPath);
const propertyB = getProperty(b, dataPath);
const comparison =
typeof propertyA === "string" || typeof propertyB === "string"
typeof propertyA === 'string' || typeof propertyB === 'string'
? compareAsStrings(propertyA, propertyB, invert)
: compareAsNumbers(propertyA, propertyB, invert);
if (comparison === 0 && dataPath2 !== undefined) {
const propertyA = getProperty(a, dataPath);
const propertyB = getProperty(b, dataPath);
return typeof propertyA === "string" || typeof propertyB === "string"
return typeof propertyA === 'string' || typeof propertyB === 'string'
? compareAsStrings(propertyA, propertyB, invert)
: compareAsNumbers(propertyA, propertyB, invert);
}
@ -461,7 +455,7 @@ export class DS4ActorSheet extends ActorSheet {
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);
if (item && !this.actor.canOwnItemType(item.type)) {
notifications.warn(
getGame().i18n.format("DS4.WarningActorCannotOwnItem", {
getGame().i18n.format('DS4.WarningActorCannotOwnItem', {
actorName: this.actor.name,
actorType: this.actor.type,
itemName: item.name,
@ -491,12 +485,12 @@ export class DS4ActorSheet extends ActorSheet {
*/
const embeddedDocumentListEntryProperties = Object.freeze({
ActiveEffect: {
selector: ".effect",
uuidDataAttribute: "effectUuid",
selector: '.effect',
uuidDataAttribute: 'effectUuid',
},
Item: {
selector: ".item",
uuidDataAttribute: "itemUuid",
selector: '.item',
uuidDataAttribute: 'itemUuid',
},
});

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4ActorSheet } from "./base-sheet";
import { DS4ActorSheet } from './base-sheet';
/**
* The Sheet class for DS4 Character Actors
@ -10,7 +10,7 @@ import { DS4ActorSheet } from "./base-sheet";
export class DS4CharacterActorSheet extends DS4ActorSheet {
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sheet", "ds4-actor-sheet", "ds4-character-sheet"],
classes: ['sheet', 'ds4-actor-sheet', 'ds4-character-sheet'],
});
}

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4ActorSheet } from "./base-sheet";
import { DS4ActorSheet } from './base-sheet';
/**
* The Sheet class for DS4 Creature Actors
@ -10,17 +10,16 @@ import { DS4ActorSheet } from "./base-sheet";
export class DS4CreatureActorSheet extends DS4ActorSheet {
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sheet", "ds4-actor-sheet", "ds4-creature-sheet"],
classes: ['sheet', 'ds4-actor-sheet', 'ds4-creature-sheet'],
});
}
/** @override */
async getData(options = {}) {
const context = await super.getData(options);
context.data.system.baseInfo.description = await TextEditor.enrichHTML(
context.data.system.baseInfo.description,
{ async: true },
);
context.data.system.baseInfo.description = await TextEditor.enrichHTML(context.data.system.baseInfo.description, {
async: true,
});
return context;
}
}

View file

@ -4,10 +4,10 @@
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../config";
import { DS4ActiveEffect } from "../documents/active-effect";
import { enforce, getGame } from "../utils/utils";
import { disableOverriddenFields } from "./sheet-helpers";
import { DS4 } from '../config';
import { DS4ActiveEffect } from '../documents/active-effect';
import { enforce, getGame } from '../utils/utils';
import { disableOverriddenFields } from './sheet-helpers';
/**
* The Sheet class for DS4 Items
@ -16,17 +16,17 @@ export class DS4ItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["sheet", "ds4-item-sheet"],
classes: ['sheet', 'ds4-item-sheet'],
height: 400,
scrollY: [".ds4-sheet-body"],
tabs: [{ navSelector: ".ds4-sheet-tab-nav", contentSelector: ".ds4-sheet-body", initial: "description" }],
scrollY: ['.ds4-sheet-body'],
tabs: [{ navSelector: '.ds4-sheet-tab-nav', contentSelector: '.ds4-sheet-body', initial: 'description' }],
width: 540,
});
}
/** @override */
get template() {
const basePath = "systems/ds4/templates/sheets/item";
const basePath = 'systems/ds4/templates/sheets/item';
return `${basePath}/${this.item.type}-sheet.hbs`;
}
@ -60,9 +60,9 @@ export class DS4ItemSheet extends ItemSheet {
setPosition(options = {}) {
const position = super.setPosition(options);
if (position) {
const sheetBody = this.element.find(".sheet-body");
const sheetBody = this.element.find('.sheet-body');
const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight);
sheetBody.css('height', bodyHeight);
}
return position;
@ -77,7 +77,7 @@ export class DS4ItemSheet extends ItemSheet {
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}"]`);
}
@ -92,12 +92,12 @@ export class DS4ItemSheet extends ItemSheet {
onControlEffect(event) {
event.preventDefault();
const a = event.currentTarget;
switch (a.dataset["action"]) {
case "create":
switch (a.dataset['action']) {
case 'create':
return this.onCreateEffect();
case "edit":
case 'edit':
return this.onEditEffect(event);
case "delete":
case 'delete':
return this.onDeleteEffect(event);
}
}
@ -121,7 +121,7 @@ export class DS4ItemSheet extends ItemSheet {
.parents(embeddedDocumentListEntryProperties.ActiveEffect.selector)
.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
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);
}
@ -134,7 +134,7 @@ export class DS4ItemSheet extends ItemSheet {
onDeleteEffect(event) {
const li = $(event.currentTarget).parents(embeddedDocumentListEntryProperties.ActiveEffect.selector);
const id = li.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
this.item.deleteEmbeddedDocuments("ActiveEffect", [id]);
this.item.deleteEmbeddedDocuments('ActiveEffect', [id]);
li.slideUp(200, () => this.render(false));
}
}
@ -144,7 +144,7 @@ export class DS4ItemSheet extends ItemSheet {
*/
const embeddedDocumentListEntryProperties = Object.freeze({
ActiveEffect: {
selector: ".effect",
idDataAttribute: "effectId",
selector: '.effect',
idDataAttribute: 'effectId',
},
});

View file

@ -2,7 +2,7 @@
//
// 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.
@ -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
*/
export function disableOverriddenFields(form, overrides, selector) {
const inputs = ["INPUT", "SELECT", "TEXTAREA", "BUTTON"];
const titleAddition = `(${getGame().i18n.localize("DS4.TooltipNotEditableDueToEffects")})`;
const inputs = ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'];
const titleAddition = `(${getGame().i18n.localize('DS4.TooltipNotEditableDueToEffects')})`;
for (const key of Object.keys(foundry.utils.flattenObject(overrides))) {
const elements = form?.querySelectorAll(selector(key));
elements?.forEach((element) => {
if (inputs.includes(element.tagName) && !element.hasAttribute("disabled")) {
element.setAttribute("disabled", "");
const title = element.getAttribute("title");
if (inputs.includes(element.tagName) && !element.hasAttribute('disabled')) {
element.setAttribute('disabled', '');
const title = element.getAttribute('title');
const newTitle = title === null ? titleAddition : `${title} ${titleAddition}`;
element.setAttribute("title", newTitle);
element.setAttribute('title', newTitle);
}
});
}

View file

@ -10,348 +10,348 @@ const i18nKeys = {
* Define the set of acttack types that can be performed with weapon items
*/
attackTypes: {
melee: "DS4.AttackTypeMelee",
ranged: "DS4.AttackTypeRanged",
meleeRanged: "DS4.AttackTypeMeleeRanged",
melee: 'DS4.AttackTypeMelee',
ranged: 'DS4.AttackTypeRanged',
meleeRanged: 'DS4.AttackTypeMeleeRanged',
},
/**
* Define the set of item availabilties
*/
itemAvailabilities: {
unset: "DS4.ItemAvailabilityUnset",
hamlet: "DS4.ItemAvailabilityHamlet",
village: "DS4.ItemAvailabilityVilage",
city: "DS4.ItemAvailabilityCity",
elves: "DS4.ItemAvailabilityElves",
dwarves: "DS4.ItemAvailabilityDwarves",
nowhere: "DS4.ItemAvailabilityNowhere",
unset: 'DS4.ItemAvailabilityUnset',
hamlet: 'DS4.ItemAvailabilityHamlet',
village: 'DS4.ItemAvailabilityVilage',
city: 'DS4.ItemAvailabilityCity',
elves: 'DS4.ItemAvailabilityElves',
dwarves: 'DS4.ItemAvailabilityDwarves',
nowhere: 'DS4.ItemAvailabilityNowhere',
},
/**
* Define the set of item types
*/
itemTypes: {
weapon: "DS4.ItemTypeWeapon",
armor: "DS4.ItemTypeArmor",
shield: "DS4.ItemTypeShield",
spell: "DS4.ItemTypeSpell",
equipment: "DS4.ItemTypeEquipment",
loot: "DS4.ItemTypeLoot",
talent: "DS4.ItemTypeTalent",
racialAbility: "DS4.ItemTypeRacialAbility",
language: "DS4.ItemTypeLanguage",
alphabet: "DS4.ItemTypeAlphabet",
specialCreatureAbility: "DS4.ItemTypeSpecialCreatureAbility",
weapon: 'DS4.ItemTypeWeapon',
armor: 'DS4.ItemTypeArmor',
shield: 'DS4.ItemTypeShield',
spell: 'DS4.ItemTypeSpell',
equipment: 'DS4.ItemTypeEquipment',
loot: 'DS4.ItemTypeLoot',
talent: 'DS4.ItemTypeTalent',
racialAbility: 'DS4.ItemTypeRacialAbility',
language: 'DS4.ItemTypeLanguage',
alphabet: 'DS4.ItemTypeAlphabet',
specialCreatureAbility: 'DS4.ItemTypeSpecialCreatureAbility',
},
/**
* Define the set of armor types, a character may only wear one item of each at any given time
*/
armorTypes: {
body: "DS4.ArmorTypeBody",
helmet: "DS4.ArmorTypeHelmet",
vambrace: "DS4.ArmorTypeVambrace",
greaves: "DS4.ArmorTypeGreaves",
vambraceGreaves: "DS4.ArmorTypeVambraceGreaves",
body: 'DS4.ArmorTypeBody',
helmet: 'DS4.ArmorTypeHelmet',
vambrace: 'DS4.ArmorTypeVambrace',
greaves: 'DS4.ArmorTypeGreaves',
vambraceGreaves: 'DS4.ArmorTypeVambraceGreaves',
},
/**
* Define abbreviations for the armor types
*/
armorTypesAbbr: {
body: "DS4.ArmorTypeBodyAbbr",
helmet: "DS4.ArmorTypeHelmetAbbr",
vambrace: "DS4.ArmorTypeVambraceAbbr",
greaves: "DS4.ArmorTypeGreavesAbbr",
vambraceGreaves: "DS4.ArmorTypeVambraceGreavesAbbr",
body: 'DS4.ArmorTypeBodyAbbr',
helmet: 'DS4.ArmorTypeHelmetAbbr',
vambrace: 'DS4.ArmorTypeVambraceAbbr',
greaves: 'DS4.ArmorTypeGreavesAbbr',
vambraceGreaves: 'DS4.ArmorTypeVambraceGreavesAbbr',
},
/**
* Define the set of armor materials, used to determine if a character may wear the armor without additional penalties
*/
armorMaterialTypes: {
cloth: "DS4.ArmorMaterialTypeCloth",
leather: "DS4.ArmorMaterialTypeLeather",
chain: "DS4.ArmorMaterialTypeChain",
plate: "DS4.ArmorMaterialTypePlate",
natural: "DS4.ArmorMaterialTypeNatural",
cloth: 'DS4.ArmorMaterialTypeCloth',
leather: 'DS4.ArmorMaterialTypeLeather',
chain: 'DS4.ArmorMaterialTypeChain',
plate: 'DS4.ArmorMaterialTypePlate',
natural: 'DS4.ArmorMaterialTypeNatural',
},
/**
* Define the abbreviations of armor materials
*/
armorMaterialTypesAbbr: {
cloth: "DS4.ArmorMaterialTypeClothAbbr",
leather: "DS4.ArmorMaterialTypeLeatherAbbr",
chain: "DS4.ArmorMaterialTypeChainAbbr",
plate: "DS4.ArmorMaterialTypePlateAbbr",
natural: "DS4.ArmorMaterialTypeNaturalAbbr",
cloth: 'DS4.ArmorMaterialTypeClothAbbr',
leather: 'DS4.ArmorMaterialTypeLeatherAbbr',
chain: 'DS4.ArmorMaterialTypeChainAbbr',
plate: 'DS4.ArmorMaterialTypePlateAbbr',
natural: 'DS4.ArmorMaterialTypeNaturalAbbr',
},
spellTypes: {
spellcasting: "DS4.SpellTypeSpellcasting",
targetedSpellcasting: "DS4.SpellTypeTargetedSpellcasting",
spellcasting: 'DS4.SpellTypeSpellcasting',
targetedSpellcasting: 'DS4.SpellTypeTargetedSpellcasting',
},
spellGroups: {
lightning: "DS4.SpellGroupLightning",
earth: "DS4.SpellGroupEarth",
water: "DS4.SpellGroupWater",
ice: "DS4.SpellGroupIce",
fire: "DS4.SpellGroupFire",
healing: "DS4.SpellGroupHealing",
light: "DS4.SpellGroupLight",
air: "DS4.SpellGroupAir",
transport: "DS4.SpellGroupTransport",
damage: "DS4.SpellGroupDamage",
shadow: "DS4.SpellGroupShadow",
protection: "DS4.SpellGroupProtection",
mindAffecting: "DS4.SpellGroupMindAffecting",
demonology: "DS4.SpellGroupDemonology",
necromancy: "DS4.SpellGroupNecromancy",
transmutation: "DS4.SpellGroupTransmutation",
area: "DS4.SpellGroupArea",
lightning: 'DS4.SpellGroupLightning',
earth: 'DS4.SpellGroupEarth',
water: 'DS4.SpellGroupWater',
ice: 'DS4.SpellGroupIce',
fire: 'DS4.SpellGroupFire',
healing: 'DS4.SpellGroupHealing',
light: 'DS4.SpellGroupLight',
air: 'DS4.SpellGroupAir',
transport: 'DS4.SpellGroupTransport',
damage: 'DS4.SpellGroupDamage',
shadow: 'DS4.SpellGroupShadow',
protection: 'DS4.SpellGroupProtection',
mindAffecting: 'DS4.SpellGroupMindAffecting',
demonology: 'DS4.SpellGroupDemonology',
necromancy: 'DS4.SpellGroupNecromancy',
transmutation: 'DS4.SpellGroupTransmutation',
area: 'DS4.SpellGroupArea',
},
cooldownDurations: {
"0r": "DS4.CooldownDuration0R",
"1r": "DS4.CooldownDuration1R",
"2r": "DS4.CooldownDuration2R",
"5r": "DS4.CooldownDuration5R",
"10r": "DS4.CooldownDuration10R",
"100r": "DS4.CooldownDuration100R",
"1d": "DS4.CooldownDuration1D",
d20d: "DS4.CooldownDurationD20D",
'0r': 'DS4.CooldownDuration0R',
'1r': 'DS4.CooldownDuration1R',
'2r': 'DS4.CooldownDuration2R',
'5r': 'DS4.CooldownDuration5R',
'10r': 'DS4.CooldownDuration10R',
'100r': 'DS4.CooldownDuration100R',
'1d': 'DS4.CooldownDuration1D',
d20d: 'DS4.CooldownDurationD20D',
},
/**
* Define the set of actor types
*/
actorTypes: {
character: "DS4.ActorTypeCharacter",
creature: "DS4.ActorTypeCreature",
character: 'DS4.ActorTypeCharacter',
creature: 'DS4.ActorTypeCreature',
},
/**
* Define the set of attributes an actor has
*/
attributes: {
body: "DS4.AttributeBody",
mobility: "DS4.AttributeMobility",
mind: "DS4.AttributeMind",
body: 'DS4.AttributeBody',
mobility: 'DS4.AttributeMobility',
mind: 'DS4.AttributeMind',
},
/**
* Define the set of traits an actor has
*/
traits: {
strength: "DS4.TraitStrength",
agility: "DS4.TraitAgility",
intellect: "DS4.TraitIntellect",
constitution: "DS4.TraitConstitution",
dexterity: "DS4.TraitDexterity",
aura: "DS4.TraitAura",
strength: 'DS4.TraitStrength',
agility: 'DS4.TraitAgility',
intellect: 'DS4.TraitIntellect',
constitution: 'DS4.TraitConstitution',
dexterity: 'DS4.TraitDexterity',
aura: 'DS4.TraitAura',
},
/**
* Define the set of combat values an actor has
*/
combatValues: {
hitPoints: "DS4.CombatValuesHitPoints",
defense: "DS4.CombatValuesDefense",
initiative: "DS4.CombatValuesInitiative",
movement: "DS4.CombatValuesMovement",
meleeAttack: "DS4.CombatValuesMeleeAttack",
rangedAttack: "DS4.CombatValuesRangedAttack",
spellcasting: "DS4.CombatValuesSpellcasting",
targetedSpellcasting: "DS4.CombatValuesTargetedSpellcasting",
hitPoints: 'DS4.CombatValuesHitPoints',
defense: 'DS4.CombatValuesDefense',
initiative: 'DS4.CombatValuesInitiative',
movement: 'DS4.CombatValuesMovement',
meleeAttack: 'DS4.CombatValuesMeleeAttack',
rangedAttack: 'DS4.CombatValuesRangedAttack',
spellcasting: 'DS4.CombatValuesSpellcasting',
targetedSpellcasting: 'DS4.CombatValuesTargetedSpellcasting',
},
/**
* The what do display in the actor sheets for the combat value text (in some languages, abbreviations are necessary)
*/
combatValuesSheet: {
hitPoints: "DS4.CombatValuesHitPointsSheet",
defense: "DS4.CombatValuesDefenseSheet",
initiative: "DS4.CombatValuesInitiativeSheet",
movement: "DS4.CombatValuesMovementSheet",
meleeAttack: "DS4.CombatValuesMeleeAttackSheet",
rangedAttack: "DS4.CombatValuesRangedAttackSheet",
spellcasting: "DS4.CombatValuesSpellcastingSheet",
targetedSpellcasting: "DS4.CombatValuesTargetedSpellcastingSheet",
hitPoints: 'DS4.CombatValuesHitPointsSheet',
defense: 'DS4.CombatValuesDefenseSheet',
initiative: 'DS4.CombatValuesInitiativeSheet',
movement: 'DS4.CombatValuesMovementSheet',
meleeAttack: 'DS4.CombatValuesMeleeAttackSheet',
rangedAttack: 'DS4.CombatValuesRangedAttackSheet',
spellcasting: 'DS4.CombatValuesSpellcastingSheet',
targetedSpellcasting: 'DS4.CombatValuesTargetedSpellcastingSheet',
},
/**
* Define the base info of a character
*/
characterBaseInfo: {
race: "DS4.CharacterBaseInfoRace",
class: "DS4.CharacterBaseInfoClass",
heroClass: "DS4.CharacterBaseInfoHeroClass",
culture: "DS4.CharacterBaseInfoCulture",
race: 'DS4.CharacterBaseInfoRace',
class: 'DS4.CharacterBaseInfoClass',
heroClass: 'DS4.CharacterBaseInfoHeroClass',
culture: 'DS4.CharacterBaseInfoCulture',
},
/**
* Define the progression info of a character
*/
characterProgression: {
level: "DS4.CharacterProgressionLevel",
experiencePoints: "DS4.CharacterProgressionExperiencePoints",
talentPoints: "DS4.CharacterProgressionTalentPoints",
progressPoints: "DS4.CharacterProgressionProgressPoints",
level: 'DS4.CharacterProgressionLevel',
experiencePoints: 'DS4.CharacterProgressionExperiencePoints',
talentPoints: 'DS4.CharacterProgressionTalentPoints',
progressPoints: 'DS4.CharacterProgressionProgressPoints',
},
/**
* Define the language info of a character
*/
characterLanguage: {
languages: "DS4.CharacterLanguageLanguages",
alphabets: "DS4.CharacterLanguageAlphabets",
languages: 'DS4.CharacterLanguageLanguages',
alphabets: 'DS4.CharacterLanguageAlphabets',
},
/**
* Define the profile info of a character
*/
characterProfile: {
biography: "DS4.CharacterProfileBiography",
gender: "DS4.CharacterProfileGender",
birthday: "DS4.CharacterProfileBirthday",
birthplace: "DS4.CharacterProfileBirthplace",
age: "DS4.CharacterProfileAge",
height: "DS4.CharacterProfileHeight",
hairColor: "DS4.CharacterProfileHairColor",
weight: "DS4.CharacterProfileWeight",
eyeColor: "DS4.CharacterProfileEyeColor",
specialCharacteristics: "DS4.CharacterProfileSpecialCharacteristics",
biography: 'DS4.CharacterProfileBiography',
gender: 'DS4.CharacterProfileGender',
birthday: 'DS4.CharacterProfileBirthday',
birthplace: 'DS4.CharacterProfileBirthplace',
age: 'DS4.CharacterProfileAge',
height: 'DS4.CharacterProfileHeight',
hairColor: 'DS4.CharacterProfileHairColor',
weight: 'DS4.CharacterProfileWeight',
eyeColor: 'DS4.CharacterProfileEyeColor',
specialCharacteristics: 'DS4.CharacterProfileSpecialCharacteristics',
},
/**
* Define currency elements of a character
*/
characterCurrency: {
gold: "DS4.CharacterCurrencyGold",
silver: "DS4.CharacterCurrencySilver",
copper: "DS4.CharacterCurrencyCopper",
gold: 'DS4.CharacterCurrencyGold',
silver: 'DS4.CharacterCurrencySilver',
copper: 'DS4.CharacterCurrencyCopper',
},
/**
* Define the different creature types a creature can be
*/
creatureTypes: {
animal: "DS4.CreatureTypeAnimal",
construct: "DS4.CreatureTypeConstruct",
humanoid: "DS4.CreatureTypeHumanoid",
magicalEntity: "DS4.CreatureTypeMagicalEntity",
plantBeing: "DS4.CreatureTypePlantBeing",
undead: "DS4.CreatureTypeUndead",
animal: 'DS4.CreatureTypeAnimal',
construct: 'DS4.CreatureTypeConstruct',
humanoid: 'DS4.CreatureTypeHumanoid',
magicalEntity: 'DS4.CreatureTypeMagicalEntity',
plantBeing: 'DS4.CreatureTypePlantBeing',
undead: 'DS4.CreatureTypeUndead',
},
/**
* Define the different size categories creatures fall into
*/
creatureSizeCategories: {
tiny: "DS4.CreatureSizeCategoryTiny",
small: "DS4.CreatureSizeCategorySmall",
normal: "DS4.CreatureSizeCategoryNormal",
large: "DS4.CreatureSizeCategoryLarge",
huge: "DS4.CreatureSizeCategoryHuge",
colossal: "DS4.CreatureSizeCategoryColossal",
tiny: 'DS4.CreatureSizeCategoryTiny',
small: 'DS4.CreatureSizeCategorySmall',
normal: 'DS4.CreatureSizeCategoryNormal',
large: 'DS4.CreatureSizeCategoryLarge',
huge: 'DS4.CreatureSizeCategoryHuge',
colossal: 'DS4.CreatureSizeCategoryColossal',
},
/**
* Define the base info of a creature
*/
creatureBaseInfo: {
loot: "DS4.CreatureBaseInfoLoot",
foeFactor: "DS4.CreatureBaseInfoFoeFactor",
creatureType: "DS4.CreatureBaseInfoCreatureType",
sizeCategory: "DS4.CreatureBaseInfoSizeCategory",
experiencePoints: "DS4.CreatureBaseInfoExperiencePoints",
description: "DS4.CreatureBaseInfoDescription",
loot: 'DS4.CreatureBaseInfoLoot',
foeFactor: 'DS4.CreatureBaseInfoFoeFactor',
creatureType: 'DS4.CreatureBaseInfoCreatureType',
sizeCategory: 'DS4.CreatureBaseInfoSizeCategory',
experiencePoints: 'DS4.CreatureBaseInfoExperiencePoints',
description: 'DS4.CreatureBaseInfoDescription',
},
/**
* Define translations for available distance units
*/
distanceUnits: {
meter: "DS4.UnitMeters",
kilometer: "DS4.UnitKilometers",
custom: "DS4.UnitCustom",
meter: 'DS4.UnitMeters',
kilometer: 'DS4.UnitKilometers',
custom: 'DS4.UnitCustom',
},
/**
* Define abbreviations for available distance units
*/
distanceUnitsAbbr: {
meter: "DS4.UnitMetersAbbr",
kilometer: "DS4.UnitKilometersAbbr",
custom: "DS4.UnitCustomAbbr",
meter: 'DS4.UnitMetersAbbr',
kilometer: 'DS4.UnitKilometersAbbr',
custom: 'DS4.UnitCustomAbbr',
},
/**
* Define translations for available duration units
*/
temporalUnits: {
rounds: "DS4.UnitRounds",
minutes: "DS4.UnitMinutes",
hours: "DS4.UnitHours",
days: "DS4.UnitDays",
custom: "DS4.UnitCustom",
rounds: 'DS4.UnitRounds',
minutes: 'DS4.UnitMinutes',
hours: 'DS4.UnitHours',
days: 'DS4.UnitDays',
custom: 'DS4.UnitCustom',
},
/**
* Define abbreviations for available duration units
*/
temporalUnitsAbbr: {
rounds: "DS4.UnitRoundsAbbr",
minutes: "DS4.UnitMinutesAbbr",
hours: "DS4.UnitHoursAbbr",
days: "DS4.UnitDaysAbbr",
custom: "DS4.UnitCustomAbbr",
rounds: 'DS4.UnitRoundsAbbr',
minutes: 'DS4.UnitMinutesAbbr',
hours: 'DS4.UnitHoursAbbr',
days: 'DS4.UnitDaysAbbr',
custom: 'DS4.UnitCustomAbbr',
},
checks: {
appraise: "DS4.ChecksAppraise",
changeSpell: "DS4.ChecksChangeSpell",
climb: "DS4.ChecksClimb",
communicate: "DS4.ChecksCommunicate",
decipherScript: "DS4.ChecksDecipherScript",
defend: "DS4.ChecksDefend",
defyPoison: "DS4.ChecksDefyPoison",
disableTraps: "DS4.ChecksDisableTraps",
featOfStrength: "DS4.ChecksFeatOfStrength",
flirt: "DS4.ChecksFlirt",
haggle: "DS4.ChecksHaggle",
hide: "DS4.ChecksHide",
identifyMagic: "DS4.ChecksIdentifyMagic",
jump: "DS4.ChecksJump",
knowledge: "DS4.ChecksKnowledge",
openLock: "DS4.ChecksOpenLock",
perception: "DS4.ChecksPerception",
pickPocket: "DS4.ChecksPickPocket",
readTracks: "DS4.ChecksReadTracks",
resistDisease: "DS4.ChecksResistDisease",
ride: "DS4.ChecksRide",
search: "DS4.ChecksSearch",
senseMagic: "DS4.ChecksSenseMagic",
sneak: "DS4.ChecksSneak",
startFire: "DS4.ChecksStartFire",
swim: "DS4.ChecksSwim",
wakeUp: "DS4.ChecksWakeUp",
workMechanism: "DS4.ChecksWorkMechanism",
appraise: 'DS4.ChecksAppraise',
changeSpell: 'DS4.ChecksChangeSpell',
climb: 'DS4.ChecksClimb',
communicate: 'DS4.ChecksCommunicate',
decipherScript: 'DS4.ChecksDecipherScript',
defend: 'DS4.ChecksDefend',
defyPoison: 'DS4.ChecksDefyPoison',
disableTraps: 'DS4.ChecksDisableTraps',
featOfStrength: 'DS4.ChecksFeatOfStrength',
flirt: 'DS4.ChecksFlirt',
haggle: 'DS4.ChecksHaggle',
hide: 'DS4.ChecksHide',
identifyMagic: 'DS4.ChecksIdentifyMagic',
jump: 'DS4.ChecksJump',
knowledge: 'DS4.ChecksKnowledge',
openLock: 'DS4.ChecksOpenLock',
perception: 'DS4.ChecksPerception',
pickPocket: 'DS4.ChecksPickPocket',
readTracks: 'DS4.ChecksReadTracks',
resistDisease: 'DS4.ChecksResistDisease',
ride: 'DS4.ChecksRide',
search: 'DS4.ChecksSearch',
senseMagic: 'DS4.ChecksSenseMagic',
sneak: 'DS4.ChecksSneak',
startFire: 'DS4.ChecksStartFire',
swim: 'DS4.ChecksSwim',
wakeUp: 'DS4.ChecksWakeUp',
workMechanism: 'DS4.ChecksWorkMechanism',
},
/**
* Translations for the standard check modifiers
*/
checkModifiers: {
routine: "DS4.CheckModifierRoutine",
veryEasy: "DS4.CheckModifierVeryEasy",
easy: "DS4.CheckModifierEasy",
normal: "DS4.CheckModifierMormal",
difficult: "DS4.CheckModifierDifficult",
veryDifficult: "DS4.CheckModifierVeryDifficult",
extremelyDifficult: "DS4.CheckModifierExtremelyDifficult",
custom: "DS4.CheckModifierCustom",
routine: 'DS4.CheckModifierRoutine',
veryEasy: 'DS4.CheckModifierVeryEasy',
easy: 'DS4.CheckModifierEasy',
normal: 'DS4.CheckModifierMormal',
difficult: 'DS4.CheckModifierDifficult',
veryDifficult: 'DS4.CheckModifierVeryDifficult',
extremelyDifficult: 'DS4.CheckModifierExtremelyDifficult',
custom: 'DS4.CheckModifierCustom',
},
};
@ -385,51 +385,51 @@ export const DS4 = {
* Define the file paths to icon images
*/
attackTypes: {
melee: "systems/ds4/assets/icons/official/combat-values/melee-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",
melee: 'systems/ds4/assets/icons/official/combat-values/melee-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',
},
/**
* Define the file paths to icon images
*/
spellTypes: {
spellcasting: "systems/ds4/assets/icons/official/combat-values/spellcasting.png",
targetedSpellcasting: "systems/ds4/assets/icons/official/combat-values/targeted-spellcasting.png",
spellcasting: 'systems/ds4/assets/icons/official/combat-values/spellcasting.png',
targetedSpellcasting: 'systems/ds4/assets/icons/official/combat-values/targeted-spellcasting.png',
},
/**
* Define the file paths to check images
*/
checks: {
appraise: "systems/ds4/assets/icons/game-icons/delapouite/two-coins.svg",
changeSpell: "systems/ds4/assets/icons/game-icons/delapouite/card-exchange.svg",
climb: "systems/ds4/assets/icons/game-icons/caro-asercion/mountain-climbing.svg",
communicate: "systems/ds4/assets/icons/game-icons/delapouite/discussion.svg",
decipherScript: "systems/ds4/assets/icons/game-icons/lorc/rune-stone.svg",
defend: "systems/ds4/assets/icons/game-icons/sbed/shield.svg",
defyPoison: "systems/ds4/assets/icons/game-icons/lorc/poison-bottle.svg",
disableTraps: "systems/ds4/assets/icons/game-icons/lorc/wolf-trap.svg",
featOfStrength: "systems/ds4/assets/icons/game-icons/delapouite/biceps.svg",
flirt: "systems/ds4/assets/icons/game-icons/lorc/charm.svg",
haggle: "systems/ds4/assets/icons/game-icons/lorc/cash.svg",
hide: "systems/ds4/assets/icons/game-icons/lorc/hidden.svg",
identifyMagic: "systems/ds4/assets/icons/game-icons/lorc/uncertainty.svg",
jump: "systems/ds4/assets/icons/game-icons/delapouite/jump-across.svg",
knowledge: "systems/ds4/assets/icons/game-icons/delapouite/bookshelf.svg",
openLock: "systems/ds4/assets/icons/game-icons/delapouite/padlock-open.svg",
perception: "systems/ds4/assets/icons/game-icons/lorc/awareness.svg",
pickPocket: "systems/ds4/assets/icons/game-icons/darkzaitev/robber-hand.svg",
readTracks: "systems/ds4/assets/icons/game-icons/delapouite/deer-track.svg",
resistDisease: "systems/ds4/assets/icons/game-icons/lorc/virus.svg",
ride: "systems/ds4/assets/icons/game-icons/delapouite/cavalry.svg",
search: "systems/ds4/assets/icons/game-icons/lorc/magnifying-glass.svg",
senseMagic: "systems/ds4/assets/icons/game-icons/delapouite/sparkles.svg",
sneak: "systems/ds4/assets/icons/game-icons/delapouite/mute.svg",
startFire: "systems/ds4/assets/icons/game-icons/lorc/campfire.svg",
swim: "systems/ds4/assets/icons/game-icons/delapouite/pool-dive.svg",
wakeUp: "systems/ds4/assets/icons/game-icons/delapouite/alarm-clock.svg",
workMechanism: "systems/ds4/assets/icons/game-icons/lorc/lever.svg",
appraise: 'systems/ds4/assets/icons/game-icons/delapouite/two-coins.svg',
changeSpell: 'systems/ds4/assets/icons/game-icons/delapouite/card-exchange.svg',
climb: 'systems/ds4/assets/icons/game-icons/caro-asercion/mountain-climbing.svg',
communicate: 'systems/ds4/assets/icons/game-icons/delapouite/discussion.svg',
decipherScript: 'systems/ds4/assets/icons/game-icons/lorc/rune-stone.svg',
defend: 'systems/ds4/assets/icons/game-icons/sbed/shield.svg',
defyPoison: 'systems/ds4/assets/icons/game-icons/lorc/poison-bottle.svg',
disableTraps: 'systems/ds4/assets/icons/game-icons/lorc/wolf-trap.svg',
featOfStrength: 'systems/ds4/assets/icons/game-icons/delapouite/biceps.svg',
flirt: 'systems/ds4/assets/icons/game-icons/lorc/charm.svg',
haggle: 'systems/ds4/assets/icons/game-icons/lorc/cash.svg',
hide: 'systems/ds4/assets/icons/game-icons/lorc/hidden.svg',
identifyMagic: 'systems/ds4/assets/icons/game-icons/lorc/uncertainty.svg',
jump: 'systems/ds4/assets/icons/game-icons/delapouite/jump-across.svg',
knowledge: 'systems/ds4/assets/icons/game-icons/delapouite/bookshelf.svg',
openLock: 'systems/ds4/assets/icons/game-icons/delapouite/padlock-open.svg',
perception: 'systems/ds4/assets/icons/game-icons/lorc/awareness.svg',
pickPocket: 'systems/ds4/assets/icons/game-icons/darkzaitev/robber-hand.svg',
readTracks: 'systems/ds4/assets/icons/game-icons/delapouite/deer-track.svg',
resistDisease: 'systems/ds4/assets/icons/game-icons/lorc/virus.svg',
ride: 'systems/ds4/assets/icons/game-icons/delapouite/cavalry.svg',
search: 'systems/ds4/assets/icons/game-icons/lorc/magnifying-glass.svg',
senseMagic: 'systems/ds4/assets/icons/game-icons/delapouite/sparkles.svg',
sneak: 'systems/ds4/assets/icons/game-icons/delapouite/mute.svg',
startFire: 'systems/ds4/assets/icons/game-icons/lorc/campfire.svg',
swim: 'systems/ds4/assets/icons/game-icons/delapouite/pool-dive.svg',
wakeUp: 'systems/ds4/assets/icons/game-icons/delapouite/alarm-clock.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
*/
characterProfileDTypes: {
biography: "String",
gender: "String",
birthday: "String",
birthplace: "String",
age: "Number",
height: "Number",
hairColor: "String",
weight: "Number",
eyeColor: "String",
specialCharacteristics: "String",
biography: 'String',
gender: 'String',
birthday: 'String',
birthplace: 'String',
age: 'Number',
height: 'Number',
hairColor: 'String',
weight: 'Number',
eyeColor: 'String',
specialCharacteristics: 'String',
},
/**

View file

@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { getGame } from '../utils/utils';
export function evaluateCheck(
dice: number[],
@ -41,7 +41,7 @@ function assignSubChecksToDice(
const requiredNumberOfDice = getRequiredNumberOfDice(checkTargetNumber);
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);
@ -68,8 +68,7 @@ function findIndexOfSmallestNonCoup(dice: number[], maximumCoupResult: number):
.map((die, index): [number, number] => [die, index])
.filter((indexedDie) => indexedDie[0] > maximumCoupResult)
.reduce(
(smallestIndexedDie, indexedDie) =>
indexedDie[0] < smallestIndexedDie[0] ? indexedDie : smallestIndexedDie,
(smallestIndexedDie, indexedDie) => (indexedDie[0] < smallestIndexedDie[0] ? indexedDie : smallestIndexedDie),
[Infinity, -1],
)[1];
}
@ -90,7 +89,7 @@ function shouldUseCoupForLastSubCheck(
!Number.isInteger(indexOfSmallestNonCoup) ||
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 (
indexOfFirstCoup !== -1 &&

View file

@ -3,9 +3,9 @@
//
// SPDX-License-Identifier: MIT
import { DialogWithListeners } from "../apps/dialog-with-listeners";
import { DS4 } from "../config";
import { getGame } from "../utils/utils";
import { DialogWithListeners } from '../apps/dialog-with-listeners';
import { DS4 } from '../config';
import { getGame } from '../utils/utils';
/** @typedef {"publicroll" | "gmroll" | "gmroll" | "selfroll"} RollModes */
@ -51,7 +51,7 @@ class CheckFactory {
maximumCoupResult: 1,
minimumFumbleResult: 20,
useSlayingDice: false,
rollMode: "publicroll",
rollMode: 'publicroll',
};
}
@ -59,9 +59,7 @@ class CheckFactory {
* Execute this check factory.
* @returns {Promise<ChatMessage | undefined>} A promise that resolves to the created chat message for the roll */
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 roll = Roll.create(formula);
const speaker = this.#options.speaker ?? ChatMessage.getSpeaker();
@ -82,7 +80,7 @@ class CheckFactory {
*/
createCheckTargetNumberModifier() {
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;
if (isMinimumFumbleResultRequired || isMaximumCoupResultRequired) {
return `c${this.#options.maximumCoupResult ?? ""}:${this.#options.minimumFumbleResult ?? ""}`;
return `c${this.#options.maximumCoupResult ?? ''}:${this.#options.minimumFumbleResult ?? ''}`;
} else {
return null;
}
@ -119,7 +117,7 @@ export async function createCheckRoll(checkTargetNumber, options = {}) {
const newOptions = {
maximumCoupResult: interactiveRollData.maximumCoupResult ?? options.maximumCoupResult,
minimumFumbleResult: interactiveRollData.minimumFumbleResult ?? options.minimumFumbleResult,
useSlayingDice: getGame().settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
useSlayingDice: getGame().settings.get('ds4', 'useSlayingDiceForAutomatedChecks'),
rollMode: interactiveRollData.rollMode ?? options.rollMode,
flavor: options.flavor,
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.
*/
async function askForInteractiveRollData(checkTargetNumber, options = {}, { template, title } = {}) {
const usedTemplate = template ?? "systems/ds4/templates/dialogs/roll-options.hbs";
const usedTitle = title ?? getGame().i18n.localize("DS4.DialogRollOptionsDefaultTitle");
const usedTemplate = template ?? 'systems/ds4/templates/dialogs/roll-options.hbs';
const usedTitle = title ?? getGame().i18n.localize('DS4.DialogRollOptionsDefaultTitle');
const id = foundry.utils.randomID();
const templateData = {
title: usedTitle,
checkTargetNumber: checkTargetNumber,
maximumCoupResult: options.maximumCoupResult ?? this.constructor.defaultOptions.maximumCoupResult,
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,
checkModifiers: Object.entries(DS4.i18n.checkModifiers).map(([key, translation]) => {
if (key in DS4.checkModifiers) {
@ -178,21 +176,21 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
buttons: {
ok: {
icon: '<i class="fas fa-check"></i>',
label: getGame().i18n.localize("DS4.GenericOkButton"),
label: getGame().i18n.localize('DS4.GenericOkButton'),
callback: (html) => {
if (!("jquery" in html)) {
if (!('jquery' in html)) {
throw new Error(
getGame().i18n.format("DS4.ErrorUnexpectedHtmlType", {
exType: "JQuery",
realType: "HTMLElement",
getGame().i18n.format('DS4.ErrorUnexpectedHtmlType', {
exType: 'JQuery',
realType: 'HTMLElement',
}),
);
} else {
const innerForm = html[0]?.querySelector("form");
const innerForm = html[0]?.querySelector('form');
if (!innerForm) {
throw new Error(
getGame().i18n.format("DS4.ErrorCouldNotFindHtmlElement", {
htmlElement: "form",
getGame().i18n.format('DS4.ErrorCouldNotFindHtmlElement', {
htmlElement: 'form',
}),
);
}
@ -202,26 +200,21 @@ async function askForInteractiveRollData(checkTargetNumber, options = {}, { temp
},
cancel: {
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) => {
const checkModifierCustomFormGroup = html
.find(`#check-modifier-custom-${id}`)
.parent(".form-group");
html.find(`#check-modifier-${id}`).on("change", (event) => {
if (
event.currentTarget.value === "custom" &&
checkModifierCustomFormGroup.hasClass("ds4-hidden")
) {
checkModifierCustomFormGroup.removeClass("ds4-hidden");
app.setPosition({ height: "auto" });
} else if (!checkModifierCustomFormGroup.hasClass("ds4-hidden")) {
checkModifierCustomFormGroup.addClass("ds4-hidden");
app.setPosition({ height: "auto" });
const checkModifierCustomFormGroup = html.find(`#check-modifier-custom-${id}`).parent('.form-group');
html.find(`#check-modifier-${id}`).on('change', (event) => {
if (event.currentTarget.value === 'custom' && checkModifierCustomFormGroup.hasClass('ds4-hidden')) {
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>}
*/
function parseDialogFormData(formData) {
const chosenCheckTargetNumber = parseInt(formData["check-target-number"]?.value);
const chosenCheckModifier = formData["check-modifier"]?.value;
const chosenCheckTargetNumber = parseInt(formData['check-target-number']?.value);
const chosenCheckModifier = formData['check-modifier']?.value;
const chosenCheckModifierValue =
chosenCheckModifier === "custom"
? parseInt(formData["check-modifier-custom"]?.value)
chosenCheckModifier === 'custom'
? parseInt(formData['check-modifier-custom']?.value)
: parseInt(chosenCheckModifier);
const chosenMaximumCoupResult = parseInt(formData["maximum-coup-result"]?.value);
const chosenMinimumFumbleResult = parseInt(formData["minimum-fumble-result"]?.value);
const chosenRollMode = formData["roll-mode"]?.value;
const chosenMaximumCoupResult = parseInt(formData['maximum-coup-result']?.value);
const chosenMinimumFumbleResult = parseInt(formData['minimum-fumble-result']?.value);
const chosenRollMode = formData['roll-mode']?.value;
return {
checkTargetNumber: Number.isSafeInteger(chosenCheckTargetNumber) ? chosenCheckTargetNumber : undefined,

View file

@ -3,8 +3,8 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { evaluateCheck, getRequiredNumberOfDice } from "./check-evaluation";
import { getGame } from '../utils/utils';
import { evaluateCheck, getRequiredNumberOfDice } from './check-evaluation';
/**
* Implements DS4 Checks as an emulated "dice throw".
@ -25,8 +25,8 @@ export class DS4Check extends DiceTerm {
});
// Parse and store check target number
const checkTargetNumberModifier = this.modifiers.filter((m) => m[0] === "v")[0];
const ctnRgx = new RegExp("v([0-9]+)?");
const checkTargetNumberModifier = this.modifiers.filter((m) => m[0] === 'v')[0];
const ctnRgx = new RegExp('v([0-9]+)?');
const ctnMatch = checkTargetNumberModifier?.match(ctnRgx);
if (ctnMatch) {
const [parseCheckTargetNumber] = ctnMatch.slice(1);
@ -38,8 +38,8 @@ export class DS4Check extends DiceTerm {
this.number = getRequiredNumberOfDice(this.checkTargetNumber);
// Parse and store maximumCoupResult and minimumFumbleResult
const coupFumbleModifier = this.modifiers.filter((m) => m[0] === "c")[0];
const cfmRgx = new RegExp("c([0-9]+)?(:([0-9]+))?");
const coupFumbleModifier = this.modifiers.filter((m) => m[0] === 'c')[0];
const cfmRgx = new RegExp('c([0-9]+)?(:([0-9]+))?');
const cfmMatch = coupFumbleModifier?.match(cfmRgx);
if (cfmMatch) {
const parseMaximumCoupResult = cfmMatch[1];
@ -51,11 +51,11 @@ export class DS4Check extends DiceTerm {
? parseInt(parseMinimumFumbleResult)
: DS4Check.DEFAULT_MINIMUM_FUMBLE_RESULT;
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
const noFumbleModifier = this.modifiers.filter((m) => m[0] === "n")[0];
const noFumbleModifier = this.modifiers.filter((m) => m[0] === 'n')[0];
if (noFumbleModifier) {
this.canFumble = false;
}
@ -76,7 +76,7 @@ export class DS4Check extends DiceTerm {
/** @override */
get expression() {
return `ds${this.modifiers.join("")}`;
return `ds${this.modifiers.join('')}`;
}
/** @override */
@ -121,13 +121,13 @@ export class DS4Check extends DiceTerm {
* @override
*/
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_MAXIMUM_COUP_RESULT = 1;
static DEFAULT_MINIMUM_FUMBLE_RESULT = 20;
static DENOMINATION = "s";
static DENOMINATION = 's';
static MODIFIERS = {
c: () => undefined, // Modifier is consumed in constructor for maximumCoupResult / minimumFumbleResult
v: () => undefined, // Modifier is consumed in constructor for checkTargetNumber

View file

@ -2,12 +2,12 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { DS4Check } from "./check";
import { getGame } from '../utils/utils';
import { DS4Check } from './check';
export class DS4Roll extends Roll {
/** @override */
static CHAT_TEMPLATE = "systems/ds4/templates/dice/roll.hbs";
static CHAT_TEMPLATE = 'systems/ds4/templates/dice/roll.hbs';
/**
* @override
@ -21,11 +21,11 @@ export class DS4Roll extends Roll {
const isCoup = firstDiceTerm instanceof DS4Check && firstDiceTerm.coup;
const isFumble = firstDiceTerm instanceof DS4Check && firstDiceTerm.fumble;
const chatData = {
formula: isPrivate ? "???" : this._formula,
formula: isPrivate ? '???' : this._formula,
flavor: isPrivate ? null : flavor,
user: getGame().user?.id,
tooltip: isPrivate ? "" : await this.getTooltip(),
total: isPrivate ? "?" : Math.round((this.total ?? 0) * 100) / 100,
tooltip: isPrivate ? '' : await this.getTooltip(),
total: isPrivate ? '?' : Math.round((this.total ?? 0) * 100) / 100,
isCoup: isPrivate ? null : isCoup,
isFumble: isPrivate ? null : isFumble,
};

View file

@ -3,8 +3,8 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { DS4Check } from "./check";
import { getGame } from '../utils/utils';
import { DS4Check } from './check';
export function registerSlayingDiceModifier() {
PoolTerm.MODIFIERS.x = slay;
@ -31,6 +31,6 @@ function slay(modifier) {
this.results.push({ result: additionalRoll.total ?? 0, active: true });
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'));
}
}

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import { mathEvaluator } from "../expression-evaluation/evaluator";
import { getGame } from "../utils/utils";
import { mathEvaluator } from '../expression-evaluation/evaluator';
import { getGame } from '../utils/utils';
/**
* @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.
*/
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

View file

@ -5,9 +5,9 @@
//
// 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 {
attributes: DS4ActorDataPropertiesDataAttributes;
@ -25,7 +25,7 @@ type DS4ActorDataPropertiesDataAttributes = {
type DS4ActorDataPropertiesDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBaseTotal<number> };
type DS4ActorDataPropertiesDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
[Key in keyof typeof DS4.i18n.combatValues]: Key extends 'hitPoints'
? ResourceDataBaseTotalMax<number>
: ModifiableDataBaseTotal<number>;
};

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import type { DS4CharacterDataProperties } from "./character/character-data-properties";
import type { DS4CreatureDataProperties } from "./creature/creature-data-properties";
import type { DS4CharacterDataProperties } from './character/character-data-properties';
import type { DS4CreatureDataProperties } from './creature/creature-data-properties';
declare global {
interface DataConfig {

View file

@ -5,9 +5,9 @@
//
// 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 {
attributes: DS4ActorDataSourceDataAttributes;
@ -32,9 +32,7 @@ export function isTrait(value: unknown): value is Trait {
}
type DS4ActorDataSourceDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
? ResourceData<number>
: ModifiableData<number>;
[Key in keyof typeof DS4.i18n.combatValues]: Key extends 'hitPoints' ? ResourceData<number> : ModifiableData<number>;
};
type CombatValue = keyof DS4ActorDataSourceDataCombatValues;

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import type { DS4CharacterDataSource } from "./character/character-data-source";
import type { DS4CreatureDataSource } from "./creature/creature-data-source";
import type { DS4CharacterDataSource } from './character/character-data-source';
import type { DS4CreatureDataSource } from './creature/creature-data-source';
declare global {
interface SourceConfig {

View file

@ -3,13 +3,13 @@
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../../config";
import { createCheckRoll } from "../../dice/check-factory";
import { mathEvaluator } from "../../expression-evaluation/evaluator";
import { logger } from "../../utils/logger";
import { getGame } from "../../utils/utils";
import { DS4ActiveEffect } from "../active-effect";
import { isAttribute, isTrait } from "./actor-data-source-base";
import { DS4 } from '../../config';
import { createCheckRoll } from '../../dice/check-factory';
import { mathEvaluator } from '../../expression-evaluation/evaluator';
import { logger } from '../../utils/logger';
import { getGame } from '../../utils/utils';
import { DS4ActiveEffect } from '../active-effect';
import { isAttribute, isTrait } from './actor-data-source-base';
/**
* The Actor class for DS4
@ -39,9 +39,7 @@ export class DS4Actor extends Actor {
maximumCoupResult: 1,
};
Object.values(this.system.attributes).forEach(
(attribute) => (attribute.total = attribute.base + attribute.mod),
);
Object.values(this.system.attributes).forEach((attribute) => (attribute.total = attribute.base + attribute.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 { 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;
}
if (condition !== undefined && condition !== "") {
if (condition !== undefined && condition !== '') {
try {
const replacedCondition = DS4Actor.replaceFormulaData(condition, { item, actor: this, effect });
return replacedCondition !== undefined ? Boolean(mathEvaluator.evaluate(replacedCondition)) : false;
@ -158,7 +156,7 @@ export class DS4Actor extends Actor {
this.applyActiveEffectsToItem(item);
}
for (const item of this.items) {
if (item.type === "talent") continue;
if (item.type === 'talent') continue;
this.applyActiveEffectsToItem(item);
}
}
@ -184,8 +182,7 @@ export class DS4Actor extends Actor {
this,
this.actorEffects,
(change) =>
!this.derivedDataProperties.includes(change.key) &&
!this.finalDerivedDataProperties.includes(change.key),
!this.derivedDataProperties.includes(change.key) && !this.finalDerivedDataProperties.includes(change.key),
).forEach(this.newStatuses.add.bind(this.newStatuses));
}
@ -218,7 +215,7 @@ export class DS4Actor extends Actor {
(combatValue) => `system.combatValues.${combatValue}.total`,
);
const checkProperties = Object.keys(DS4.i18n.checks)
.filter((check) => check !== "defend")
.filter((check) => check !== 'defend')
.map((check) => `system.checks.${check}`);
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.traits).forEach((trait) => (trait.total = Math.ceil(trait.total)));
Object.entries(this.system.combatValues)
.filter(([key]) => key !== "movement")
.filter(([key]) => key !== 'movement')
.forEach(([, combatValue]) => (combatValue.total = Math.ceil(combatValue.total)));
Object.keys(this.system.checks).forEach((key) => {
this.system.checks[key] = Math.ceil(this.system.checks[key]);
@ -270,7 +267,7 @@ export class DS4Actor extends Actor {
* @type {string[]}
*/
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[]}
*/
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() {
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);
}
@ -340,7 +337,7 @@ export class DS4Actor extends Actor {
* @protected
*/
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,
featOfStrength: system.attributes.body.total + system.traits.strength.total,
flirt: system.attributes.mind.total + system.traits.aura.total,
haggle:
system.attributes.mind.total + Math.max(system.traits.intellect.total, system.traits.intellect.total),
haggle: system.attributes.mind.total + Math.max(system.traits.intellect.total, system.traits.intellect.total),
hide: system.attributes.mobility.total + system.traits.agility.total,
identifyMagic: system.attributes.mind.total + system.traits.intellect.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
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;
}
@ -421,10 +417,10 @@ export class DS4Actor extends Actor {
async rollCheck(check, options = {}) {
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
await createCheckRoll(this.system.checks[check], {
rollMode: getGame().settings.get("core", "rollMode"),
rollMode: getGame().settings.get('core', 'rollMode'),
maximumCoupResult: this.system.rolling.maximumCoupResult,
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
flavor: "DS4.ActorCheckFlavor",
flavor: 'DS4.ActorCheckFlavor',
flavorData: { actor: speaker.alias ?? this.name, check: DS4.i18nKeys.checks[check] },
speaker,
});
@ -445,10 +441,10 @@ export class DS4Actor extends Actor {
const checkTargetNumber = this.system.attributes[attribute].total + this.system.traits[trait].total;
const speaker = ChatMessage.getSpeaker({ actor: this, ...options.speaker });
await createCheckRoll(checkTargetNumber, {
rollMode: getGame().settings.get("core", "rollMode"),
rollMode: getGame().settings.get('core', 'rollMode'),
maximumCoupResult: this.system.rolling.maximumCoupResult,
minimumFumbleResult: this.system.rolling.minimumFumbleResult,
flavor: "DS4.ActorGenericCheckFlavor",
flavor: 'DS4.ActorGenericCheckFlavor',
flavorData: {
actor: speaker.alias ?? this.name,
attribute: DS4.i18n.attributes[attribute],
@ -464,14 +460,14 @@ export class DS4Actor extends Actor {
* @protected
*/
async selectAttributeAndTrait() {
const attributeIdentifier = "attribute-trait-selection-attribute";
const traitIdentifier = "attribute-trait-selection-trait";
const attributeIdentifier = 'attribute-trait-selection-attribute';
const traitIdentifier = 'attribute-trait-selection-trait';
return Dialog.prompt({
title: getGame().i18n.localize("DS4.DialogAttributeTraitSelection"),
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
title: getGame().i18n.localize('DS4.DialogAttributeTraitSelection'),
content: await renderTemplate('systems/ds4/templates/dialogs/simple-select-form.hbs', {
selects: [
{
label: getGame().i18n.localize("DS4.Attribute"),
label: getGame().i18n.localize('DS4.Attribute'),
identifier: attributeIdentifier,
options: Object.fromEntries(
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,
options: Object.fromEntries(
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) => {
const selectedAttribute = html.find(`#${attributeIdentifier}`).val();
if (!isAttribute(selectedAttribute)) {
throw new Error(
getGame().i18n.format("DS4.ErrorUnexpectedAttribute", {
getGame().i18n.format('DS4.ErrorUnexpectedAttribute', {
actualAttribute: selectedAttribute,
expectedTypes: Object.keys(DS4.i18n.attributes)
.map((attribute) => `'${attribute}'`)
.join(", "),
.join(', '),
}),
);
}
const selectedTrait = html.find(`#${traitIdentifier}`).val();
if (!isTrait(selectedTrait)) {
throw new Error(
getGame().i18n.format("DS4.ErrorUnexpectedTrait", {
getGame().i18n.format('DS4.ErrorUnexpectedTrait', {
actualTrait: selectedTrait,
expectedTypes: Object.keys(DS4.i18n.traits)
.map((attribute) => `'${attribute}'`)
.join(", "),
.join(', '),
}),
);
}

View file

@ -2,17 +2,17 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
import type { DS4ActorDataPropertiesDataBase } from '../actor-data-properties-base';
import type {
DS4CharacterDataSourceDataBaseInfo,
DS4CharacterDataSourceDataCurrency,
DS4CharacterDataSourceDataProfile,
DS4CharacterDataSourceDataProgression,
DS4CharacterDataSourceDataSlayerPoints,
} from "./character-data-source";
} from './character-data-source';
export interface DS4CharacterDataProperties {
type: "character";
type: 'character';
data: DS4CharacterDataPropertiesData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { UsableResource } from "../../common/common-data";
import type { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
import type { UsableResource } from '../../common/common-data';
import type { DS4ActorDataSourceDataBase } from '../actor-data-source-base';
export interface DS4CharacterDataSource {
type: "character";
type: 'character';
data: DS4CharacterDataSourceData;
}

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4Actor } from "../actor";
import { DS4Actor } from '../actor';
export class DS4Character extends DS4Actor {
/** @override */
@ -13,11 +13,11 @@ export class DS4Character extends DS4Actor {
/** @override */
get finalDerivedDataProperties() {
return [...super.finalDerivedDataProperties, "system.slayerPoints.max"];
return [...super.finalDerivedDataProperties, 'system.slayerPoints.max'];
}
/** @override */
get ownableItemTypes() {
return [...super.ownableItemTypes, "talent", "racialAbility", "language", "alphabet"];
return [...super.ownableItemTypes, 'talent', 'racialAbility', 'language', 'alphabet'];
}
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
import type { DS4CreatureDataSourceDataBaseInfo } from "./creature-data-source";
import type { DS4ActorDataPropertiesDataBase } from '../actor-data-properties-base';
import type { DS4CreatureDataSourceDataBaseInfo } from './creature-data-source';
export interface DS4CreatureDataProperties {
type: "creature";
type: 'creature';
data: DS4CreatureDataPropertiesData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../../config";
import type { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
import type { DS4 } from '../../../config';
import type { DS4ActorDataSourceDataBase } from '../actor-data-source-base';
export interface DS4CreatureDataSource {
type: "creature";
type: 'creature';
data: DS4CreatureDataSourceData;
}

View file

@ -2,12 +2,12 @@
//
// 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 {
override get ownableItemTypes(): Array<ItemType> {
return [...super.ownableItemTypes, "specialCreatureAbility"];
return [...super.ownableItemTypes, 'specialCreatureAbility'];
}
}

View file

@ -2,10 +2,10 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../../utils/utils";
import { DS4Actor } from "./actor";
import { DS4Character } from "./character/character";
import { DS4Creature } from "./creature/creature";
import { getGame } from '../../utils/utils';
import { DS4Actor } from './actor';
import { DS4Character } from './character/character';
import { DS4Creature } from './creature/creature';
const handler = {
/**
@ -14,12 +14,12 @@ const handler = {
*/
construct(_, args) {
switch (args[0]?.type) {
case "character":
case 'character':
return new DS4Character(...args);
case "creature":
case 'creature':
return new DS4Creature(...args);
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 }));
}
},
};

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { getGame } from '../utils/utils';
/**
* @typedef {object} DS4ChatMessageFlags
@ -22,7 +22,7 @@ export class DS4ChatMessage extends ChatMessage {
const flavorData = Object.fromEntries(
Object.entries(this.flags.ds4?.flavorData ?? {}).map(([key, value]) => [
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);

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4AlphabetDataSourceData } from "./alphabet-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4AlphabetDataSourceData } from './alphabet-data-source';
export interface DS4AlphabetDataProperties {
type: "alphabet";
type: 'alphabet';
data: DS4AlphabetDataPropertiesData;
}

View file

@ -2,10 +2,10 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
export interface DS4AlphabetDataSource {
type: "alphabet";
type: 'alphabet';
data: DS4AlphabetDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Alphabet extends DS4Item {}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4ArmorDataSourceData } from "./armor-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4ArmorDataSourceData } from './armor-data-source';
export interface DS4ArmorDataProperties {
type: "armor";
type: 'armor';
data: DS4ArmorDataPropertiesData;
}

View file

@ -2,16 +2,16 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../../config";
import type { DS4 } from '../../../config';
import type {
DS4ItemDataSourceDataBase,
DS4ItemDataSourceDataEquipable,
DS4ItemDataSourceDataPhysical,
DS4ItemDataSourceDataProtective,
} from "../item-data-source-base";
} from '../item-data-source-base';
export interface DS4ArmorDataSource {
type: "armor";
type: 'armor';
data: DS4ArmorDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Armor extends DS4Item {}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4EquipmentDataSourceData } from "./equipment-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4EquipmentDataSourceData } from './equipment-data-source';
export interface DS4EquipmentDataProperties {
type: "equipment";
type: 'equipment';
data: DS4EquipmentDataPropertiesData;
}

View file

@ -6,10 +6,10 @@ import type {
DS4ItemDataSourceDataBase,
DS4ItemDataSourceDataEquipable,
DS4ItemDataSourceDataPhysical,
} from "../item-data-source-base";
} from '../item-data-source-base';
export interface DS4EquipmentDataSource {
type: "equipment";
type: 'equipment';
data: DS4EquipmentDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Equipment extends DS4Item {}

View file

@ -2,17 +2,17 @@
//
// SPDX-License-Identifier: MIT
import type { DS4AlphabetDataProperties } from "./alphabet/alphabet-data-properties";
import type { DS4ArmorDataProperties } from "./armor/armor-data-properties";
import type { DS4EquipmentDataProperties } from "./equipment/equipment-data-properties";
import type { DS4LanguageDataProperties } from "./language/language-data-properties";
import type { DS4LootDataProperties } from "./loot/loot-data-properties";
import type { DS4RacialAbilityDataProperties } from "./racial-ability/racial-ability-data-properties";
import type { DS4ShieldDataProperties } from "./shield/shield-data-properties";
import type { DS4SpecialCreatureAbilityDataProperties } from "./special-creature-ability/special-creature-ability-data-properties";
import type { DS4SpellDataProperties } from "./spell/spell-data-properties";
import type { DS4TalentDataProperties } from "./talent/talent-data-properties";
import type { DS4WeaponDataProperties } from "./weapon/weapon-data-properties";
import type { DS4AlphabetDataProperties } from './alphabet/alphabet-data-properties';
import type { DS4ArmorDataProperties } from './armor/armor-data-properties';
import type { DS4EquipmentDataProperties } from './equipment/equipment-data-properties';
import type { DS4LanguageDataProperties } from './language/language-data-properties';
import type { DS4LootDataProperties } from './loot/loot-data-properties';
import type { DS4RacialAbilityDataProperties } from './racial-ability/racial-ability-data-properties';
import type { DS4ShieldDataProperties } from './shield/shield-data-properties';
import type { DS4SpecialCreatureAbilityDataProperties } from './special-creature-ability/special-creature-ability-data-properties';
import type { DS4SpellDataProperties } from './spell/spell-data-properties';
import type { DS4TalentDataProperties } from './talent/talent-data-properties';
import type { DS4WeaponDataProperties } from './weapon/weapon-data-properties';
declare global {
interface DataConfig {

View file

@ -4,7 +4,7 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../config";
import type { DS4 } from '../../config';
export interface DS4ItemDataSourceDataBase {
description: string;

View file

@ -2,18 +2,18 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../config";
import type { DS4AlphabetDataSource } from "./alphabet/alphabet-data-source";
import type { DS4ArmorDataSource } from "./armor/armor-data-source";
import type { DS4EquipmentDataSource } from "./equipment/equipment-data-source";
import type { DS4LanguageDataSource } from "./language/language-data-source";
import type { DS4LootDataSource } from "./loot/loot-data-source";
import type { DS4RacialAbilityDataSource } from "./racial-ability/racial-ability-data-source";
import type { DS4ShieldDataSource } from "./shield/shield-data-source";
import type { DS4SpecialCreatureAbilityDataSource } from "./special-creature-ability/special-creature-ability-data-source";
import type { DS4SpellDataSource } from "./spell/spell-data-source";
import type { DS4TalentDataSource } from "./talent/talent-data-source";
import type { DS4WeaponDataSource } from "./weapon/weapon-data-source";
import type { DS4 } from '../../config';
import type { DS4AlphabetDataSource } from './alphabet/alphabet-data-source';
import type { DS4ArmorDataSource } from './armor/armor-data-source';
import type { DS4EquipmentDataSource } from './equipment/equipment-data-source';
import type { DS4LanguageDataSource } from './language/language-data-source';
import type { DS4LootDataSource } from './loot/loot-data-source';
import type { DS4RacialAbilityDataSource } from './racial-ability/racial-ability-data-source';
import type { DS4ShieldDataSource } from './shield/shield-data-source';
import type { DS4SpecialCreatureAbilityDataSource } from './special-creature-ability/special-creature-ability-data-source';
import type { DS4SpellDataSource } from './spell/spell-data-source';
import type { DS4TalentDataSource } from './talent/talent-data-source';
import type { DS4WeaponDataSource } from './weapon/weapon-data-source';
declare global {
interface SourceConfig {

View file

@ -3,7 +3,7 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../../utils/utils";
import { getGame } from '../../utils/utils';
/**
* 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
*/
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
*/
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
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 }));
}
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4LanguageDataSourceData } from "./language-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4LanguageDataSourceData } from './language-data-source';
export interface DS4LanguageDataProperties {
type: "language";
type: 'language';
data: DS4LanguageDataPropertiesData;
}

View file

@ -2,10 +2,10 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
export interface DS4LanguageDataSource {
type: "language";
type: 'language';
data: DS4LanguageDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Language extends DS4Item {}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4LootDataSourceData } from "./loot-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4LootDataSourceData } from './loot-data-source';
export interface DS4LootDataProperties {
type: "loot";
type: 'loot';
data: DS4LootDataPropertiesData;
}

View file

@ -2,10 +2,10 @@
//
// 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 {
type: "loot";
type: 'loot';
data: DS4LootDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Loot extends DS4Item {}

View file

@ -2,19 +2,19 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../../utils/utils";
import { DS4Alphabet } from "./alphabet/alphabet";
import { DS4Armor } from "./armor/armor";
import { DS4Equipment } from "./equipment/equipment";
import { DS4Item } from "./item";
import { DS4Language } from "./language/language";
import { DS4Loot } from "./loot/loot";
import { DS4RacialAbility } from "./racial-ability/racial-ability";
import { DS4Shield } from "./shield/shield";
import { DS4SpecialCreatureAbility } from "./special-creature-ability/special-creature-ability";
import { DS4Spell } from "./spell/spell";
import { DS4Talent } from "./talent/talent";
import { DS4Weapon } from "./weapon/weapon";
import { getGame } from '../../utils/utils';
import { DS4Alphabet } from './alphabet/alphabet';
import { DS4Armor } from './armor/armor';
import { DS4Equipment } from './equipment/equipment';
import { DS4Item } from './item';
import { DS4Language } from './language/language';
import { DS4Loot } from './loot/loot';
import { DS4RacialAbility } from './racial-ability/racial-ability';
import { DS4Shield } from './shield/shield';
import { DS4SpecialCreatureAbility } from './special-creature-ability/special-creature-ability';
import { DS4Spell } from './spell/spell';
import { DS4Talent } from './talent/talent';
import { DS4Weapon } from './weapon/weapon';
const handler = {
/**
@ -23,30 +23,30 @@ const handler = {
*/
construct(_, args) {
switch (args[0]?.type) {
case "alphabet":
case 'alphabet':
return new DS4Alphabet(...args);
case "armor":
case 'armor':
return new DS4Armor(...args);
case "equipment":
case 'equipment':
return new DS4Equipment(...args);
case "language":
case 'language':
return new DS4Language(...args);
case "loot":
case 'loot':
return new DS4Loot(...args);
case "racialAbility":
case 'racialAbility':
return new DS4RacialAbility(...args);
case "shield":
case 'shield':
return new DS4Shield(...args);
case "specialCreatureAbility":
case 'specialCreatureAbility':
return new DS4SpecialCreatureAbility(...args);
case "spell":
case 'spell':
return new DS4Spell(...args);
case "talent":
case 'talent':
return new DS4Talent(...args);
case "weapon":
case 'weapon':
return new DS4Weapon(...args);
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 }));
}
},
};

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4RacialAbilityDataSourceData } from "./racial-ability-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4RacialAbilityDataSourceData } from './racial-ability-data-source';
export interface DS4RacialAbilityDataProperties {
type: "racialAbility";
type: 'racialAbility';
data: DS4RacialAbilityDataPropertiesData;
}

View file

@ -2,10 +2,10 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
export interface DS4RacialAbilityDataSource {
type: "racialAbility";
type: 'racialAbility';
data: DS4RacialAbilityDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4RacialAbility extends DS4Item {}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4ShieldDataSourceData } from "./shield-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4ShieldDataSourceData } from './shield-data-source';
export interface DS4ShieldDataProperties {
type: "shield";
type: 'shield';
data: DS4ShieldDataPropertiesData;
}

View file

@ -7,10 +7,10 @@ import type {
DS4ItemDataSourceDataEquipable,
DS4ItemDataSourceDataPhysical,
DS4ItemDataSourceDataProtective,
} from "../item-data-source-base";
} from '../item-data-source-base';
export interface DS4ShieldDataSource {
type: "shield";
type: 'shield';
data: DS4ShieldDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Shield extends DS4Item {}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4SpecialCreatureAbilityDataSourceData } from "./special-creature-ability-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4SpecialCreatureAbilityDataSourceData } from './special-creature-ability-data-source';
export interface DS4SpecialCreatureAbilityDataProperties {
type: "specialCreatureAbility";
type: 'specialCreatureAbility';
data: DS4SpecialCreatureAbilityDataPropertiesData;
}

View file

@ -2,10 +2,10 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
export interface DS4SpecialCreatureAbilityDataSource {
type: "specialCreatureAbility";
type: 'specialCreatureAbility';
data: DS4SpecialCreatureAbilityDataSourceData;
}

View file

@ -2,6 +2,6 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4SpecialCreatureAbility extends DS4Item {}

View file

@ -2,7 +2,7 @@
//
// 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 {
const spellPriceFactor = calculateSpellPriceFactor(data.cooldownDuration);
@ -17,16 +17,16 @@ export function calculateSpellPrice(data: DS4SpellDataSourceData): number | null
function calculateSpellPriceFactor(cooldownDuration: CooldownDuration): number {
switch (cooldownDuration) {
case "0r":
case "1r":
case "2r":
case "5r":
case "10r":
case "100r":
case '0r':
case '1r':
case '2r':
case '5r':
case '10r':
case '100r':
return 1;
case "1d":
case '1d':
return 2;
case "d20d":
case 'd20d':
return 3;
}
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4SpellDataSourceData } from "./spell-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4SpellDataSourceData } from './spell-data-source';
export interface DS4SpellDataProperties {
type: "spell";
type: 'spell';
data: DS4SpellDataPropertiesData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../../config";
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataEquipable } from "../item-data-source-base";
import type { DS4 } from '../../../config';
import type { DS4ItemDataSourceDataBase, DS4ItemDataSourceDataEquipable } from '../item-data-source-base';
export interface DS4SpellDataSource {
type: "spell";
type: 'spell';
data: DS4SpellDataSourceData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import { createCheckRoll } from "../../../dice/check-factory";
import { notifications } from "../../../ui/notifications";
import { getGame } from "../../../utils/utils";
import { DS4Item } from "../item";
import { calculateSpellPrice } from "./calculate-spell-price";
import { createCheckRoll } from '../../../dice/check-factory';
import { notifications } from '../../../ui/notifications';
import { getGame } from '../../../utils/utils';
import { DS4Item } from '../item';
import { calculateSpellPrice } from './calculate-spell-price';
export class DS4Spell extends DS4Item {
/** @override */
@ -24,7 +24,7 @@ export class DS4Spell extends DS4Item {
if (!this.system.equipped) {
return notifications.warn(
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
game.i18n.format('DS4.WarningItemMustBeEquippedToBeRolled', {
name: this.name,
id: this.id,
type: this.type,
@ -33,14 +33,14 @@ export class DS4Spell extends DS4Item {
}
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 hasComplexModifier = this.system.spellModifier.complex !== "";
const hasComplexModifier = this.system.spellModifier.complex !== '';
if (hasComplexModifier === undefined) {
notifications.info(
game.i18n.format("DS4.InfoManuallyEnterSpellModifier", {
game.i18n.format('DS4.InfoManuallyEnterSpellModifier', {
name: this.name,
spellModifier: this.system.spellModifier.complex,
}),
@ -49,24 +49,23 @@ export class DS4Spell extends DS4Item {
const spellType = this.system.spellType;
const opponentDefense = this.system.opponentDefense;
const checkTargetNumber =
ownerSystemData.combatValues[spellType].total +
(hasComplexModifier ? 0 : this.system.spellModifier.numerical);
ownerSystemData.combatValues[spellType].total + (hasComplexModifier ? 0 : this.system.spellModifier.numerical);
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
const flavor =
opponentDefense !== undefined && opponentDefense !== 0
? "DS4.ItemSpellCheckFlavorWithOpponentDefense"
: "DS4.ItemSpellCheckFlavor";
? 'DS4.ItemSpellCheckFlavorWithOpponentDefense'
: 'DS4.ItemSpellCheckFlavor';
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
const flavorData = {
actor: speaker.alias ?? this.actor.name,
spell: this.name,
};
if (opponentDefense !== undefined && opponentDefense !== 0) {
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
flavorData.opponentDefense = (opponentDefense < 0 ? '' : '+') + opponentDefense;
}
await createCheckRoll(checkTargetNumber, {
rollMode: game.settings.get("core", "rollMode"),
rollMode: game.settings.get('core', 'rollMode'),
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
flavor: flavor,
@ -80,6 +79,6 @@ export class DS4Spell extends DS4Item {
* @memberof hookEvents
* @param {DS4Item} item Item being rolled.
*/
Hooks.callAll("ds4.rollItem", this);
Hooks.callAll('ds4.rollItem', this);
}
}

View file

@ -2,12 +2,12 @@
//
// SPDX-License-Identifier: MIT
import type { ModifiableDataBaseTotalMax } from "../../common/common-data";
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4TalentDataSourceData } from "./talent-data-source";
import type { ModifiableDataBaseTotalMax } from '../../common/common-data';
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4TalentDataSourceData } from './talent-data-source';
export interface DS4TalentDataProperties {
type: "talent";
type: 'talent';
data: DS4TalentDataPropertiesData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import type { ModifiableDataBaseMax } from "../../common/common-data";
import type { DS4ItemDataSourceDataBase } from "../item-data-source-base";
import type { ModifiableDataBaseMax } from '../../common/common-data';
import type { DS4ItemDataSourceDataBase } from '../item-data-source-base';
export interface DS4TalentDataSource {
type: "talent";
type: 'talent';
data: DS4TalentDataSourceData;
}

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4Item } from "../item";
import { DS4Item } from '../item';
export class DS4Talent extends DS4Item {
/** @override */

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import type { DS4ItemDataPropertiesDataRollable } from "../item-data-properties-base";
import type { DS4WeaponDataSourceData } from "./weapon-data-source";
import type { DS4ItemDataPropertiesDataRollable } from '../item-data-properties-base';
import type { DS4WeaponDataSourceData } from './weapon-data-source';
interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDataPropertiesDataRollable {
opponentDefenseForAttackType: {
@ -13,6 +13,6 @@ interface DS4WeaponDataPropertiesData extends DS4WeaponDataSourceData, DS4ItemDa
}
export interface DS4WeaponDataProperties {
type: "weapon";
type: 'weapon';
data: DS4WeaponDataPropertiesData;
}

View file

@ -2,15 +2,15 @@
//
// SPDX-License-Identifier: MIT
import type { DS4 } from "../../../config";
import type { DS4 } from '../../../config';
import type {
DS4ItemDataSourceDataBase,
DS4ItemDataSourceDataEquipable,
DS4ItemDataSourceDataPhysical,
} from "../item-data-source-base";
} from '../item-data-source-base';
export interface DS4WeaponDataSource {
type: "weapon";
type: 'weapon';
data: DS4WeaponDataSourceData;
}

View file

@ -2,11 +2,11 @@
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../../../config";
import { createCheckRoll } from "../../../dice/check-factory";
import { notifications } from "../../../ui/notifications";
import { getGame } from "../../../utils/utils";
import { DS4Item } from "../item";
import { DS4 } from '../../../config';
import { createCheckRoll } from '../../../dice/check-factory';
import { notifications } from '../../../ui/notifications';
import { getGame } from '../../../utils/utils';
import { DS4Item } from '../item';
export class DS4Weapon extends DS4Item {
/** @override */
@ -14,10 +14,10 @@ export class DS4Weapon extends DS4Item {
const system = this.system;
system.rollable = system.equipped;
system.opponentDefenseForAttackType = {};
if (system.attackType === "melee" || system.attackType === "meleeRanged") {
if (system.attackType === 'melee' || system.attackType === 'meleeRanged') {
system.opponentDefenseForAttackType.melee = system.opponentDefense;
}
if (system.attackType === "ranged" || system.attackType === "meleeRanged") {
if (system.attackType === 'ranged' || system.attackType === 'meleeRanged') {
system.opponentDefenseForAttackType.ranged = system.opponentDefense;
}
}
@ -27,7 +27,7 @@ export class DS4Weapon extends DS4Item {
const game = getGame();
if (!this.system.equipped) {
return notifications.warn(
game.i18n.format("DS4.WarningItemMustBeEquippedToBeRolled", {
game.i18n.format('DS4.WarningItemMustBeEquippedToBeRolled', {
name: this.name,
id: this.id,
type: this.type,
@ -36,7 +36,7 @@ export class DS4Weapon extends DS4Item {
}
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;
@ -48,19 +48,19 @@ export class DS4Weapon extends DS4Item {
const speaker = ChatMessage.getSpeaker({ actor: this.actor, ...options.speaker });
const flavor =
opponentDefense !== undefined && opponentDefense !== 0
? "DS4.ItemWeaponCheckFlavorWithOpponentDefense"
: "DS4.ItemWeaponCheckFlavor";
? 'DS4.ItemWeaponCheckFlavorWithOpponentDefense'
: 'DS4.ItemWeaponCheckFlavor';
/** @type {import("../../../dice/check-factory").DS4CheckFactoryOptions["flavorData"]} */
const flavorData = {
actor: speaker.alias ?? this.actor.name,
weapon: this.name,
};
if (opponentDefense !== undefined && opponentDefense !== 0) {
flavorData.opponentDefense = (opponentDefense < 0 ? "" : "+") + opponentDefense;
flavorData.opponentDefense = (opponentDefense < 0 ? '' : '+') + opponentDefense;
}
await createCheckRoll(checkTargetNumber, {
rollMode: getGame().settings.get("core", "rollMode"),
rollMode: getGame().settings.get('core', 'rollMode'),
maximumCoupResult: ownerSystemData.rolling.maximumCoupResult,
minimumFumbleResult: ownerSystemData.rolling.minimumFumbleResult,
speaker,
@ -68,7 +68,7 @@ export class DS4Weapon extends DS4Item {
flavorData,
});
Hooks.callAll("ds4.rollItem", this);
Hooks.callAll('ds4.rollItem', this);
}
/**
@ -77,29 +77,29 @@ export class DS4Weapon extends DS4Item {
* @protected
*/
async getPerformedAttackType() {
if (this.system.attackType !== "meleeRanged") {
if (this.system.attackType !== 'meleeRanged') {
return this.system.attackType;
}
const { melee, ranged } = { ...DS4.i18n.attackTypes };
const identifier = `attack-type-selection-${foundry.utils.randomID()}`;
return Dialog.prompt({
title: getGame().i18n.localize("DS4.DialogAttackTypeSelection"),
content: await renderTemplate("systems/ds4/templates/dialogs/simple-select-form.hbs", {
title: getGame().i18n.localize('DS4.DialogAttackTypeSelection'),
content: await renderTemplate('systems/ds4/templates/dialogs/simple-select-form.hbs', {
selects: [
{
label: getGame().i18n.localize("DS4.AttackType"),
label: getGame().i18n.localize('DS4.AttackType'),
identifier,
options: { melee, ranged },
},
],
}),
label: getGame().i18n.localize("DS4.GenericOkButton"),
label: getGame().i18n.localize('DS4.GenericOkButton'),
callback: (html) => {
const selectedAttackType = html.find(`#${identifier}`).val();
if (selectedAttackType !== "melee" && selectedAttackType !== "ranged") {
if (selectedAttackType !== 'melee' && selectedAttackType !== 'ranged') {
throw new Error(
getGame().i18n.format("DS4.ErrorUnexpectedAttackType", {
getGame().i18n.format('DS4.ErrorUnexpectedAttackType', {
actualType: selectedAttackType,
expectedTypes: "'melee', 'ranged'",
}),

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import { getGame } from "../utils/utils";
import { DS4ActorProxy } from "./actor/proxy";
import { getGame } from '../utils/utils';
import { DS4ActorProxy } from './actor/proxy';
/** @type {object | undefined} */
let fallbackData = undefined;
@ -12,7 +12,7 @@ function getFallbackData() {
if (!fallbackData) {
fallbackData = {};
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;

View file

@ -2,8 +2,8 @@
//
// SPDX-License-Identifier: MIT
import "../scss/ds4.scss";
import '../scss/ds4.scss';
import { registerForHooks } from "./hooks/hooks";
import { registerForHooks } from './hooks/hooks';
registerForHooks();

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { Validator } from "./validator";
import { Validator } from './validator';
export class Evaluator<Context extends object> {
context?: Context;
@ -28,7 +28,7 @@ export class Evaluator<Context extends object> {
this.validator.validate(expression);
const body = `with (sandbox) { return ${expression}; }`;
const evaluate = new Function("sandbox", body);
const evaluate = new Function('sandbox', body);
return evaluate(this.context ?? {});
}
}

View file

@ -15,47 +15,47 @@ interface TokenWithoutSymbol {
pos: number;
}
type TypeWithSymbol = "iden" | "number" | "string";
type TypeWithSymbol = 'iden' | 'number' | 'string';
type TypeWithoutSymbol =
| "+"
| "-"
| "*"
| "**"
| "/"
| "%"
| "==="
| "!=="
| "=="
| "!="
| "<"
| "<="
| ">"
| ">="
| "&&"
| "||"
| "&"
| "|"
| "~"
| "^"
| "<<"
| ">>"
| ">>>"
| "."
| "?."
| "??"
| "!"
| "?"
| ":"
| "("
| ")"
| "["
| "]"
| ","
| "{"
| "}"
| "invalid"
| "eof";
| '+'
| '-'
| '*'
| '**'
| '/'
| '%'
| '==='
| '!=='
| '=='
| '!='
| '<'
| '<='
| '>'
| '>='
| '&&'
| '||'
| '&'
| '|'
| '~'
| '^'
| '<<'
| '>>'
| '>>>'
| '.'
| '?.'
| '??'
| '!'
| '?'
| ':'
| '('
| ')'
| '['
| ']'
| ','
| '{'
| '}'
| 'invalid'
| 'eof';
export const literals = ["true", "false", "null", "undefined"];
export const safeOperators = ["in", "instanceof", "typeof", "void"];
export const literals = ['true', 'false', 'null', 'undefined'];
export const safeOperators = ['in', 'instanceof', 'typeof', 'void'];

Some files were not shown because too many files have changed in this diff Show more