In the Active Effect Config, there are now additional inputs to configure the effect to be applied to items owned by the actor instead of the actor itself. It is possible to select the items to which to apply the effect via matching by name, or via a condition expression, that provides similar capabilities as the evaluation of mathematical expressions in rolls. Data from the Actor, Item, and Active Effect can be accessed similar to how properties are accessed in roll formulas (using the prefixes `@actor`, `@item`, and `@effect`). For example, in order to apply an effect to all ranged weapons, the conditions would be ```js '@item.type' === 'weapon' && '@item.data.attackType' === 'ranged' ```
90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
|
// SPDX-FileCopyrightText: 2021 Gesina Schwalbe
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { getGame } from "../helpers";
|
|
|
|
import type { ItemType } from "./item-data-source";
|
|
|
|
declare global {
|
|
interface DocumentClassConfig {
|
|
Item: typeof DS4Item;
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-namespace
|
|
namespace Hooks {
|
|
interface StaticCallbacks {
|
|
"ds4.rollItem": (item: DS4Item) => void;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The Item class for DS4
|
|
*/
|
|
export class DS4Item extends Item {
|
|
/** An object that tracks the changes to the data model which were applied by active effects */
|
|
overrides: Record<string, unknown> = {};
|
|
|
|
override prepareData() {
|
|
this.data.reset();
|
|
this.prepareBaseData();
|
|
this.prepareEmbeddedDocuments();
|
|
this.prepareDerivedData();
|
|
this.applyActiveEffects();
|
|
}
|
|
|
|
applyActiveEffects(): void {
|
|
if (!this.actor?.initialized) {
|
|
return;
|
|
}
|
|
|
|
this.overrides = {};
|
|
const overrides: Record<string, unknown> = {};
|
|
|
|
// Organize non-disabled and -surpressed effects by their application priority
|
|
const changesWithEffect = this.actor?.itemEffects(this).flatMap((e) => e.getFactoredChangesWithEffect()) ?? [];
|
|
changesWithEffect.sort((a, b) => (a.change.priority ?? 0) - (b.change.priority ?? 0));
|
|
|
|
// Apply all changes
|
|
for (const changeWithEffect of changesWithEffect) {
|
|
const result = changeWithEffect.effect.apply(this, changeWithEffect.change);
|
|
if (result !== null) overrides[changeWithEffect.change.key] = result;
|
|
}
|
|
|
|
// Expand the set of final overrides
|
|
this.overrides = foundry.utils.expandObject({ ...foundry.utils.flattenObject(this.overrides), ...overrides });
|
|
}
|
|
|
|
override prepareDerivedData(): void {
|
|
this.data.data.rollable = false;
|
|
}
|
|
|
|
isNonEquippedEuipable(): boolean {
|
|
return "equipped" in this.data.data && !this.data.data.equipped;
|
|
}
|
|
|
|
/**
|
|
* The number of times that active effect changes originating from this item should be applied.
|
|
*/
|
|
get activeEffectFactor(): number | undefined {
|
|
return 1;
|
|
}
|
|
|
|
/**
|
|
* The list of item types that are rollable.
|
|
*/
|
|
static get rollableItemTypes(): ItemType[] {
|
|
return ["weapon", "spell"];
|
|
}
|
|
|
|
/**
|
|
* Roll a check for an action with this item.
|
|
* @param options - Additional options to customize the roll
|
|
*/
|
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
async roll(options: { speaker?: { token?: TokenDocument; alias?: string } } = {}): Promise<void> {
|
|
throw new Error(getGame().i18n.format("DS4.ErrorRollingForItemTypeNotPossible", { type: this.data.type }));
|
|
}
|
|
}
|