forked from foundryvtt/pf2e
-
Notifications
You must be signed in to change notification settings - Fork 0
/
damage.ts
115 lines (104 loc) · 5.29 KB
/
damage.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
import { WeaponTrait } from "@item/weapon/types.ts";
import { immunityTypes, resistanceTypes, weaknessTypes } from "@scripts/config/iwr.ts";
import { DamageType } from "@system/damage/types.ts";
import {
BASE_DAMAGE_TYPES_TO_CATEGORIES,
DAMAGE_TYPES,
DAMAGE_TYPE_ICONS,
ENERGY_DAMAGE_TYPES,
PHYSICAL_DAMAGE_TYPES,
} from "@system/damage/values.ts";
import { ErrorPF2e, sluggify, tupleHasValue } from "@util";
import * as R from "remeda";
import { CustomDamageData } from "./data.ts";
import { isHomebrewCustomDamage } from "./helpers.ts";
import { HomebrewElements } from "./menu.ts";
/**
* To update all custom damage types in the system, we need to ensure that all collections are added to and cleaned.
* This reduces the scope of all damage related operations so that its easier to identify when something goes wrong.
*/
export class DamageTypeManager {
// All collections that homebrew damage must be updated in
collections = {
physical: PHYSICAL_DAMAGE_TYPES as unknown as string[],
energy: ENERGY_DAMAGE_TYPES as unknown as string[],
DAMAGE_TYPES,
BASE_DAMAGE_TYPES_TO_CATEGORIES,
DAMAGE_TYPE_ICONS,
damageTypesLocalization: CONFIG.PF2E.damageTypes,
damageRollFlavorsLocalization: CONFIG.PF2E.damageRollFlavors,
immunityTypes: immunityTypes as Record<string, string>,
weaknessTypes: weaknessTypes as Record<string, string>,
resistanceTypes: resistanceTypes as Record<string, string>,
};
addCustomDamage(data: CustomDamageData, options: { slug?: string } = {}): void {
const collections = this.collections;
const slug = (options.slug ?? sluggify(data.label)) as DamageType;
collections.DAMAGE_TYPES.add(slug);
if (tupleHasValue(["physical", "energy"], data.category)) {
collections[data.category].push(slug);
}
collections.BASE_DAMAGE_TYPES_TO_CATEGORIES[slug] = data.category ?? null;
collections.DAMAGE_TYPE_ICONS[slug] = data.icon?.substring(3) ?? null; // icons registered do not include the fa-
collections.damageTypesLocalization[slug] = data.label;
const versatileLabel = game.i18n.format("PF2E.TraitVersatileX", { x: data.label });
CONFIG.PF2E.weaponTraits[`versatile-${slug}` as WeaponTrait] = versatileLabel;
CONFIG.PF2E.npcAttackTraits[`versatile-${slug}` as WeaponTrait] = versatileLabel;
const damageFlavor = game.i18n.localize(data.label).toLocaleLowerCase(game.i18n.lang);
collections.damageRollFlavorsLocalization[slug] = damageFlavor;
collections.immunityTypes[slug] = damageFlavor;
collections.weaknessTypes[slug] = damageFlavor;
collections.resistanceTypes[slug] = damageFlavor;
}
updateSettings(): void {
const reservedTerms = HomebrewElements.reservedTerms;
// Delete all existing homebrew damage types first
const typesToDelete: Set<string> = DAMAGE_TYPES.filter((t) => !reservedTerms.damageTypes.has(t));
for (const collection of Object.values(this.collections)) {
if (collection instanceof Set) {
const types = [...collection].filter((t) => typesToDelete.has(t));
for (const damageType of types) collection.delete(damageType);
} else {
const types = Object.keys(collection).filter((t): t is keyof typeof collection => typesToDelete.has(t));
for (const damageType of types) delete collection[damageType];
}
}
// Delete versatile damage traits
for (const type of typesToDelete) {
const weaponTraits: Record<string, string> = CONFIG.PF2E.weaponTraits;
const npcAttackTraits: Record<string, string> = CONFIG.PF2E.npcAttackTraits;
delete weaponTraits[`versatile-${type}`];
delete npcAttackTraits[`versatile-${type}`];
}
// Read module damage types
const activeModules = [...game.modules.entries()].filter(([_key, foundryModule]) => foundryModule.active);
for (const [key, foundryModule] of activeModules) {
const homebrew = foundryModule.flags[key]?.["pf2e-homebrew"];
if (!R.isPlainObject(homebrew) || !homebrew.damageTypes) continue;
const elements = homebrew.damageTypes;
if (!R.isPlainObject(elements) || !isHomebrewCustomDamage(elements)) {
console.warn(ErrorPF2e(`Homebrew record damageTypes is malformed in module ${key}`).message);
continue;
}
for (const [slug, data] of Object.entries(elements)) {
if (!reservedTerms.damageTypes.has(slug)) {
this.addCustomDamage(data, { slug });
} else {
console.warn(
ErrorPF2e(
`Homebrew damage type "${slug}" from module ${foundryModule.title} is a reserved term.`,
).message,
);
continue;
}
}
}
// Read setting damage types
const customTypes = game.settings
.get("pf2e", "homebrew.damageTypes")
.filter((t) => !reservedTerms.damageTypes.has(sluggify(t.label)));
for (const data of customTypes) {
this.addCustomDamage(data);
}
}
}