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' ```
149 lines
5 KiB
TypeScript
149 lines
5 KiB
TypeScript
// SPDX-FileCopyrightText: 2021 Johannes Loher
|
|
// SPDX-FileCopyrightText: 2021 Oliver Rümpelein
|
|
// SPDX-FileCopyrightText: 2021 Gesina Schwalbe
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
import { DS4ActiveEffect } from "../active-effect/active-effect";
|
|
import { disableOverriddenFields } from "../apps/sheet-helpers";
|
|
import { DS4 } from "../config";
|
|
import { getGame } from "../helpers";
|
|
import notifications from "../ui/notifications";
|
|
import { enforce } from "../utils";
|
|
import { isDS4ItemDataTypePhysical } from "./item-data-source-base";
|
|
|
|
/**
|
|
* The Sheet class for DS4 Items
|
|
*/
|
|
export class DS4ItemSheet extends ItemSheet<ItemSheet.Options, DS4ItemSheetData> {
|
|
static override get defaultOptions(): ItemSheet.Options {
|
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
classes: ["sheet", "ds4-item-sheet"],
|
|
height: 400,
|
|
scrollY: [".ds4-sheet-body"],
|
|
tabs: [{ navSelector: ".ds4-sheet-tab-nav", contentSelector: ".ds4-sheet-body", initial: "description" }],
|
|
width: 540,
|
|
});
|
|
}
|
|
|
|
override get template(): string {
|
|
const basePath = "systems/ds4/templates/sheets/item";
|
|
return `${basePath}/${this.item.data.type}-sheet.hbs`;
|
|
}
|
|
|
|
override async getData(): Promise<DS4ItemSheetData> {
|
|
const data = {
|
|
...(await super.getData()),
|
|
config: DS4,
|
|
isOwned: this.item.isOwned,
|
|
actor: this.item.actor,
|
|
isPhysical: isDS4ItemDataTypePhysical(this.item.data.data),
|
|
};
|
|
return data;
|
|
}
|
|
|
|
override _getSubmitData(updateData = {}) {
|
|
const data = super._getSubmitData(updateData);
|
|
// Prevent submitting overridden values
|
|
const overrides = foundry.utils.flattenObject(this.item.overrides);
|
|
for (const k of Object.keys(overrides)) {
|
|
delete data[k];
|
|
}
|
|
return data;
|
|
}
|
|
|
|
override setPosition(
|
|
options: Partial<Application.Position> = {},
|
|
): (Application.Position & { height: number }) | void {
|
|
const position = super.setPosition(options);
|
|
if (position) {
|
|
const sheetBody = this.element.find(".sheet-body");
|
|
const bodyHeight = position.height - 192;
|
|
sheetBody.css("height", bodyHeight);
|
|
}
|
|
|
|
return position;
|
|
}
|
|
|
|
override activateListeners(html: JQuery): void {
|
|
super.activateListeners(html);
|
|
|
|
if (!this.options.editable) return;
|
|
|
|
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
|
|
|
|
disableOverriddenFields.call(this);
|
|
}
|
|
|
|
/**
|
|
* Handles a click on an element of this sheet to control an embedded effect of the item corresponding to this
|
|
* sheet.
|
|
*
|
|
* @param event - The originating click event
|
|
*/
|
|
protected onControlEffect(event: JQuery.ClickEvent): void {
|
|
event.preventDefault();
|
|
if (this.item.isOwned) {
|
|
return notifications.warn(getGame().i18n.localize("DS4.WarningManageActiveEffectOnOwnedItem"));
|
|
}
|
|
const a = event.currentTarget;
|
|
switch (a.dataset["action"]) {
|
|
case "create":
|
|
return this.onCreateEffect();
|
|
case "edit":
|
|
return this.onEditEffect(event);
|
|
case "delete":
|
|
return this.onDeleteEffect(event);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new embedded effect.
|
|
*/
|
|
protected onCreateEffect(): void {
|
|
DS4ActiveEffect.createDefault(this.item);
|
|
}
|
|
|
|
/**
|
|
* Opens the sheet of the embedded effect corresponding to the clicked element.
|
|
*
|
|
* @param event - The originating click event
|
|
*/
|
|
protected onEditEffect(event: JQuery.ClickEvent): void {
|
|
const id = $(event.currentTarget)
|
|
.parents(embeddedDocumentListEntryProperties.ActiveEffect.selector)
|
|
.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
|
const effect = this.item.effects.get(id);
|
|
enforce(effect, getGame().i18n.format("DS4.ErrorItemDoesNotHaveEffect", { id, item: this.item.name }));
|
|
effect.sheet?.render(true);
|
|
}
|
|
|
|
/**
|
|
* Deletes the embedded item corresponding to the clicked element.
|
|
*
|
|
* @param event - The originating click event
|
|
*/
|
|
protected onDeleteEffect(event: JQuery.ClickEvent): void {
|
|
const li = $(event.currentTarget).parents(embeddedDocumentListEntryProperties.ActiveEffect.selector);
|
|
const id = li.data(embeddedDocumentListEntryProperties.ActiveEffect.idDataAttribute);
|
|
this.item.deleteEmbeddedDocuments("ActiveEffect", [id]);
|
|
li.slideUp(200, () => this.render(false));
|
|
}
|
|
}
|
|
|
|
interface DS4ItemSheetData extends ItemSheet.Data<ItemSheet.Options> {
|
|
config: typeof DS4;
|
|
isOwned: boolean;
|
|
actor: DS4ItemSheet["item"]["actor"];
|
|
isPhysical: boolean;
|
|
}
|
|
|
|
/**
|
|
* This object contains information about specific properties embedded document list entries for each different type.
|
|
*/
|
|
const embeddedDocumentListEntryProperties = Object.freeze({
|
|
ActiveEffect: {
|
|
selector: ".effect",
|
|
idDataAttribute: "effectId",
|
|
},
|
|
});
|