refactor: use subclasses for different actor types

This commit is contained in:
Johannes Loher 2022-02-16 13:32:04 +01:00
parent 21f849b464
commit be616e3be8
23 changed files with 321 additions and 240 deletions

View file

@ -0,0 +1,44 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
// SPDX-FileCopyrightText: 2021 Oliver Rümpelein
// SPDX-FileCopyrightText: 2021 Gesina Schwalbe
// SPDX-FileCopyrightText: 2021 Siegfried Krug
//
// SPDX-License-Identifier: MIT
import { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from "../common/common-data";
import { DS4 } from "../config";
export interface DS4ActorDataPropertiesDataBase {
attributes: DS4ActorDataPropertiesDataAttributes;
traits: DS4ActorDataPropertiesDataTraits;
combatValues: DS4ActorDataPropertiesDataCombatValues;
rolling: DS4ActorDataPropertiesDataRolling;
checks: DS4ActorDataPropertiesDataChecks;
}
type DS4ActorDataPropertiesDataAttributes = {
[Key in keyof typeof DS4.i18n.attributes]: ModifiableDataBaseTotal<number>;
};
type DS4ActorDataPropertiesDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBaseTotal<number> };
type DS4ActorDataPropertiesDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
? ResourceDataBaseTotalMax<number>
: ModifiableDataBaseTotal<number>;
};
interface DS4ActorDataPropertiesDataRolling {
maximumCoupResult: number;
minimumFumbleResult: number;
}
type DS4ActorDataPropertiesDataChecks = {
[key in Check]: number;
};
export type Check = keyof typeof DS4.i18n.checks;
export function isCheck(value: string): value is Check {
return Object.keys(DS4.i18n.checks).includes(value);
}

View file

@ -1,17 +1,9 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { ModifiableDataBaseTotal, ResourceDataBaseTotalMax } from "../common/common-data";
import { DS4 } from "../config";
import {
DS4CharacterDataSourceDataBaseInfo,
DS4CharacterDataSourceDataCurrency,
DS4CharacterDataSourceDataProfile,
DS4CharacterDataSourceDataProgression,
DS4CharacterDataSourceDataSlayerPoints,
DS4CreatureDataSourceDataBaseInfo,
} from "./actor-data-source";
import { DS4CharacterDataProperties } from "./character/character-data-properties";
import { DS4CreatureDataProperties } from "./creature/creature-data-properties";
declare global {
interface DataConfig {
@ -20,68 +12,3 @@ declare global {
}
export type DS4ActorDataProperties = DS4CharacterDataProperties | DS4CreatureDataProperties;
interface DS4CharacterDataProperties {
type: "character";
data: DS4CharacterDataPropertiesData;
}
interface DS4CreatureDataProperties {
type: "creature";
data: DS4CreatureDataPropertiesData;
}
// templates
interface DS4ActorDataPropertiesDataBase {
attributes: DS4ActorDataPropertiesDataAttributes;
traits: DS4ActorDataPropertiesDataTraits;
combatValues: DS4ActorDataPropertiesDataCombatValues;
rolling: DS4ActorDataPropertiesDataRolling;
checks: DS4ActorDataPropertiesDataChecks;
}
type DS4ActorDataPropertiesDataAttributes = {
[Key in keyof typeof DS4.i18n.attributes]: ModifiableDataBaseTotal<number>;
};
type DS4ActorDataPropertiesDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBaseTotal<number> };
type DS4ActorDataPropertiesDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
? ResourceDataBaseTotalMax<number>
: ModifiableDataBaseTotal<number>;
};
interface DS4ActorDataPropertiesDataRolling {
maximumCoupResult: number;
minimumFumbleResult: number;
}
type DS4ActorDataPropertiesDataChecks = {
[key in Check]: number;
};
export type Check = keyof typeof DS4.i18n.checks;
export function isCheck(value: string): value is Check {
return Object.keys(DS4.i18n.checks).includes(value);
}
// types
interface DS4CreatureDataPropertiesData extends DS4ActorDataPropertiesDataBase {
baseInfo: DS4CreatureDataSourceDataBaseInfo;
}
interface DS4CharacterDataPropertiesData extends DS4ActorDataPropertiesDataBase {
baseInfo: DS4CharacterDataSourceDataBaseInfo;
progression: DS4CharacterDataSourceDataProgression;
profile: DS4CharacterDataSourceDataProfile;
currency: DS4CharacterDataSourceDataCurrency;
slayerPoints: DS4CharacterDataPropertiesDataSlayerPoints;
}
export interface DS4CharacterDataPropertiesDataSlayerPoints extends DS4CharacterDataSourceDataSlayerPoints {
max: number;
}

View file

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
// SPDX-FileCopyrightText: 2021 Oliver Rümpelein
// SPDX-FileCopyrightText: 2021 Gesina Schwalbe
// SPDX-FileCopyrightText: 2021 Siegfried Krug
//
// SPDX-License-Identifier: MIT
import { ModifiableData, ModifiableDataBase, ResourceData } from "../common/common-data";
import { DS4 } from "../config";
export interface DS4ActorDataSourceDataBase {
attributes: DS4ActorDataSourceDataAttributes;
traits: DS4ActorDataSourceDataTraits;
combatValues: DS4ActorDataSourceDataCombatValues;
}
type DS4ActorDataSourceDataAttributes = { [Key in keyof typeof DS4.i18n.attributes]: ModifiableDataBase<number> };
type Attribute = keyof DS4ActorDataSourceDataAttributes;
export function isAttribute(value: unknown): value is Attribute {
return (Object.keys(DS4.i18n.attributes) as Array<unknown>).includes(value);
}
type DS4ActorDataSourceDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBase<number> };
type Trait = keyof DS4ActorDataSourceDataTraits;
export function isTrait(value: unknown): value is Trait {
return (Object.keys(DS4.i18n.traits) as Array<unknown>).includes(value);
}
type DS4ActorDataSourceDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
? ResourceData<number>
: ModifiableData<number>;
};
type CombatValue = keyof DS4ActorDataSourceDataCombatValues;
export function isCombatValue(value: string): value is CombatValue {
return (Object.keys(DS4.i18n.combatValues) as Array<unknown>).includes(value);
}

View file

@ -1,12 +1,9 @@
// SPDX-FileCopyrightText: 2021 Johannes Loher
// SPDX-FileCopyrightText: 2021 Oliver Rümpelein
// SPDX-FileCopyrightText: 2021 Gesina Schwalbe
// SPDX-FileCopyrightText: 2021 Siegfried Krug
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { ModifiableData, ModifiableDataBase, ResourceData, UsableResource } from "../common/common-data";
import { DS4 } from "../config";
import { DS4CharacterDataSource } from "./character/character-data-source";
import { DS4CreatureDataSource } from "./creature/creature-data-source";
declare global {
interface SourceConfig {
@ -15,111 +12,3 @@ declare global {
}
export type DS4ActorDataSource = DS4CharacterDataSource | DS4CreatureDataSource;
interface DS4CharacterDataSource {
type: "character";
data: DS4CharacterDataSourceData;
}
interface DS4CreatureDataSource {
type: "creature";
data: DS4CreatureDataSourceData;
}
// templates
interface DS4ActorDataSourceDataBase {
attributes: DS4ActorDataSourceDataAttributes;
traits: DS4ActorDataSourceDataTraits;
combatValues: DS4ActorDataSourceDataCombatValues;
}
type DS4ActorDataSourceDataAttributes = { [Key in keyof typeof DS4.i18n.attributes]: ModifiableDataBase<number> };
type Attribute = keyof DS4ActorDataSourceDataAttributes;
export function isAttribute(value: unknown): value is Attribute {
return (Object.keys(DS4.i18n.attributes) as Array<unknown>).includes(value);
}
type DS4ActorDataSourceDataTraits = { [Key in keyof typeof DS4.i18n.traits]: ModifiableDataBase<number> };
type Trait = keyof DS4ActorDataSourceDataTraits;
export function isTrait(value: unknown): value is Trait {
return (Object.keys(DS4.i18n.traits) as Array<unknown>).includes(value);
}
type DS4ActorDataSourceDataCombatValues = {
[Key in keyof typeof DS4.i18n.combatValues]: Key extends "hitPoints"
? ResourceData<number>
: ModifiableData<number>;
};
type CombatValue = keyof DS4ActorDataSourceDataCombatValues;
export function isCombatValue(value: string): value is CombatValue {
return (Object.keys(DS4.i18n.combatValues) as Array<unknown>).includes(value);
}
// types
interface DS4CreatureDataSourceData extends DS4ActorDataSourceDataBase {
baseInfo: DS4CreatureDataSourceDataBaseInfo;
}
export interface DS4CreatureDataSourceDataBaseInfo {
loot: string;
foeFactor: number;
creatureType: CreatureType;
sizeCategory: SizeCategory;
experiencePoints: number;
description: string;
}
type CreatureType = keyof typeof DS4.i18n.creatureTypes;
type SizeCategory = keyof typeof DS4.i18n.creatureSizeCategories;
interface DS4CharacterDataSourceData extends DS4ActorDataSourceDataBase {
baseInfo: DS4CharacterDataSourceDataBaseInfo;
progression: DS4CharacterDataSourceDataProgression;
profile: DS4CharacterDataSourceDataProfile;
currency: DS4CharacterDataSourceDataCurrency;
slayerPoints: DS4CharacterDataSourceDataSlayerPoints;
}
export interface DS4CharacterDataSourceDataBaseInfo {
race: string;
class: string;
heroClass: string;
culture: string;
}
export interface DS4CharacterDataSourceDataProgression {
level: number;
experiencePoints: number;
talentPoints: UsableResource<number>;
progressPoints: UsableResource<number>;
}
export interface DS4CharacterDataSourceDataProfile {
biography: string;
gender: string;
birthday: string;
birthplace: string;
age: number;
height: number;
hairColor: string;
weight: number;
eyeColor: string;
specialCharacteristics: string;
}
export interface DS4CharacterDataSourceDataCurrency {
gold: number;
silver: number;
copper: number;
}
export interface DS4CharacterDataSourceDataSlayerPoints {
value: number;
}

View file

@ -5,16 +5,16 @@
//
// SPDX-License-Identifier: MIT
import { DS4ActiveEffect } from "../../active-effect";
import { ModifiableDataBaseTotal } from "../../common/common-data";
import { DS4 } from "../../config";
import { getCanvas, getGame } from "../../helpers";
import type { DS4Item } from "../../item/item";
import { DS4Settings, getDS4Settings } from "../../settings";
import notifications from "../../ui/notifications";
import { enforce } from "../../utils";
import { isCheck } from "../actor-data-properties";
import { DS4ActiveEffect } from "../active-effect";
import { ModifiableDataBaseTotal } from "../common/common-data";
import { DS4 } from "../config";
import { getCanvas, getGame } from "../helpers";
import { DS4Settings, getDS4Settings } from "../settings";
import notifications from "../ui/notifications";
import { enforce } from "../utils";
import { isCheck } from "./actor-data-properties-base";
import type { DS4Item } from "../item/item";
/**
* The base sheet class for all {@link DS4Actor}s.
*/

View file

@ -10,8 +10,8 @@ import { DS4Item } from "../item/item";
import { DS4ArmorDataProperties, DS4ShieldDataProperties } from "../item/item-data-properties";
import { ItemType } from "../item/item-data-source";
import { createCheckRoll } from "../rolls/check-factory";
import { Check } from "./actor-data-properties";
import { isAttribute, isTrait } from "./actor-data-source";
import { Check } from "./actor-data-properties-base";
import { isAttribute, isTrait } from "./actor-data-source-base";
declare global {
interface DocumentClassConfig {
@ -157,9 +157,6 @@ export class DS4Actor extends Actor {
this.data.data.combatValues.hitPoints.max = this.data.data.combatValues.hitPoints.total;
this.data.data.checks.defend = this.data.data.combatValues.defense.total;
if (this.data.type === "character") {
this.data.data.slayerPoints.max = 3;
}
}
/**
@ -167,32 +164,14 @@ export class DS4Actor extends Actor {
* given in dot notation.
*/
get finalDerivedDataProperties(): string[] {
return ["data.combatValues.hitPoints.max", "data.checks.defend"].concat(
this.data.type === "character" ? ["data.slayerPoints.max"] : [],
);
return ["data.combatValues.hitPoints.max", "data.checks.defend"];
}
/**
* The list of item types that can be owned by this actor.
*/
get ownableItemTypes(): Array<ItemType> {
switch (this.data.type) {
case "character":
return [
"weapon",
"armor",
"shield",
"equipment",
"loot",
"spell",
"talent",
"racialAbility",
"language",
"alphabet",
];
case "creature":
return ["weapon", "armor", "shield", "equipment", "loot", "spell", "specialCreatureAbility"];
}
return ["weapon", "armor", "shield", "equipment", "loot", "spell"];
}
/**

View file

@ -0,0 +1,29 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
import {
DS4CharacterDataSourceDataBaseInfo,
DS4CharacterDataSourceDataCurrency,
DS4CharacterDataSourceDataProfile,
DS4CharacterDataSourceDataProgression,
DS4CharacterDataSourceDataSlayerPoints,
} from "./character-data-source";
export interface DS4CharacterDataProperties {
type: "character";
data: DS4CharacterDataPropertiesData;
}
interface DS4CharacterDataPropertiesData extends DS4ActorDataPropertiesDataBase {
baseInfo: DS4CharacterDataSourceDataBaseInfo;
progression: DS4CharacterDataSourceDataProgression;
profile: DS4CharacterDataSourceDataProfile;
currency: DS4CharacterDataSourceDataCurrency;
slayerPoints: DS4CharacterDataPropertiesDataSlayerPoints;
}
export interface DS4CharacterDataPropertiesDataSlayerPoints extends DS4CharacterDataSourceDataSlayerPoints {
max: number;
}

View file

@ -0,0 +1,56 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { UsableResource } from "../../common/common-data";
import { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
export interface DS4CharacterDataSource {
type: "character";
data: DS4CharacterDataSourceData;
}
interface DS4CharacterDataSourceData extends DS4ActorDataSourceDataBase {
baseInfo: DS4CharacterDataSourceDataBaseInfo;
progression: DS4CharacterDataSourceDataProgression;
profile: DS4CharacterDataSourceDataProfile;
currency: DS4CharacterDataSourceDataCurrency;
slayerPoints: DS4CharacterDataSourceDataSlayerPoints;
}
export interface DS4CharacterDataSourceDataBaseInfo {
race: string;
class: string;
heroClass: string;
culture: string;
}
export interface DS4CharacterDataSourceDataProgression {
level: number;
experiencePoints: number;
talentPoints: UsableResource<number>;
progressPoints: UsableResource<number>;
}
export interface DS4CharacterDataSourceDataProfile {
biography: string;
gender: string;
birthday: string;
birthplace: string;
age: number;
height: number;
hairColor: string;
weight: number;
eyeColor: string;
specialCharacteristics: string;
}
export interface DS4CharacterDataSourceDataCurrency {
gold: number;
silver: number;
copper: number;
}
export interface DS4CharacterDataSourceDataSlayerPoints {
value: number;
}

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4ActorSheet } from "./actor-sheet";
import { DS4ActorSheet } from "../actor-sheet";
/**
* The Sheet class for DS4 Character Actors

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { ItemType } from "../../item/item-data-source";
import { DS4Actor } from "../actor";
export class DS4Character extends DS4Actor {
/** @override */
prepareFinalDerivedData(): void {
super.prepareFinalDerivedData();
this.data.data.slayerPoints.max = 3;
}
/** @override */
get finalDerivedDataProperties(): string[] {
return [...super.finalDerivedDataProperties, "data.slayerPoints.max"];
}
/** @override */
get ownableItemTypes(): Array<ItemType> {
return [...super.ownableItemTypes, "talent", "racialAbility", "language", "alphabet"];
}
}
export interface DS4Character {
data: foundry.data.ActorData & { type: "character"; _source: { type: "character" } };
}

View file

@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { DS4ActorDataPropertiesDataBase } from "../actor-data-properties-base";
import { DS4CreatureDataSourceDataBaseInfo } from "./creature-data-source";
export interface DS4CreatureDataProperties {
type: "creature";
data: DS4CreatureDataPropertiesData;
}
interface DS4CreatureDataPropertiesData extends DS4ActorDataPropertiesDataBase {
baseInfo: DS4CreatureDataSourceDataBaseInfo;
}

View file

@ -0,0 +1,28 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { DS4 } from "../../config";
import { DS4ActorDataSourceDataBase } from "../actor-data-source-base";
export interface DS4CreatureDataSource {
type: "creature";
data: DS4CreatureDataSourceData;
}
interface DS4CreatureDataSourceData extends DS4ActorDataSourceDataBase {
baseInfo: DS4CreatureDataSourceDataBaseInfo;
}
export interface DS4CreatureDataSourceDataBaseInfo {
loot: string;
foeFactor: number;
creatureType: CreatureType;
sizeCategory: SizeCategory;
experiencePoints: number;
description: string;
}
type CreatureType = keyof typeof DS4.i18n.creatureTypes;
type SizeCategory = keyof typeof DS4.i18n.creatureSizeCategories;

View file

@ -2,7 +2,7 @@
//
// SPDX-License-Identifier: MIT
import { DS4ActorSheet } from "./actor-sheet";
import { DS4ActorSheet } from "../actor-sheet";
/**
* The Sheet class for DS4 Creature Actors

View file

@ -0,0 +1,17 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { ItemType } from "../../item/item-data-source";
import { DS4Actor } from "../actor";
export class DS4Creature extends DS4Actor {
/** @override */
get ownableItemTypes(): Array<ItemType> {
return [...super.ownableItemTypes, "specialCreatureAbility"];
}
}
export interface DS4Creature {
data: foundry.data.ActorData & { type: "creature"; _source: { type: "creature" } };
}

23
src/actor/proxy.ts Normal file
View file

@ -0,0 +1,23 @@
// SPDX-FileCopyrightText: 2022 Johannes Loher
//
// SPDX-License-Identifier: MIT
import { getGame } from "../helpers";
import { DS4Actor } from "./actor";
import { DS4Character } from "./character/character";
import { DS4Creature } from "./creature/creature";
const handler = {
construct(_: typeof DS4Actor, args: ConstructorParameters<typeof DS4Actor>) {
switch (args[0]?.type) {
case "character":
return new DS4Character(...args);
case "creature":
return new DS4Creature(...args);
default:
throw new Error(getGame().i18n.format("DS4.ErrorInvalidActorType", { type: args[0]?.type }));
}
},
};
export const DS4ActorProxy: typeof DS4Actor = new Proxy(DS4Actor, handler);