Merge branch 'separate-data-and_data' into 'master'
Separate data and _data for DS4Item See merge request dungeonslayers/ds4!97
This commit is contained in:
commit
7fad6416fc
13 changed files with 308 additions and 142 deletions
|
@ -46,7 +46,7 @@
|
||||||
"postinstall": "husky install"
|
"postinstall": "husky install"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@league-of-foundry-developers/foundry-vtt-types": "^0.7.9-3",
|
"@league-of-foundry-developers/foundry-vtt-types": "^0.7.9-4",
|
||||||
"@rollup/plugin-node-resolve": "^11.2.0",
|
"@rollup/plugin-node-resolve": "^11.2.0",
|
||||||
"@types/fs-extra": "^9.0.8",
|
"@types/fs-extra": "^9.0.8",
|
||||||
"@types/jest": "^26.0.20",
|
"@types/jest": "^26.0.20",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ModifiableData, ResourceData, UsableResource } from "../common/common-data";
|
import { ModifiableData, ModifiableDataBase, ResourceData, UsableResource } from "../common/common-data";
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from "../config";
|
||||||
import { DS4ItemData } from "../item/item-data";
|
import { DS4ItemData } from "../item/item-data";
|
||||||
|
|
||||||
|
@ -6,33 +6,34 @@ export type DS4ActorData = DS4CharacterData | DS4CreatureData;
|
||||||
|
|
||||||
type ActorType = keyof typeof DS4.i18n.actorTypes;
|
type ActorType = keyof typeof DS4.i18n.actorTypes;
|
||||||
|
|
||||||
interface DS4ActorDataHelper<T, U extends ActorType> extends Actor.Data<T, DS4ItemData> {
|
export interface DS4ActorDataHelper<T, U extends ActorType> extends Actor.Data<T, DS4ItemData> {
|
||||||
type: U;
|
type: U;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DS4CharacterData = DS4ActorDataHelper<DS4CharacterDataData, "character">;
|
type DS4CharacterData = DS4ActorDataHelper<DS4CharacterDataData, "character">;
|
||||||
type DS4CreatureData = DS4ActorDataHelper<DS4CreatureDataData, "creature">;
|
type DS4CreatureData = DS4ActorDataHelper<DS4CreatureDataData, "creature">;
|
||||||
|
|
||||||
|
// templates
|
||||||
|
|
||||||
interface DS4ActorDataDataBase {
|
interface DS4ActorDataDataBase {
|
||||||
attributes: DS4ActorDataDataAttributes;
|
attributes: DS4ActorDataDataAttributes;
|
||||||
traits: DS4ActorDataDataTraits;
|
traits: DS4ActorDataDataTraits;
|
||||||
combatValues: DS4ActorDataDataCombatValues;
|
combatValues: DS4ActorDataDataCombatValues;
|
||||||
rolling: DS4ActorDataDataRolling;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4ActorDataDataAttributes {
|
interface DS4ActorDataDataAttributes {
|
||||||
body: ModifiableData<number>;
|
body: ModifiableDataBase<number>;
|
||||||
mobility: ModifiableData<number>;
|
mobility: ModifiableDataBase<number>;
|
||||||
mind: ModifiableData<number>;
|
mind: ModifiableDataBase<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4ActorDataDataTraits {
|
interface DS4ActorDataDataTraits {
|
||||||
strength: ModifiableData<number>;
|
strength: ModifiableDataBase<number>;
|
||||||
constitution: ModifiableData<number>;
|
constitution: ModifiableDataBase<number>;
|
||||||
agility: ModifiableData<number>;
|
agility: ModifiableDataBase<number>;
|
||||||
dexterity: ModifiableData<number>;
|
dexterity: ModifiableDataBase<number>;
|
||||||
intellect: ModifiableData<number>;
|
intellect: ModifiableDataBase<number>;
|
||||||
aura: ModifiableData<number>;
|
aura: ModifiableDataBase<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4ActorDataDataCombatValues {
|
interface DS4ActorDataDataCombatValues {
|
||||||
|
@ -46,10 +47,7 @@ interface DS4ActorDataDataCombatValues {
|
||||||
targetedSpellcasting: ModifiableData<number>;
|
targetedSpellcasting: ModifiableData<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4ActorDataDataRolling {
|
// types
|
||||||
maximumCoupResult?: number;
|
|
||||||
minimumFumbleResult?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4CharacterDataData extends DS4ActorDataDataBase {
|
interface DS4CharacterDataData extends DS4ActorDataDataBase {
|
||||||
baseInfo: DS4CharacterDataDataBaseInfo;
|
baseInfo: DS4CharacterDataDataBaseInfo;
|
||||||
|
@ -58,25 +56,25 @@ interface DS4CharacterDataData extends DS4ActorDataDataBase {
|
||||||
profile: DS4CharacterDataDataProfile;
|
profile: DS4CharacterDataDataProfile;
|
||||||
currency: DS4CharacterDataDataCurrency;
|
currency: DS4CharacterDataDataCurrency;
|
||||||
}
|
}
|
||||||
interface DS4CharacterDataDataBaseInfo {
|
export interface DS4CharacterDataDataBaseInfo {
|
||||||
race: string;
|
race: string;
|
||||||
class: string;
|
class: string;
|
||||||
heroClass: string;
|
heroClass: string;
|
||||||
culture: string;
|
culture: string;
|
||||||
}
|
}
|
||||||
interface DS4CharacterDataDataProgression {
|
export interface DS4CharacterDataDataProgression {
|
||||||
level: number;
|
level: number;
|
||||||
experiencePoints: number;
|
experiencePoints: number;
|
||||||
talentPoints: UsableResource<number>;
|
talentPoints: UsableResource<number>;
|
||||||
progressPoints: UsableResource<number>;
|
progressPoints: UsableResource<number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4CharacterDataDataLanguage {
|
export interface DS4CharacterDataDataLanguage {
|
||||||
languages: string;
|
languages: string;
|
||||||
alphabets: string;
|
alphabets: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4CharacterDataDataProfile {
|
export interface DS4CharacterDataDataProfile {
|
||||||
biography: string;
|
biography: string;
|
||||||
gender: string;
|
gender: string;
|
||||||
birthday: string;
|
birthday: string;
|
||||||
|
@ -89,7 +87,7 @@ interface DS4CharacterDataDataProfile {
|
||||||
specialCharacteristics: string;
|
specialCharacteristics: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4CharacterDataDataCurrency {
|
export interface DS4CharacterDataDataCurrency {
|
||||||
gold: number;
|
gold: number;
|
||||||
silver: number;
|
silver: number;
|
||||||
copper: number;
|
copper: number;
|
||||||
|
@ -99,11 +97,7 @@ interface DS4CreatureDataData extends DS4ActorDataDataBase {
|
||||||
baseInfo: DS4CreatureDataDataBaseInfo;
|
baseInfo: DS4CreatureDataDataBaseInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead";
|
export interface DS4CreatureDataDataBaseInfo {
|
||||||
|
|
||||||
type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal";
|
|
||||||
|
|
||||||
interface DS4CreatureDataDataBaseInfo {
|
|
||||||
loot: string;
|
loot: string;
|
||||||
foeFactor: number;
|
foeFactor: number;
|
||||||
creatureType: CreatureType;
|
creatureType: CreatureType;
|
||||||
|
@ -111,3 +105,7 @@ interface DS4CreatureDataDataBaseInfo {
|
||||||
experiencePoints: number;
|
experiencePoints: number;
|
||||||
description: string;
|
description: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CreatureType = "animal" | "construct" | "humanoid" | "magicalEntity" | "plantBeing" | "undead";
|
||||||
|
|
||||||
|
type SizeCategory = "tiny" | "small" | "normal" | "large" | "huge" | "colossal";
|
||||||
|
|
69
src/module/actor/actor-prepared-data.ts
Normal file
69
src/module/actor/actor-prepared-data.ts
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
import { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from "../common/common-data";
|
||||||
|
import {
|
||||||
|
DS4ActorDataHelper,
|
||||||
|
DS4CharacterDataDataBaseInfo,
|
||||||
|
DS4CharacterDataDataCurrency,
|
||||||
|
DS4CharacterDataDataLanguage,
|
||||||
|
DS4CharacterDataDataProfile,
|
||||||
|
DS4CharacterDataDataProgression,
|
||||||
|
DS4CreatureDataDataBaseInfo,
|
||||||
|
} from "./actor-data";
|
||||||
|
|
||||||
|
export type DS4ActorPreparedData = DS4CharacterPreparedData | DS4CreaturePreparedData;
|
||||||
|
|
||||||
|
type DS4CharacterPreparedData = DS4ActorDataHelper<DS4CharacterPreparedDataData, "character">;
|
||||||
|
type DS4CreaturePreparedData = DS4ActorDataHelper<DS4CreaturePreparedDataData, "creature">;
|
||||||
|
|
||||||
|
// templates
|
||||||
|
|
||||||
|
interface DS4ActorPreparedDataDataBase {
|
||||||
|
attributes: DS4ActorPreparedDataDataAttributes;
|
||||||
|
traits: DS4ActorPreparedDataDataTraits;
|
||||||
|
combatValues: DS4ActorPreparedDataDataCombatValues;
|
||||||
|
rolling: DS4ActorPreparedDataDataRolling;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4ActorPreparedDataDataAttributes {
|
||||||
|
body: ModifiableDataBaseTotal<number>;
|
||||||
|
mobility: ModifiableDataBaseTotal<number>;
|
||||||
|
mind: ModifiableDataBaseTotal<number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4ActorPreparedDataDataTraits {
|
||||||
|
strength: ModifiableDataBaseTotal<number>;
|
||||||
|
constitution: ModifiableDataBaseTotal<number>;
|
||||||
|
agility: ModifiableDataBaseTotal<number>;
|
||||||
|
dexterity: ModifiableDataBaseTotal<number>;
|
||||||
|
intellect: ModifiableDataBaseTotal<number>;
|
||||||
|
aura: ModifiableDataBaseTotal<number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4ActorPreparedDataDataCombatValues {
|
||||||
|
hitPoints: ResourceDataBaseTotalMax<number>;
|
||||||
|
defense: ModifiableDataBaseTotal<number>;
|
||||||
|
initiative: ModifiableDataBaseTotal<number>;
|
||||||
|
movement: ModifiableDataBaseTotal<number>;
|
||||||
|
meleeAttack: ModifiableDataBaseTotal<number>;
|
||||||
|
rangedAttack: ModifiableDataBaseTotal<number>;
|
||||||
|
spellcasting: ModifiableDataBaseTotal<number>;
|
||||||
|
targetedSpellcasting: ModifiableDataBaseTotal<number>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4ActorPreparedDataDataRolling {
|
||||||
|
maximumCoupResult: number;
|
||||||
|
minimumFumbleResult: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
interface DS4CharacterPreparedDataData extends DS4ActorPreparedDataDataBase {
|
||||||
|
baseInfo: DS4CharacterDataDataBaseInfo;
|
||||||
|
progression: DS4CharacterDataDataProgression;
|
||||||
|
language: DS4CharacterDataDataLanguage;
|
||||||
|
profile: DS4CharacterDataDataProfile;
|
||||||
|
currency: DS4CharacterDataDataCurrency;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4CreaturePreparedDataData extends DS4ActorPreparedDataDataBase {
|
||||||
|
baseInfo: DS4CreatureDataDataBaseInfo;
|
||||||
|
}
|
|
@ -1,16 +1,17 @@
|
||||||
import { ModifiableData } from "../common/common-data";
|
import { ModifiableDataBaseTotal } from "../common/common-data";
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from "../config";
|
||||||
import { DS4Item } from "../item/item";
|
import { DS4Item } from "../item/item";
|
||||||
import { ItemType } from "../item/item-data";
|
import { ItemType } from "../item/item-data";
|
||||||
import { DS4ActorData } from "./actor-data";
|
import { DS4ActorData } from "./actor-data";
|
||||||
|
import { DS4ActorPreparedData } from "./actor-prepared-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Actor class for DS4
|
* The Actor class for DS4
|
||||||
*/
|
*/
|
||||||
export class DS4Actor extends Actor<DS4ActorData, DS4Item> {
|
export class DS4Actor extends Actor<DS4ActorData, DS4Item, DS4ActorPreparedData> {
|
||||||
/** @override */
|
/** @override */
|
||||||
prepareData(): void {
|
prepareData(): void {
|
||||||
this.data = duplicate(this._data) as DS4ActorData;
|
this.data = duplicate(this._data) as DS4ActorPreparedData;
|
||||||
if (!this.data.img) this.data.img = CONST.DEFAULT_TOKEN;
|
if (!this.data.img) this.data.img = CONST.DEFAULT_TOKEN;
|
||||||
if (!this.data.name) this.data.name = "New " + this.entity;
|
if (!this.data.name) this.data.name = "New " + this.entity;
|
||||||
this.prepareBaseData();
|
this.prepareBaseData();
|
||||||
|
@ -32,11 +33,13 @@ export class DS4Actor extends Actor<DS4ActorData, DS4Item> {
|
||||||
|
|
||||||
const attributes = data.data.attributes;
|
const attributes = data.data.attributes;
|
||||||
Object.values(attributes).forEach(
|
Object.values(attributes).forEach(
|
||||||
(attribute: ModifiableData<number>) => (attribute.total = attribute.base + attribute.mod),
|
(attribute: ModifiableDataBaseTotal<number>) => (attribute.total = attribute.base + attribute.mod),
|
||||||
);
|
);
|
||||||
|
|
||||||
const traits = data.data.traits;
|
const traits = data.data.traits;
|
||||||
Object.values(traits).forEach((trait: ModifiableData<number>) => (trait.total = trait.base + trait.mod));
|
Object.values(traits).forEach(
|
||||||
|
(trait: ModifiableDataBaseTotal<number>) => (trait.total = trait.base + trait.mod),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
applyActiveEffectsToBaseData(): void {
|
applyActiveEffectsToBaseData(): void {
|
||||||
|
@ -72,7 +75,7 @@ export class DS4Actor extends Actor<DS4ActorData, DS4Item> {
|
||||||
|
|
||||||
return changes.concat(
|
return changes.concat(
|
||||||
e.data.changes.filter(predicate).flatMap((c) => {
|
e.data.changes.filter(predicate).flatMap((c) => {
|
||||||
const duplicatedChange = duplicate(c) as ActiveEffect.Change;
|
const duplicatedChange = duplicate(c);
|
||||||
duplicatedChange.priority = duplicatedChange.priority ?? duplicatedChange.mode * 10;
|
duplicatedChange.priority = duplicatedChange.priority ?? duplicatedChange.mode * 10;
|
||||||
return Array(factor).fill({
|
return Array(factor).fill({
|
||||||
...duplicatedChange,
|
...duplicatedChange,
|
||||||
|
@ -169,22 +172,20 @@ export class DS4Actor extends Actor<DS4ActorData, DS4Item> {
|
||||||
const data = this.data.data;
|
const data = this.data.data;
|
||||||
const armorValueOfEquippedItems = this._calculateArmorValueOfEquippedItems();
|
const armorValueOfEquippedItems = this._calculateArmorValueOfEquippedItems();
|
||||||
|
|
||||||
data.combatValues.hitPoints.base =
|
data.combatValues.hitPoints.base = data.attributes.body.total + data.traits.constitution.total + 10;
|
||||||
(data.attributes.body.total ?? 0) + (data.traits.constitution.total ?? 0) + 10;
|
|
||||||
data.combatValues.defense.base =
|
data.combatValues.defense.base =
|
||||||
(data.attributes.body.total ?? 0) + (data.traits.constitution.total ?? 0) + armorValueOfEquippedItems;
|
data.attributes.body.total + data.traits.constitution.total + armorValueOfEquippedItems;
|
||||||
data.combatValues.initiative.base = (data.attributes.mobility.total ?? 0) + (data.traits.agility.total ?? 0);
|
data.combatValues.initiative.base = data.attributes.mobility.total + data.traits.agility.total;
|
||||||
data.combatValues.movement.base = (data.attributes.mobility.total ?? 0) / 2 + 1;
|
data.combatValues.movement.base = data.attributes.mobility.total / 2 + 1;
|
||||||
data.combatValues.meleeAttack.base = (data.attributes.body.total ?? 0) + (data.traits.strength.total ?? 0);
|
data.combatValues.meleeAttack.base = data.attributes.body.total + data.traits.strength.total;
|
||||||
data.combatValues.rangedAttack.base =
|
data.combatValues.rangedAttack.base = data.attributes.mobility.total + data.traits.dexterity.total;
|
||||||
(data.attributes.mobility.total ?? 0) + (data.traits.dexterity.total ?? 0);
|
|
||||||
data.combatValues.spellcasting.base =
|
data.combatValues.spellcasting.base =
|
||||||
(data.attributes.mind.total ?? 0) + (data.traits.aura.total ?? 0) - armorValueOfEquippedItems;
|
data.attributes.mind.total + data.traits.aura.total - armorValueOfEquippedItems;
|
||||||
data.combatValues.targetedSpellcasting.base =
|
data.combatValues.targetedSpellcasting.base =
|
||||||
(data.attributes.mind.total ?? 0) + (data.traits.dexterity.total ?? 0) - armorValueOfEquippedItems;
|
data.attributes.mind.total + data.traits.dexterity.total - armorValueOfEquippedItems;
|
||||||
|
|
||||||
Object.values(data.combatValues).forEach(
|
Object.values(data.combatValues).forEach(
|
||||||
(combatValue: ModifiableData<number>) => (combatValue.total = combatValue.base + combatValue.mod),
|
(combatValue: ModifiableDataBaseTotal<number>) => (combatValue.total = combatValue.base + combatValue.mod),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ModifiableMaybeData } from "../../common/common-data";
|
import { ModifiableDataBaseTotal } from "../../common/common-data";
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from "../../config";
|
||||||
import { DS4Item } from "../../item/item";
|
import { DS4Item } from "../../item/item";
|
||||||
import { DS4ItemData } from "../../item/item-data";
|
import { DS4ItemData } from "../../item/item-data";
|
||||||
|
@ -75,17 +75,16 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
|
||||||
|
|
||||||
protected _addTooltipsToData(data: ActorSheet.Data<DS4Actor>): ActorSheet.Data<DS4Actor> {
|
protected _addTooltipsToData(data: ActorSheet.Data<DS4Actor>): ActorSheet.Data<DS4Actor> {
|
||||||
const valueGroups = [data.data.attributes, data.data.traits, data.data.combatValues];
|
const valueGroups = [data.data.attributes, data.data.traits, data.data.combatValues];
|
||||||
|
|
||||||
valueGroups.forEach((valueGroup) => {
|
valueGroups.forEach((valueGroup) => {
|
||||||
Object.values(valueGroup).forEach(
|
Object.values(valueGroup).forEach((attribute: ModifiableDataBaseTotal<number> & { tooltip?: string }) => {
|
||||||
(attribute: ModifiableMaybeData<number | null> & { tooltip?: string }) => {
|
attribute.tooltip = this._getTooltipForValue(attribute);
|
||||||
attribute.tooltip = this._getTooltipForValue(attribute);
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _getTooltipForValue(value: ModifiableMaybeData<number | null>): string {
|
protected _getTooltipForValue(value: ModifiableDataBaseTotal<number>): string {
|
||||||
return `${value.base} (${game.i18n.localize("DS4.TooltipBaseValue")}) + ${value.mod} (${game.i18n.localize(
|
return `${value.base} (${game.i18n.localize("DS4.TooltipBaseValue")}) + ${value.mod} (${game.i18n.localize(
|
||||||
"DS4.TooltipModifier",
|
"DS4.TooltipModifier",
|
||||||
)}) ➞ ${game.i18n.localize("DS4.TooltipEffects")} ➞ ${value.total}`;
|
)}) ➞ ${game.i18n.localize("DS4.TooltipEffects")} ➞ ${value.total}`;
|
||||||
|
@ -160,7 +159,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Data<DS4Actor>> {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
const el: HTMLFormElement = $(ev.currentTarget).get(0);
|
const el: HTMLFormElement = $(ev.currentTarget).get(0);
|
||||||
const id = $(ev.currentTarget).parents(".item").data("itemId");
|
const id = $(ev.currentTarget).parents(".item").data("itemId");
|
||||||
const item = duplicate<DS4Item, "lenient">(this.actor.getOwnedItem(id));
|
const item = duplicate(this.actor.getOwnedItem(id));
|
||||||
const property: string | undefined = $(ev.currentTarget).data("property");
|
const property: string | undefined = $(ev.currentTarget).data("property");
|
||||||
|
|
||||||
// Early return:
|
// Early return:
|
||||||
|
|
|
@ -1,20 +1,30 @@
|
||||||
export interface ModifiableData<T> {
|
export interface ModifiableData<T> {
|
||||||
|
mod: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HasBase<T> {
|
||||||
base: T;
|
base: T;
|
||||||
mod: T;
|
}
|
||||||
total?: T;
|
export interface ModifiableDataBase<T> extends ModifiableData<T>, HasBase<T> {}
|
||||||
|
|
||||||
|
export interface HasTotal<T> {
|
||||||
|
total: T;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModifiableMaybeData<T> {
|
export interface ModifiableDataTotal<T> extends ModifiableData<T>, HasTotal<T> {}
|
||||||
base?: T;
|
|
||||||
mod: T;
|
|
||||||
total?: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ResourceData<T> extends ModifiableMaybeData<T> {
|
export interface ModifiableDataBaseTotal<T> extends ModifiableDataBase<T>, HasTotal<T> {}
|
||||||
|
|
||||||
|
export interface ResourceData<T> extends ModifiableData<T> {
|
||||||
value: T;
|
value: T;
|
||||||
max?: T;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface HasMax<T> {
|
||||||
|
max: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ResourceDataBaseTotalMax<T> extends ResourceData<T>, HasBase<T>, HasTotal<T>, HasMax<T> {}
|
||||||
|
|
||||||
export interface UsableResource<T> {
|
export interface UsableResource<T> {
|
||||||
total: T;
|
total: T;
|
||||||
used: T;
|
used: T;
|
||||||
|
|
6
src/module/global.d.ts
vendored
Normal file
6
src/module/global.d.ts
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
declare namespace ClientSettings {
|
||||||
|
interface Values {
|
||||||
|
"ds4.systemMigrationVersion": number;
|
||||||
|
"ds4.useSlayingDiceForAutomatedChecks": boolean;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import { ModifiableData } from "../common/common-data";
|
import { ModifiableDataBase } from "../common/common-data";
|
||||||
import { DS4 } from "../config";
|
import { DS4 } from "../config";
|
||||||
|
|
||||||
export type ItemType = keyof typeof DS4.i18n.itemTypes;
|
export type ItemType = keyof typeof DS4.i18n.itemTypes;
|
||||||
|
@ -16,7 +16,7 @@ export type DS4ItemData =
|
||||||
| DS4AlphabetData
|
| DS4AlphabetData
|
||||||
| DS4SpecialCreatureAbilityData;
|
| DS4SpecialCreatureAbilityData;
|
||||||
|
|
||||||
interface DS4ItemDataHelper<T, U extends ItemType> extends Item.Data<T> {
|
export interface DS4ItemDataHelper<T, U extends ItemType> extends Item.Data<T> {
|
||||||
type: U;
|
type: U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,69 +32,6 @@ type DS4LanguageData = DS4ItemDataHelper<DS4LanguageDataData, "language">;
|
||||||
type DS4AlphabetData = DS4ItemDataHelper<DS4AlphabetDataData, "alphabet">;
|
type DS4AlphabetData = DS4ItemDataHelper<DS4AlphabetDataData, "alphabet">;
|
||||||
type DS4SpecialCreatureAbilityData = DS4ItemDataHelper<DS4SpecialCreatureAbilityDataData, "specialCreatureAbility">;
|
type DS4SpecialCreatureAbilityData = DS4ItemDataHelper<DS4SpecialCreatureAbilityDataData, "specialCreatureAbility">;
|
||||||
|
|
||||||
export type AttackType = keyof typeof DS4["i18n"]["attackTypes"];
|
|
||||||
|
|
||||||
interface DS4WeaponDataData
|
|
||||||
extends DS4ItemDataDataBase,
|
|
||||||
DS4ItemDataDataPhysical,
|
|
||||||
DS4ItemDataDataEquipable,
|
|
||||||
DS4ItemDataDataRollable {
|
|
||||||
attackType: AttackType;
|
|
||||||
weaponBonus: number;
|
|
||||||
opponentDefense: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4ArmorDataData
|
|
||||||
extends DS4ItemDataDataBase,
|
|
||||||
DS4ItemDataDataPhysical,
|
|
||||||
DS4ItemDataDataEquipable,
|
|
||||||
DS4ItemDataDataProtective {
|
|
||||||
armorMaterialType: "cloth" | "leather" | "chain" | "plate";
|
|
||||||
armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4TalentDataData extends DS4ItemDataDataBase {
|
|
||||||
rank: DS4TalentRank;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4TalentRank extends ModifiableData<number> {
|
|
||||||
max: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable, DS4ItemDataDataRollable {
|
|
||||||
spellType: "spellcasting" | "targetedSpellcasting";
|
|
||||||
bonus: string;
|
|
||||||
spellCategory:
|
|
||||||
| "healing"
|
|
||||||
| "fire"
|
|
||||||
| "ice"
|
|
||||||
| "light"
|
|
||||||
| "darkness"
|
|
||||||
| "mindAffecting"
|
|
||||||
| "electricity"
|
|
||||||
| "none"
|
|
||||||
| "unset";
|
|
||||||
maxDistance: UnitData<DistanceUnit>;
|
|
||||||
effectRadius: UnitData<DistanceUnit>;
|
|
||||||
duration: UnitData<TemporalUnit>;
|
|
||||||
cooldownDuration: UnitData<TemporalUnit>;
|
|
||||||
scrollPrice: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4ShieldDataData
|
|
||||||
extends DS4ItemDataDataBase,
|
|
||||||
DS4ItemDataDataPhysical,
|
|
||||||
DS4ItemDataDataEquipable,
|
|
||||||
DS4ItemDataDataProtective {}
|
|
||||||
interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {}
|
|
||||||
interface DS4LootDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {}
|
|
||||||
type DS4RacialAbilityDataData = DS4ItemDataDataBase;
|
|
||||||
type DS4LanguageDataData = DS4ItemDataDataBase;
|
|
||||||
type DS4AlphabetDataData = DS4ItemDataDataBase;
|
|
||||||
interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase {
|
|
||||||
experiencePoints: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
// templates
|
// templates
|
||||||
|
|
||||||
interface DS4ItemDataDataBase {
|
interface DS4ItemDataDataBase {
|
||||||
|
@ -115,10 +52,6 @@ interface DS4ItemDataDataEquipable {
|
||||||
equipped: boolean;
|
equipped: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DS4ItemDataDataRollable {
|
|
||||||
rollable?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface DS4ItemDataDataProtective {
|
interface DS4ItemDataDataProtective {
|
||||||
armorValue: number;
|
armorValue: number;
|
||||||
}
|
}
|
||||||
|
@ -129,3 +62,70 @@ interface UnitData<UnitType> {
|
||||||
}
|
}
|
||||||
type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom";
|
type TemporalUnit = "rounds" | "minutes" | "hours" | "days" | "custom";
|
||||||
type DistanceUnit = "meter" | "kilometer" | "custom";
|
type DistanceUnit = "meter" | "kilometer" | "custom";
|
||||||
|
|
||||||
|
// types
|
||||||
|
|
||||||
|
export interface DS4WeaponDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {
|
||||||
|
attackType: AttackType;
|
||||||
|
weaponBonus: number;
|
||||||
|
opponentDefense: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AttackType = keyof typeof DS4["i18n"]["attackTypes"];
|
||||||
|
|
||||||
|
export interface DS4ArmorDataData
|
||||||
|
extends DS4ItemDataDataBase,
|
||||||
|
DS4ItemDataDataPhysical,
|
||||||
|
DS4ItemDataDataEquipable,
|
||||||
|
DS4ItemDataDataProtective {
|
||||||
|
armorMaterialType: "cloth" | "leather" | "chain" | "plate";
|
||||||
|
armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DS4TalentDataData extends DS4ItemDataDataBase {
|
||||||
|
rank: DS4TalentRank;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DS4TalentRank extends ModifiableDataBase<number> {
|
||||||
|
max: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DS4SpellDataData extends DS4ItemDataDataBase, DS4ItemDataDataEquipable {
|
||||||
|
spellType: "spellcasting" | "targetedSpellcasting";
|
||||||
|
bonus: string;
|
||||||
|
spellCategory:
|
||||||
|
| "healing"
|
||||||
|
| "fire"
|
||||||
|
| "ice"
|
||||||
|
| "light"
|
||||||
|
| "darkness"
|
||||||
|
| "mindAffecting"
|
||||||
|
| "electricity"
|
||||||
|
| "none"
|
||||||
|
| "unset";
|
||||||
|
maxDistance: UnitData<DistanceUnit>;
|
||||||
|
effectRadius: UnitData<DistanceUnit>;
|
||||||
|
duration: UnitData<TemporalUnit>;
|
||||||
|
cooldownDuration: UnitData<TemporalUnit>;
|
||||||
|
scrollPrice: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DS4ShieldDataData
|
||||||
|
extends DS4ItemDataDataBase,
|
||||||
|
DS4ItemDataDataPhysical,
|
||||||
|
DS4ItemDataDataEquipable,
|
||||||
|
DS4ItemDataDataProtective {}
|
||||||
|
|
||||||
|
export interface DS4EquipmentDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical, DS4ItemDataDataEquipable {}
|
||||||
|
|
||||||
|
export interface DS4LootDataData extends DS4ItemDataDataBase, DS4ItemDataDataPhysical {}
|
||||||
|
|
||||||
|
export type DS4RacialAbilityDataData = DS4ItemDataDataBase;
|
||||||
|
|
||||||
|
export type DS4LanguageDataData = DS4ItemDataDataBase;
|
||||||
|
|
||||||
|
export type DS4AlphabetDataData = DS4ItemDataDataBase;
|
||||||
|
|
||||||
|
export interface DS4SpecialCreatureAbilityDataData extends DS4ItemDataDataBase {
|
||||||
|
experiencePoints: number;
|
||||||
|
}
|
||||||
|
|
80
src/module/item/item-prepared-data.ts
Normal file
80
src/module/item/item-prepared-data.ts
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
import { HasTotal } from "../common/common-data";
|
||||||
|
import {
|
||||||
|
DS4AlphabetDataData,
|
||||||
|
DS4ArmorDataData,
|
||||||
|
DS4EquipmentDataData,
|
||||||
|
DS4ItemDataHelper,
|
||||||
|
DS4LanguageDataData,
|
||||||
|
DS4LootDataData,
|
||||||
|
DS4RacialAbilityDataData,
|
||||||
|
DS4ShieldDataData,
|
||||||
|
DS4SpecialCreatureAbilityDataData,
|
||||||
|
DS4SpellDataData,
|
||||||
|
DS4TalentDataData,
|
||||||
|
DS4TalentRank,
|
||||||
|
DS4WeaponDataData,
|
||||||
|
} from "./item-data";
|
||||||
|
|
||||||
|
export type DS4ItemPreparedData =
|
||||||
|
| DS4WeaponPreparedData
|
||||||
|
| DS4ArmorPreparedData
|
||||||
|
| DS4ShieldPreparedData
|
||||||
|
| DS4SpellPreparedData
|
||||||
|
| DS4EquipmentPreparedData
|
||||||
|
| DS4LootPreparedData
|
||||||
|
| DS4TalentPreparedData
|
||||||
|
| DS4RacialAbilityPreparedData
|
||||||
|
| DS4LanguagePreparedData
|
||||||
|
| DS4AlphabetPreparedData
|
||||||
|
| DS4SpecialCreatureAbilityPreparedData;
|
||||||
|
|
||||||
|
type DS4WeaponPreparedData = DS4ItemDataHelper<DS4WeaponPreparedDataData, "weapon">;
|
||||||
|
type DS4ArmorPreparedData = DS4ItemDataHelper<DS4ArmorPreparedDataData, "armor">;
|
||||||
|
type DS4ShieldPreparedData = DS4ItemDataHelper<DS4ShieldPreparedDataData, "shield">;
|
||||||
|
type DS4SpellPreparedData = DS4ItemDataHelper<DS4SpellPreparedDataData, "spell">;
|
||||||
|
type DS4EquipmentPreparedData = DS4ItemDataHelper<DS4EquipmentPreparedDataData, "equipment">;
|
||||||
|
type DS4LootPreparedData = DS4ItemDataHelper<DS4LootPreparedDataData, "loot">;
|
||||||
|
type DS4TalentPreparedData = DS4ItemDataHelper<DS4TalentPreparedDataData, "talent">;
|
||||||
|
type DS4RacialAbilityPreparedData = DS4ItemDataHelper<DS4RacialAbilityPreparedDataData, "racialAbility">;
|
||||||
|
type DS4LanguagePreparedData = DS4ItemDataHelper<DS4LanguagePreparedDataData, "language">;
|
||||||
|
type DS4AlphabetPreparedData = DS4ItemDataHelper<DS4AlphabetPreparedDataData, "alphabet">;
|
||||||
|
type DS4SpecialCreatureAbilityPreparedData = DS4ItemDataHelper<
|
||||||
|
DS4SpecialCreatureAbilityPreparedDataData,
|
||||||
|
"specialCreatureAbility"
|
||||||
|
>;
|
||||||
|
|
||||||
|
// templates
|
||||||
|
|
||||||
|
interface DS4ItemPreparedDataDataRollable {
|
||||||
|
rollable: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
//types
|
||||||
|
|
||||||
|
interface DS4WeaponPreparedDataData extends DS4WeaponDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4ArmorPreparedDataData extends DS4ArmorDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4ShieldPreparedDataData extends DS4ShieldDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4SpellPreparedDataData extends DS4SpellDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4EquipmentPreparedDataData extends DS4EquipmentDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4LootPreparedDataData extends DS4LootDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4TalentPreparedDataData extends DS4TalentDataData, DS4ItemPreparedDataDataRollable {
|
||||||
|
rank: DS4TalentPreparedRank;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface DS4TalentPreparedRank extends DS4TalentRank, HasTotal<number> {}
|
||||||
|
|
||||||
|
interface DS4RacialAbilityPreparedDataData extends DS4RacialAbilityDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4LanguagePreparedDataData extends DS4LanguageDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4AlphabetPreparedDataData extends DS4AlphabetDataData, DS4ItemPreparedDataDataRollable {}
|
||||||
|
|
||||||
|
interface DS4SpecialCreatureAbilityPreparedDataData
|
||||||
|
extends DS4SpecialCreatureAbilityDataData,
|
||||||
|
DS4ItemPreparedDataDataRollable {}
|
|
@ -3,11 +3,12 @@ import { DS4 } from "../config";
|
||||||
import { createCheckRoll } from "../rolls/check-factory";
|
import { createCheckRoll } from "../rolls/check-factory";
|
||||||
import notifications from "../ui/notifications";
|
import notifications from "../ui/notifications";
|
||||||
import { AttackType, DS4ItemData, ItemType } from "./item-data";
|
import { AttackType, DS4ItemData, ItemType } from "./item-data";
|
||||||
|
import { DS4ItemPreparedData } from "./item-prepared-data";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Item class for DS4
|
* The Item class for DS4
|
||||||
*/
|
*/
|
||||||
export class DS4Item extends Item<DS4ItemData> {
|
export class DS4Item extends Item<DS4ItemData, DS4ItemPreparedData> {
|
||||||
/**
|
/**
|
||||||
* @override
|
* @override
|
||||||
*/
|
*/
|
||||||
|
@ -23,6 +24,8 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
}
|
}
|
||||||
if (this.data.type === "weapon" || this.data.type === "spell") {
|
if (this.data.type === "weapon" || this.data.type === "spell") {
|
||||||
this.data.data.rollable = this.data.data.equipped;
|
this.data.data.rollable = this.data.data.equipped;
|
||||||
|
} else {
|
||||||
|
this.data.data.rollable = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,10 +94,10 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
const ownerDataData = actor.data.data;
|
const ownerDataData = actor.data.data;
|
||||||
const weaponBonus = this.data.data.weaponBonus;
|
const weaponBonus = this.data.data.weaponBonus;
|
||||||
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
const combatValue = await this.getCombatValueKeyForAttackType(this.data.data.attackType);
|
||||||
const checkTargetNumber = (ownerDataData.combatValues[combatValue].total as number) + weaponBonus;
|
const checkTargetNumber = ownerDataData.combatValues[combatValue].total + weaponBonus;
|
||||||
|
|
||||||
await createCheckRoll(checkTargetNumber, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream
|
||||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||||
flavor: game.i18n.format("DS4.ItemWeaponCheckFlavor", { actor: actor.name, weapon: this.name }),
|
flavor: game.i18n.format("DS4.ItemWeaponCheckFlavor", { actor: actor.name, weapon: this.name }),
|
||||||
|
@ -135,10 +138,10 @@ export class DS4Item extends Item<DS4ItemData> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const spellType = this.data.data.spellType;
|
const spellType = this.data.data.spellType;
|
||||||
const checkTargetNumber = (ownerDataData.combatValues[spellType].total as number) + (spellBonus ?? 0);
|
const checkTargetNumber = ownerDataData.combatValues[spellType].total + (spellBonus ?? 0);
|
||||||
|
|
||||||
await createCheckRoll(checkTargetNumber, {
|
await createCheckRoll(checkTargetNumber, {
|
||||||
rollMode: game.settings.get("core", "rollMode"),
|
rollMode: game.settings.get("core", "rollMode") as Const.DiceRollMode, // TODO(types): Type this setting in upstream
|
||||||
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
maximumCoupResult: ownerDataData.rolling.maximumCoupResult,
|
||||||
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
minimumFumbleResult: ownerDataData.rolling.minimumFumbleResult,
|
||||||
flavor: game.i18n.format("DS4.ItemSpellCheckFlavor", { actor: actor.name, spell: this.name }),
|
flavor: game.i18n.format("DS4.ItemSpellCheckFlavor", { actor: actor.name, spell: this.name }),
|
||||||
|
|
|
@ -9,7 +9,7 @@ async function migrate(): Promise<void> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const oldMigrationVersion: number = game.settings.get("ds4", "systemMigrationVersion");
|
const oldMigrationVersion = game.settings.get("ds4", "systemMigrationVersion");
|
||||||
|
|
||||||
const targetMigrationVersion = migrations.length;
|
const targetMigrationVersion = migrations.length;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ export async function createCheckRoll(
|
||||||
const newOptions: Partial<DS4CheckFactoryOptions> = {
|
const newOptions: Partial<DS4CheckFactoryOptions> = {
|
||||||
maximumCoupResult: gmModifierData.maximumCoupResult ?? options.maximumCoupResult,
|
maximumCoupResult: gmModifierData.maximumCoupResult ?? options.maximumCoupResult,
|
||||||
minimumFumbleResult: gmModifierData.minimumFumbleResult ?? options.minimumFumbleResult,
|
minimumFumbleResult: gmModifierData.minimumFumbleResult ?? options.minimumFumbleResult,
|
||||||
useSlayingDice: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks") ?? false,
|
useSlayingDice: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
|
||||||
rollMode: gmModifierData.rollMode ?? options.rollMode,
|
rollMode: gmModifierData.rollMode ?? options.rollMode,
|
||||||
flavor: options.flavor,
|
flavor: options.flavor,
|
||||||
};
|
};
|
||||||
|
|
10
yarn.lock
10
yarn.lock
|
@ -647,9 +647,9 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@league-of-foundry-developers/foundry-vtt-types@npm:^0.7.9-3":
|
"@league-of-foundry-developers/foundry-vtt-types@npm:^0.7.9-4":
|
||||||
version: 0.7.9-3
|
version: 0.7.9-4
|
||||||
resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.7.9-3"
|
resolution: "@league-of-foundry-developers/foundry-vtt-types@npm:0.7.9-4"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/howler": 2.2.1
|
"@types/howler": 2.2.1
|
||||||
"@types/jquery": 3.5.1
|
"@types/jquery": 3.5.1
|
||||||
|
@ -659,7 +659,7 @@ __metadata:
|
||||||
pixi.js: 5.3.4
|
pixi.js: 5.3.4
|
||||||
tinymce: 5.6.2
|
tinymce: 5.6.2
|
||||||
typescript: ^4.1.4
|
typescript: ^4.1.4
|
||||||
checksum: 75524c7aa78ddb77cad1a9d041af30ae5bbd708f5b26568dabbb3d913a4643aefcc6f2ed80e1e76b3c17050579665eab155f035f840db6397691cf68eeee9b3f
|
checksum: 9aeee3d49c20dd69e736abd50347e43f5cfdcfdca7fba5af9fb321250cc3ca78758daed14fe6328005f3b606ed0ace49bf2562d7262912c1461132718ab793b8
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -2891,7 +2891,7 @@ __metadata:
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "dungeonslayers4@workspace:."
|
resolution: "dungeonslayers4@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@league-of-foundry-developers/foundry-vtt-types": ^0.7.9-3
|
"@league-of-foundry-developers/foundry-vtt-types": ^0.7.9-4
|
||||||
"@rollup/plugin-node-resolve": ^11.2.0
|
"@rollup/plugin-node-resolve": ^11.2.0
|
||||||
"@types/fs-extra": ^9.0.8
|
"@types/fs-extra": ^9.0.8
|
||||||
"@types/jest": ^26.0.20
|
"@types/jest": ^26.0.20
|
||||||
|
|
Loading…
Reference in a new issue