Merge branch '068-enable-strict-mode' into 'master'
Enable strict mode Closes #68 See merge request dungeonslayers/ds4!72
This commit is contained in:
commit
33dcbab6d5
14 changed files with 1752 additions and 1466 deletions
|
@ -1,4 +1,4 @@
|
||||||
image: node:latest
|
image: node:lts
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- prepare
|
- prepare
|
||||||
|
|
2994
package-lock.json
generated
2994
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -198,7 +198,11 @@
|
||||||
"DS4.RollDialogDefaultTitle": "Proben-Optionen",
|
"DS4.RollDialogDefaultTitle": "Proben-Optionen",
|
||||||
"DS4.RollDialogOkButton": "OK",
|
"DS4.RollDialogOkButton": "OK",
|
||||||
"DS4.RollDialogCancelButton": "Abbrechen",
|
"DS4.RollDialogCancelButton": "Abbrechen",
|
||||||
"DS4.ErrorUnexpectedHtmlType": "Typfehler: Erwartet wurde {exType}, tatsächlich erhalten wurde {realType}",
|
"DS4.ErrorUnexpectedHtmlType": "Typfehler: Erwartet wurde '{exType}', tatsächlich erhalten wurde '{realType}'.",
|
||||||
|
"DS4.ErrorCouldNotFindForm": "Konnte HTML Element '{htmlElement}' nicht finden.",
|
||||||
|
"DS4.ErrorActorDoesNotHaveItem": "Der Aktor '{actor}' hat kein Item mit der ID '{id}'.",
|
||||||
|
"DS4.ErrorUnexpectedError": "Es gab einen unerwarteten Fehler im Dungeonslayers 4 System. Für mehr Details schauen Sie bitte in die Konsole (F12).",
|
||||||
|
"DS4.ErrorItemDoesNotHaveEffect": "Das Item '{item}' hat keinen Effekt mit der ID '{id}'.",
|
||||||
"DS4.RollDialogTargetLabel": "Probenwert",
|
"DS4.RollDialogTargetLabel": "Probenwert",
|
||||||
"DS4.RollDialogModifierLabel": "SL-Modifikator",
|
"DS4.RollDialogModifierLabel": "SL-Modifikator",
|
||||||
"DS4.RollDialogCoupLabel": "Immersieg bis",
|
"DS4.RollDialogCoupLabel": "Immersieg bis",
|
||||||
|
|
|
@ -198,7 +198,11 @@
|
||||||
"DS4.RollDialogDefaultTitle": "Roll Options",
|
"DS4.RollDialogDefaultTitle": "Roll Options",
|
||||||
"DS4.RollDialogOkButton": "Ok",
|
"DS4.RollDialogOkButton": "Ok",
|
||||||
"DS4.RollDialogCancelButton": "Cancel",
|
"DS4.RollDialogCancelButton": "Cancel",
|
||||||
"DS4.ErrorUnexpectedHtmlType": "Type Error: Expected {exType}, got {realType}",
|
"DS4.ErrorUnexpectedHtmlType": "Type Error: Expected '{exType}' but got '{realType}'.",
|
||||||
|
"DS4.ErrorCouldNotFindForm": "Could not find HTML element '{htmlElement}'.",
|
||||||
|
"DS4.ErrorActorDoesNotHaveItem": "The actor '{actor}' does not have any item with the id '{id}'.",
|
||||||
|
"DS4.ErrorUnexpectedError": "There was an unexpected error in the Dungeonslayers 4 system. For more details, please take a look at the console (F12).",
|
||||||
|
"DS4.ErrorItemDoesNotHaveEffect": "The item '{item}' does not have any effect with the id '{id}'.",
|
||||||
"DS4.RollDialogTargetLabel": "Check Target Number",
|
"DS4.RollDialogTargetLabel": "Check Target Number",
|
||||||
"DS4.RollDialogModifierLabel": "Game Master Modifier",
|
"DS4.RollDialogModifierLabel": "Game Master Modifier",
|
||||||
"DS4.RollDialogCoupLabel": "Coup to",
|
"DS4.RollDialogCoupLabel": "Coup to",
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { DS4Actor } from "../actor";
|
||||||
/**
|
/**
|
||||||
* The base Sheet class for all DS4 Actors
|
* The base Sheet class for all DS4 Actors
|
||||||
*/
|
*/
|
||||||
export class DS4ActorSheet extends ActorSheet<DS4Actor> {
|
export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
|
||||||
// TODO(types): Improve mergeObject in upstream so that it isn't necessary to provide all parameters (see https://github.com/League-of-Foundry-Developers/foundry-vtt-types/issues/272)
|
// TODO(types): Improve mergeObject in upstream so that it isn't necessary to provide all parameters (see https://github.com/League-of-Foundry-Developers/foundry-vtt-types/issues/272)
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions(): BaseEntitySheet.Options {
|
static get defaultOptions(): BaseEntitySheet.Options {
|
||||||
|
@ -48,9 +48,9 @@ export class DS4ActorSheet extends ActorSheet<DS4Actor> {
|
||||||
* object itemsByType.
|
* object itemsByType.
|
||||||
* @returns The data fed to the template of the actor sheet
|
* @returns The data fed to the template of the actor sheet
|
||||||
*/
|
*/
|
||||||
getData(): ActorSheet.Data<DS4Actor> | Promise<ActorSheet.Data<DS4Actor>> {
|
async getData(): Promise<ActorSheet.Data<DS4Actor>> {
|
||||||
const data = {
|
const data = {
|
||||||
...super.getData(),
|
...(await super.getData()),
|
||||||
// Add the localization config to the data:
|
// Add the localization config to the data:
|
||||||
config: DS4,
|
config: DS4,
|
||||||
// Add the items explicitly sorted by type to the data:
|
// Add the items explicitly sorted by type to the data:
|
||||||
|
@ -72,7 +72,14 @@ export class DS4ActorSheet extends ActorSheet<DS4Actor> {
|
||||||
// Update Inventory Item
|
// Update Inventory Item
|
||||||
html.find(".item-edit").on("click", (ev) => {
|
html.find(".item-edit").on("click", (ev) => {
|
||||||
const li = $(ev.currentTarget).parents(".item");
|
const li = $(ev.currentTarget).parents(".item");
|
||||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
const id = li.data("itemId");
|
||||||
|
const item = this.actor.getOwnedItem(id);
|
||||||
|
if (!item) {
|
||||||
|
throw new Error(game.i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
||||||
|
}
|
||||||
|
if (!item.sheet) {
|
||||||
|
throw new Error(game.i18n.localize("DS4.ErrorUnexpectedError"));
|
||||||
|
}
|
||||||
item.sheet.render(true);
|
item.sheet.render(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -221,7 +228,7 @@ export class DS4ActorSheet extends ActorSheet<DS4Actor> {
|
||||||
): Promise<boolean | undefined | ActorSheet.OwnedItemData<DS4Actor>> {
|
): Promise<boolean | undefined | ActorSheet.OwnedItemData<DS4Actor>> {
|
||||||
const item = ((await Item.fromDropData(data)) as unknown) as DS4Item;
|
const item = ((await Item.fromDropData(data)) as unknown) as DS4Item;
|
||||||
if (item && !this.actor.canOwnItemType(item.data.type)) {
|
if (item && !this.actor.canOwnItemType(item.data.type)) {
|
||||||
ui.notifications.warn(
|
ui.notifications?.warn(
|
||||||
game.i18n.format("DS4.WarningActorCannotOwnItem", {
|
game.i18n.format("DS4.WarningActorCannotOwnItem", {
|
||||||
actorName: this.actor.name,
|
actorName: this.actor.name,
|
||||||
actorType: this.actor.data.type,
|
actorType: this.actor.data.type,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { createCheckRoll } from "./rolls/check-factory";
|
||||||
import { registerSystemSettings } from "./settings";
|
import { registerSystemSettings } from "./settings";
|
||||||
import { migration } from "./migrations";
|
import { migration } from "./migrations";
|
||||||
|
|
||||||
Hooks.once("init", async function () {
|
Hooks.once("init", async () => {
|
||||||
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
|
console.log(`DS4 | Initializing the DS4 Game System\n${DS4.ASCII}`);
|
||||||
|
|
||||||
game.ds4 = {
|
game.ds4 = {
|
||||||
|
@ -68,23 +68,11 @@ async function registerHandlebarsPartials() {
|
||||||
/**
|
/**
|
||||||
* This function runs after game data has been requested and loaded from the servers, so entities exist
|
* This function runs after game data has been requested and loaded from the servers, so entities exist
|
||||||
*/
|
*/
|
||||||
Hooks.once("setup", function () {
|
Hooks.once("setup", () => {
|
||||||
const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"];
|
localizeAndSortConfigObjects();
|
||||||
|
|
||||||
// Localize and sort CONFIG objects
|
|
||||||
for (const o of Object.keys(DS4.i18n)) {
|
|
||||||
const localized = Object.entries(DS4.i18n[o]).map((e) => {
|
|
||||||
return [e[0], game.i18n.localize(e[1] as string)];
|
|
||||||
});
|
|
||||||
if (!noSort.includes(o)) localized.sort((a, b) => a[1].localeCompare(b[1]));
|
|
||||||
DS4.i18n[o] = localized.reduce((obj, e) => {
|
|
||||||
obj[e[0]] = e[1];
|
|
||||||
return obj;
|
|
||||||
}, {});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Hooks.once("ready", function () {
|
Hooks.once("ready", () => {
|
||||||
migration.migrate();
|
migration.migrate();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -105,3 +93,24 @@ Hooks.once("ready", function () {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Localizes all objects in {@link DS4.i18n} and sorts them unless they are explicitly excluded.
|
||||||
|
*/
|
||||||
|
function localizeAndSortConfigObjects() {
|
||||||
|
const noSort = ["attributes", "traits", "combatValues", "creatureSizeCategories"];
|
||||||
|
|
||||||
|
const localizeObject = <T extends { [s: string]: string }>(obj: T, sort = true): T => {
|
||||||
|
const localized = Object.entries(obj).map(([key, value]) => {
|
||||||
|
return [key, game.i18n.localize(value)];
|
||||||
|
});
|
||||||
|
if (sort) localized.sort((a, b) => a[1].localeCompare(b[1]));
|
||||||
|
return Object.fromEntries(localized);
|
||||||
|
};
|
||||||
|
|
||||||
|
DS4.i18n = Object.fromEntries(
|
||||||
|
Object.entries(DS4.i18n).map(([key, value]) => {
|
||||||
|
return [key, localizeObject(value, !noSort.includes(key))];
|
||||||
|
}),
|
||||||
|
) as typeof DS4.i18n;
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { isDS4ItemDataTypePhysical } from "./item-data";
|
||||||
/**
|
/**
|
||||||
* The Sheet class for DS4 Items
|
* The Sheet class for DS4 Items
|
||||||
*/
|
*/
|
||||||
export class DS4ItemSheet extends ItemSheet<DS4Item> {
|
export class DS4ItemSheet extends ItemSheet<ItemSheet.Data<DS4Item>> {
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions(): BaseEntitySheet.Options {
|
static get defaultOptions(): BaseEntitySheet.Options {
|
||||||
const superDefaultOptions = super.defaultOptions;
|
const superDefaultOptions = super.defaultOptions;
|
||||||
|
@ -41,9 +41,9 @@ export class DS4ItemSheet extends ItemSheet<DS4Item> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
getData(): ItemSheet.Data<DS4Item> | Promise<ItemSheet.Data<DS4Item>> {
|
async getData(): Promise<ItemSheet.Data<DS4Item>> {
|
||||||
const data = {
|
const data = {
|
||||||
...super.getData(),
|
...(await super.getData()),
|
||||||
config: DS4,
|
config: DS4,
|
||||||
isOwned: this.item.isOwned,
|
isOwned: this.item.isOwned,
|
||||||
actor: this.item.actor,
|
actor: this.item.actor,
|
||||||
|
@ -83,7 +83,7 @@ export class DS4ItemSheet extends ItemSheet<DS4Item> {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.item.isOwned) {
|
if (this.item.isOwned) {
|
||||||
return ui.notifications.warn(game.i18n.localize("DS4.WarningManageActiveEffectOnOwnedItem"));
|
return ui.notifications?.warn(game.i18n.localize("DS4.WarningManageActiveEffectOnOwnedItem"));
|
||||||
}
|
}
|
||||||
const a = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
const li = $(a).parents(".effect");
|
const li = $(a).parents(".effect");
|
||||||
|
@ -92,7 +92,11 @@ export class DS4ItemSheet extends ItemSheet<DS4Item> {
|
||||||
case "create":
|
case "create":
|
||||||
return this._createActiveEffect();
|
return this._createActiveEffect();
|
||||||
case "edit":
|
case "edit":
|
||||||
const effect = this.item.effects.get(li.data("effectId"));
|
const id = li.data("effectId");
|
||||||
|
const effect = this.item.effects.get(id);
|
||||||
|
if (!effect) {
|
||||||
|
throw new Error(game.i18n.format("DS4.ErrorItemDoesNotHaveEffect", { id, item: this.item.name }));
|
||||||
|
}
|
||||||
return effect.sheet.render(true);
|
return effect.sheet.render(true);
|
||||||
case "delete": {
|
case "delete": {
|
||||||
return this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId"));
|
return this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId"));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { migrate as migrate001 } from "./migrations/001";
|
import { migrate as migrate001 } from "./migrations/001";
|
||||||
|
|
||||||
async function migrate(): Promise<void> {
|
async function migrate(): Promise<void> {
|
||||||
if (!game.user.isGM) {
|
if (!game.user?.isGM) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,14 +18,14 @@ async function migrate(): Promise<void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion: number): Promise<void> {
|
async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion: number): Promise<void> {
|
||||||
if (!game.user.isGM) {
|
if (!game.user?.isGM) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrationsToExecute = migrations.slice(oldMigrationVersion, targetMigrationVersion);
|
const migrationsToExecute = migrations.slice(oldMigrationVersion, targetMigrationVersion);
|
||||||
|
|
||||||
if (migrationsToExecute.length > 0) {
|
if (migrationsToExecute.length > 0) {
|
||||||
ui.notifications.info(
|
ui.notifications?.info(
|
||||||
game.i18n.format("DS4.InfoSystemUpdateStart", {
|
game.i18n.format("DS4.InfoSystemUpdateStart", {
|
||||||
currentVersion: oldMigrationVersion,
|
currentVersion: oldMigrationVersion,
|
||||||
targetVersion: targetMigrationVersion,
|
targetVersion: targetMigrationVersion,
|
||||||
|
@ -40,7 +40,7 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion
|
||||||
await migration();
|
await migration();
|
||||||
game.settings.set("ds4", "systemMigrationVersion", currentMigrationVersion);
|
game.settings.set("ds4", "systemMigrationVersion", currentMigrationVersion);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ui.notifications.error(
|
ui.notifications?.error(
|
||||||
game.i18n.format("DS4.ErrorDuringMigration", {
|
game.i18n.format("DS4.ErrorDuringMigration", {
|
||||||
currentVersion: oldMigrationVersion,
|
currentVersion: oldMigrationVersion,
|
||||||
targetVersion: targetMigrationVersion,
|
targetVersion: targetMigrationVersion,
|
||||||
|
@ -54,7 +54,7 @@ async function migrateFromTo(oldMigrationVersion: number, targetMigrationVersion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.notifications.info(
|
ui.notifications?.info(
|
||||||
game.i18n.format("DS4.InfoSystemUpdateCompleted", {
|
game.i18n.format("DS4.InfoSystemUpdateCompleted", {
|
||||||
currentVersion: oldMigrationVersion,
|
currentVersion: oldMigrationVersion,
|
||||||
targetVersion: targetMigrationVersion,
|
targetVersion: targetMigrationVersion,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export async function migrate(): Promise<void> {
|
export async function migrate(): Promise<void> {
|
||||||
for (const a of game.actors.entities) {
|
for (const a of game.actors?.entities ?? []) {
|
||||||
const updateData = getActorUpdateData();
|
const updateData = getActorUpdateData();
|
||||||
console.log(`Migrating actor ${a.name}`);
|
console.log(`Migrating actor ${a.name}`);
|
||||||
await a.update(updateData, { enforceTypes: false });
|
await a.update(updateData, { enforceTypes: false });
|
||||||
|
@ -18,7 +18,7 @@ function getActorUpdateData(): Record<string, unknown> {
|
||||||
"rangedAttack",
|
"rangedAttack",
|
||||||
"spellcasting",
|
"spellcasting",
|
||||||
"targetedSpellcasting",
|
"targetedSpellcasting",
|
||||||
].reduce((acc, curr) => {
|
].reduce((acc: Partial<Record<string, { "-=base": null }>>, curr) => {
|
||||||
acc[curr] = { "-=base": null };
|
acc[curr] = { "-=base": null };
|
||||||
return acc;
|
return acc;
|
||||||
}, {}),
|
}, {}),
|
||||||
|
|
|
@ -131,34 +131,42 @@ async function askGmModifier(
|
||||||
const renderedHtml = await renderTemplate(usedTemplate, templateData);
|
const renderedHtml = await renderTemplate(usedTemplate, templateData);
|
||||||
|
|
||||||
const dialogPromise = new Promise<HTMLFormElement>((resolve) => {
|
const dialogPromise = new Promise<HTMLFormElement>((resolve) => {
|
||||||
new Dialog({
|
new Dialog(
|
||||||
title: usedTitle,
|
{
|
||||||
content: renderedHtml,
|
title: usedTitle,
|
||||||
buttons: {
|
content: renderedHtml,
|
||||||
ok: {
|
buttons: {
|
||||||
icon: '<i class="fas fa-check"></i>',
|
ok: {
|
||||||
label: game.i18n.localize("DS4.RollDialogOkButton"),
|
icon: '<i class="fas fa-check"></i>',
|
||||||
callback: (html) => {
|
label: game.i18n.localize("DS4.RollDialogOkButton"),
|
||||||
if (!("jquery" in html)) {
|
callback: (html) => {
|
||||||
throw new Error(
|
if (!("jquery" in html)) {
|
||||||
game.i18n.format("DS4.ErrorUnexpectedHtmlType", {
|
throw new Error(
|
||||||
exType: "JQuery",
|
game.i18n.format("DS4.ErrorUnexpectedHtmlType", {
|
||||||
realType: "HTMLElement",
|
exType: "JQuery",
|
||||||
}),
|
realType: "HTMLElement",
|
||||||
);
|
}),
|
||||||
} else {
|
);
|
||||||
const innerForm = html[0].querySelector("form");
|
} else {
|
||||||
resolve(innerForm);
|
const innerForm = html[0].querySelector("form");
|
||||||
}
|
if (!innerForm) {
|
||||||
|
throw new Error(
|
||||||
|
game.i18n.format("DS4.ErrorCouldNotFindHtmlElement", { htmlElement: "form" }),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
resolve(innerForm);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
icon: '<i class="fas fa-times"></i>',
|
||||||
|
label: game.i18n.localize("DS4.RollDialogCancelButton"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
cancel: {
|
default: "ok",
|
||||||
icon: '<i class="fas fa-times"></i>',
|
|
||||||
label: game.i18n.localize("DS4.RollDialogCancelButton"),
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
default: "ok",
|
{ jQuery: true },
|
||||||
}).render(true);
|
).render(true);
|
||||||
});
|
});
|
||||||
const dialogForm = await dialogPromise;
|
const dialogForm = await dialogPromise;
|
||||||
return parseDialogFormData(dialogForm);
|
return parseDialogFormData(dialogForm);
|
||||||
|
|
|
@ -56,8 +56,8 @@ export class DS4Check extends DiceTerm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
success = null;
|
success: boolean | null = null;
|
||||||
failure = null;
|
failure: boolean | null = null;
|
||||||
targetValue = DS4Check.DEFAULT_TARGET_VALUE;
|
targetValue = DS4Check.DEFAULT_TARGET_VALUE;
|
||||||
minCritFailure = DS4Check.DEFAULT_MIN_CRIT_FAILURE;
|
minCritFailure = DS4Check.DEFAULT_MIN_CRIT_FAILURE;
|
||||||
maxCritSuccess = DS4Check.DEFAULT_MAX_CRIT_SUCCESS;
|
maxCritSuccess = DS4Check.DEFAULT_MAX_CRIT_SUCCESS;
|
||||||
|
@ -93,16 +93,11 @@ export class DS4Check extends DiceTerm {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Term Modifiers */
|
|
||||||
noop(): this {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// DS4 only allows recursive explosions
|
// DS4 only allows recursive explosions
|
||||||
explode(modifier: string): this {
|
explode(modifier: string): void {
|
||||||
const rgx = /[xX]/;
|
const rgx = /[xX]/;
|
||||||
const match = modifier.match(rgx);
|
const match = modifier.match(rgx);
|
||||||
if (!match) return this;
|
if (!match) return;
|
||||||
|
|
||||||
this.results = (this.results as Array<RollResult>)
|
this.results = (this.results as Array<RollResult>)
|
||||||
.map((r) => {
|
.map((r) => {
|
||||||
|
@ -135,7 +130,7 @@ export class DS4Check extends DiceTerm {
|
||||||
static DENOMINATION = "s";
|
static DENOMINATION = "s";
|
||||||
static MODIFIERS = {
|
static MODIFIERS = {
|
||||||
x: "explode",
|
x: "explode",
|
||||||
c: "noop", // Modifier is consumed in constructor for target value
|
c: (): void => undefined, // Modifier is consumed in constructor for crit
|
||||||
v: "noop", // Modifier is consumed in constructor for target value
|
v: (): void => undefined, // Modifier is consumed in constructor for target value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import { calculateRollResult, isDiceSwapNecessary, isSlayingDiceRepetition, sepa
|
||||||
export function ds4roll(
|
export function ds4roll(
|
||||||
checkTargetValue: number,
|
checkTargetValue: number,
|
||||||
rollOptions: Partial<RollOptions> = {},
|
rollOptions: Partial<RollOptions> = {},
|
||||||
dice: Array<number> = null,
|
dice: Array<number> = [],
|
||||||
): RollResult {
|
): RollResult {
|
||||||
if (checkTargetValue <= 20) {
|
if (checkTargetValue <= 20) {
|
||||||
return rollCheckSingleDie(checkTargetValue, rollOptions, dice);
|
return rollCheckSingleDie(checkTargetValue, rollOptions, dice);
|
||||||
|
@ -36,11 +36,11 @@ export function ds4roll(
|
||||||
export function rollCheckSingleDie(
|
export function rollCheckSingleDie(
|
||||||
checkTargetValue: number,
|
checkTargetValue: number,
|
||||||
rollOptions: Partial<RollOptions>,
|
rollOptions: Partial<RollOptions>,
|
||||||
dice: Array<number> = null,
|
dice: Array<number> = [],
|
||||||
): RollResult {
|
): RollResult {
|
||||||
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
|
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
|
||||||
|
|
||||||
if (dice?.length != 1) {
|
if (dice.length != 1) {
|
||||||
dice = [new DS4RollProvider().getNextRoll()];
|
dice = [new DS4RollProvider().getNextRoll()];
|
||||||
}
|
}
|
||||||
const usedDice = dice;
|
const usedDice = dice;
|
||||||
|
@ -75,13 +75,13 @@ export function rollCheckSingleDie(
|
||||||
export function rollCheckMultipleDice(
|
export function rollCheckMultipleDice(
|
||||||
targetValue: number,
|
targetValue: number,
|
||||||
rollOptions: Partial<RollOptions>,
|
rollOptions: Partial<RollOptions>,
|
||||||
dice: Array<number> = null,
|
dice: Array<number> = [],
|
||||||
): RollResult {
|
): RollResult {
|
||||||
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
|
const usedOptions = new DefaultRollOptions().mergeWith(rollOptions);
|
||||||
const remainderTargetValue = targetValue % 20;
|
const remainderTargetValue = targetValue % 20;
|
||||||
const numberOfDice = Math.ceil(targetValue / 20);
|
const numberOfDice = Math.ceil(targetValue / 20);
|
||||||
|
|
||||||
if (!dice || dice.length != numberOfDice) {
|
if (dice.length != numberOfDice) {
|
||||||
dice = new DS4RollProvider().getNextRolls(numberOfDice);
|
dice = new DS4RollProvider().getNextRolls(numberOfDice);
|
||||||
}
|
}
|
||||||
const usedDice = dice;
|
const usedDice = dice;
|
||||||
|
|
37
src/module/ui/notifications.ts
Normal file
37
src/module/ui/notifications.ts
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
const notifications = {
|
||||||
|
info: (message: string, { permanent = false }: { permanent?: boolean } = {}): void => {
|
||||||
|
if (ui.notifications) {
|
||||||
|
ui.notifications.info(message, { permanent });
|
||||||
|
} else {
|
||||||
|
console.info(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
warn: (message: string, { permanent = false }: { permanent?: boolean } = {}): void => {
|
||||||
|
if (ui.notifications) {
|
||||||
|
ui.notifications.warn(message, { permanent });
|
||||||
|
} else {
|
||||||
|
console.log(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: (message: string, { permanent = false }: { permanent?: boolean } = {}): void => {
|
||||||
|
if (ui.notifications) {
|
||||||
|
ui.notifications.error(message, { permanent });
|
||||||
|
} else {
|
||||||
|
console.warn(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
notify: (
|
||||||
|
message: string,
|
||||||
|
type: "info" | "warning" | "error" = "info",
|
||||||
|
{ permanent = false }: { permanent?: boolean } = {},
|
||||||
|
): void => {
|
||||||
|
if (ui.notifications) {
|
||||||
|
ui.notifications.notify(message, type, { permanent });
|
||||||
|
} else {
|
||||||
|
const log = { info: console.info, warning: console.warn, error: console.error }[type];
|
||||||
|
log(message);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default notifications;
|
|
@ -6,7 +6,7 @@
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"strict": false
|
"strict": true
|
||||||
},
|
},
|
||||||
"include": ["src"]
|
"include": ["src"]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue