Clean up actor sheet
This commit is contained in:
parent
1f629f3468
commit
48620636df
12 changed files with 189 additions and 166 deletions
|
@ -8,13 +8,13 @@
|
||||||
import { ModifiableDataBaseTotal } from "../../common/common-data";
|
import { ModifiableDataBaseTotal } from "../../common/common-data";
|
||||||
import { DS4 } from "../../config";
|
import { DS4 } from "../../config";
|
||||||
import { getCanvas, getGame } from "../../helpers";
|
import { getCanvas, getGame } from "../../helpers";
|
||||||
import { DS4Item } from "../../item/item";
|
|
||||||
import { DS4Settings, getDS4Settings } from "../../settings";
|
import { DS4Settings, getDS4Settings } from "../../settings";
|
||||||
import notifications from "../../ui/notifications";
|
import notifications from "../../ui/notifications";
|
||||||
|
import { enforce } from "../../utils";
|
||||||
import { isCheck } from "../actor-data-properties";
|
import { isCheck } from "../actor-data-properties";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The base Sheet class for all DS4 Actors
|
* The base sheet class for all {@link DS4Actor}s.
|
||||||
*/
|
*/
|
||||||
export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetData> {
|
export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetData> {
|
||||||
/** @override */
|
/** @override */
|
||||||
|
@ -38,12 +38,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
return `${basePath}/${this.actor.data.type}-sheet.hbs`;
|
return `${basePath}/${this.actor.data.type}-sheet.hbs`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** @override */
|
||||||
* This method returns the data for the template of the actor sheet.
|
|
||||||
* It explicitly adds the items of the object sorted by type in the
|
|
||||||
* object itemsByType.
|
|
||||||
* @returns The data fed to the template of the actor sheet
|
|
||||||
*/
|
|
||||||
async getData(): Promise<DS4ActorSheetData> {
|
async getData(): Promise<DS4ActorSheetData> {
|
||||||
const itemsByType = Object.fromEntries(
|
const itemsByType = Object.fromEntries(
|
||||||
Object.entries(this.actor.itemTypes).map(([itemType, items]) => {
|
Object.entries(this.actor.itemTypes).map(([itemType, items]) => {
|
||||||
|
@ -69,6 +64,9 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds tooltips to the attributes, traits, and combatValues of the actor data of the given {@link ActorSheet.Data}.
|
||||||
|
*/
|
||||||
protected addTooltipsToData(data: ActorSheet.Data): ActorSheet.Data {
|
protected addTooltipsToData(data: ActorSheet.Data): ActorSheet.Data {
|
||||||
const valueGroups = [data.data.data.attributes, data.data.data.traits, data.data.data.combatValues];
|
const valueGroups = [data.data.data.attributes, data.data.data.traits, data.data.data.combatValues];
|
||||||
|
|
||||||
|
@ -80,6 +78,9 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a tooltip for a given attribute, trait, or combatValue.
|
||||||
|
*/
|
||||||
protected getTooltipForValue(value: ModifiableDataBaseTotal<number>): string {
|
protected getTooltipForValue(value: ModifiableDataBaseTotal<number>): string {
|
||||||
return `${value.base} (${getGame().i18n.localize("DS4.TooltipBaseValue")}) + ${
|
return `${value.base} (${getGame().i18n.localize("DS4.TooltipBaseValue")}) + ${
|
||||||
value.mod
|
value.mod
|
||||||
|
@ -92,151 +93,92 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
activateListeners(html: JQuery): void {
|
activateListeners(html: JQuery): void {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
// Add Inventory Item
|
html.find(".control-item").on("click", this.onControlItem.bind(this));
|
||||||
html.find(".item-create").on("click", this.onItemCreate.bind(this));
|
html.find(".change-item").on("change", this.onChangeItem.bind(this));
|
||||||
|
|
||||||
// Update Inventory Item
|
|
||||||
html.find(".item-edit").on("click", (ev) => {
|
|
||||||
const li = $(ev.currentTarget).parents(".item");
|
|
||||||
const id = li.data("itemId");
|
|
||||||
const item = this.actor.items.get(id);
|
|
||||||
if (!item) {
|
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
|
||||||
}
|
|
||||||
if (!item.sheet) {
|
|
||||||
throw new Error(getGame().i18n.localize("DS4.ErrorUnexpectedError"));
|
|
||||||
}
|
|
||||||
item.sheet.render(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete Inventory Item
|
|
||||||
html.find(".item-delete").on("click", (ev) => {
|
|
||||||
const li = $(ev.currentTarget).parents(".item");
|
|
||||||
this.actor.deleteEmbeddedDocuments("Item", [li.data("itemId")]);
|
|
||||||
li.slideUp(200, () => this.render(false));
|
|
||||||
});
|
|
||||||
|
|
||||||
html.find(".item-change").on("change", this.onItemChange.bind(this));
|
|
||||||
|
|
||||||
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
|
html.find(".control-effect").on("click", this.onControlEffect.bind(this));
|
||||||
html.find(".change-effect").on("change", this.onChangeEffect.bind(this));
|
html.find(".change-effect").on("change", this.onChangeEffect.bind(this));
|
||||||
|
|
||||||
html.find(".rollable-item").on("click", this.onRollItem.bind(this));
|
html.find(".rollable-item").on("click", this.onRollItem.bind(this));
|
||||||
|
|
||||||
html.find(".rollable-check").on("click", this.onRollCheck.bind(this));
|
html.find(".rollable-check").on("click", this.onRollCheck.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle creating a new embedded Item for the actor using initial data defined in the HTML dataset
|
* Handles a click on an element of this sheet to control an embedded item of the actor corresponding to this sheet.
|
||||||
|
*
|
||||||
* @param event - The originating click event
|
* @param event - The originating click event
|
||||||
*/
|
*/
|
||||||
protected onItemCreate(event: JQuery.ClickEvent): void {
|
protected onControlItem(event: JQuery.ClickEvent): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const header = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
|
switch (a.dataset["action"]) {
|
||||||
const { type, ...data } = foundry.utils.deepClone(header.dataset);
|
case "create":
|
||||||
|
return this.onCreateItem(event);
|
||||||
|
case "edit":
|
||||||
|
return this.onEditItem(event);
|
||||||
|
case "delete":
|
||||||
|
return this.onDeleteItem(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new embedded item using the initial data defined in the HTML dataset of the clicked element.
|
||||||
|
*
|
||||||
|
* @param event - The originating click event
|
||||||
|
*/
|
||||||
|
protected onCreateItem(event: JQuery.ClickEvent): void {
|
||||||
|
const { type, ...data } = foundry.utils.deepClone(event.currentTarget.dataset);
|
||||||
const name = getGame().i18n.localize(`DS4.New${type.capitalize()}Name`);
|
const name = getGame().i18n.localize(`DS4.New${type.capitalize()}Name`);
|
||||||
|
|
||||||
const itemData = {
|
const itemData = {
|
||||||
name: name,
|
name: name,
|
||||||
type: type,
|
type: type,
|
||||||
data: data,
|
data: data,
|
||||||
};
|
};
|
||||||
|
Item.create(itemData, { parent: this.actor });
|
||||||
DS4Item.create(itemData, { parent: this.actor });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle changes to properties of an Owned Item from within character sheet.
|
* Opens the sheet of the embedded item corresponding to the clicked element.
|
||||||
* Can currently properly bind: see getValue().
|
*
|
||||||
* Assumes the item property is given as the value of the HTML element property 'data-property'.
|
* @param event - The originating click event
|
||||||
* @param ev - The originating change event
|
|
||||||
*/
|
*/
|
||||||
protected onItemChange(ev: JQuery.ChangeEvent): void {
|
protected onEditItem(event: JQuery.ClickEvent): void {
|
||||||
ev.preventDefault();
|
const id = $(event.currentTarget).parents(".item").data("id");
|
||||||
const el: HTMLFormElement = $(ev.currentTarget).get(0);
|
|
||||||
const id = $(ev.currentTarget).parents(".item").data("itemId");
|
|
||||||
const item = this.actor.items.get(id);
|
const item = this.actor.items.get(id);
|
||||||
if (!item) {
|
enforce(item, getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
enforce(item.sheet);
|
||||||
}
|
item.sheet.render(true);
|
||||||
const itemObject = item.toObject();
|
|
||||||
const property: string | undefined = $(ev.currentTarget).data("property");
|
|
||||||
|
|
||||||
// Early return:
|
|
||||||
// Disabled => do nothing
|
|
||||||
if (el.disabled || el.getAttribute("disabled")) return;
|
|
||||||
// name not given => raise
|
|
||||||
if (property === undefined) {
|
|
||||||
throw TypeError("HTML element does not provide 'data-property' attribute");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set new value
|
|
||||||
const newValue = this.getValue(el);
|
|
||||||
foundry.utils.setProperty(itemObject, property, newValue);
|
|
||||||
item.update(itemObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Collect the value of a form element depending on the element's type
|
* Deletes the embedded item corresponding to the clicked element.
|
||||||
* The value is parsed to:
|
*
|
||||||
* - Checkbox: boolean
|
* @param event - The originating click event
|
||||||
* - Text input: string
|
|
||||||
* - Number: number
|
|
||||||
* @param el - The input element to collect the value of
|
|
||||||
* @param inverted - Whether or not the value should be inverted
|
|
||||||
*/
|
*/
|
||||||
private getValue(el: HTMLFormElement, inverted = false): boolean | string | number {
|
protected onDeleteItem(event: JQuery.ClickEvent): void {
|
||||||
// One needs to differentiate between e.g. checkboxes (value="on") and select boxes etc.
|
const li = $(event.currentTarget).parents(".item");
|
||||||
// Checkbox:
|
this.actor.deleteEmbeddedDocuments("Item", [li.data("id")]);
|
||||||
if (el.type === "checkbox") {
|
li.slideUp(200, () => this.render(false));
|
||||||
const value: boolean = el.checked;
|
|
||||||
return inverted ? !value : value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Text input:
|
/**
|
||||||
else if (el.type === "text") {
|
* Applies a change to a property of an embedded item depending on the `data-property` attribute of the
|
||||||
const value: string = el.value;
|
* {@link HTMLInputElement} that has been changed and its new value.
|
||||||
return value;
|
*
|
||||||
}
|
* @param event - The originating change event
|
||||||
|
*/
|
||||||
// Numbers:
|
protected onChangeItem(event: JQuery.ChangeEvent): void {
|
||||||
else if (el.type === "number") {
|
return this.onChangeEmbeddedDocument(event, ".item", "Item");
|
||||||
const value = Number(el.value.trim());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// // Ranges:
|
|
||||||
// else if (el.type === "range") {
|
|
||||||
// const value: string = el.value.trim();
|
|
||||||
// return value;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Radio Checkboxes (untested, cf. FormDataExtended.process)
|
|
||||||
// else if (el.type === "radio") {
|
|
||||||
// const chosen: HTMLFormElement = el.find((r: HTMLFormElement) => r["checked"]);
|
|
||||||
// const value: string = chosen ? chosen.value : null;
|
|
||||||
// return value;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Multi-Select (untested, cf. FormDataExtended.process)
|
|
||||||
// else if (el.type === "select-multiple") {
|
|
||||||
// const value: Array<string> = [];
|
|
||||||
// el.options.array.forEach((opt: HTMLOptionElement) => {
|
|
||||||
// if (opt.selected) value.push(opt.value);
|
|
||||||
// });
|
|
||||||
// return value;
|
|
||||||
|
|
||||||
// unsupported:
|
|
||||||
else {
|
|
||||||
throw new TypeError("Binding of item property to this type of HTML element not supported; given: " + el);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a click on an element of this sheet to control an embedded effect of the actor corresponding to this
|
||||||
|
* sheet.
|
||||||
|
*
|
||||||
|
* @param event - The originating click event
|
||||||
|
*/
|
||||||
protected onControlEffect(event: JQuery.ClickEvent): void {
|
protected onControlEffect(event: JQuery.ClickEvent): void {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const a = event.currentTarget;
|
const a = event.currentTarget;
|
||||||
|
@ -250,45 +192,115 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new embedded effect.
|
||||||
|
*
|
||||||
|
* @param event - The originating click event
|
||||||
|
*/
|
||||||
protected onCreateEffect(): void {
|
protected onCreateEffect(): void {
|
||||||
const createData = {
|
const effectData = {
|
||||||
label: getGame().i18n.localize(`DS4.NewEffectLabel`),
|
label: getGame().i18n.localize(`DS4.NewEffectLabel`),
|
||||||
icon: "icons/svg/aura.svg",
|
icon: "icons/svg/aura.svg",
|
||||||
origin: this.actor.uuid,
|
origin: this.actor.uuid,
|
||||||
};
|
};
|
||||||
ActiveEffect.create(createData, { parent: this.actor });
|
ActiveEffect.create(effectData, { parent: this.actor });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the sheet of the embedded effect corresponding to the clicked element.
|
||||||
|
*
|
||||||
|
* @param event - The originating click event
|
||||||
|
*/
|
||||||
protected onEditEffect(event: JQuery.ClickEvent): void {
|
protected onEditEffect(event: JQuery.ClickEvent): void {
|
||||||
const id = $(event.currentTarget).parents(".effect").data("effectId");
|
const id = $(event.currentTarget).parents(".effect").data("id");
|
||||||
const effect = this.actor.effects.get(id);
|
const effect = this.actor.effects.get(id);
|
||||||
if (!effect) {
|
enforce(effect, getGame().i18n.format("DS4.ErrorActorDoesNotHaveEffect", { id, actor: this.actor.name }));
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorActorDoesNotHaveEffect", { id, actor: this.actor.name }));
|
|
||||||
}
|
|
||||||
effect.sheet.render(true);
|
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 {
|
protected onDeleteEffect(event: JQuery.ClickEvent): void {
|
||||||
const li = $(event.currentTarget).parents(".effect");
|
const li = $(event.currentTarget).parents(".effect");
|
||||||
const id = li.data("effectId");
|
const id = li.data("id");
|
||||||
this.actor.deleteEmbeddedDocuments("ActiveEffect", [id]);
|
this.actor.deleteEmbeddedDocuments("ActiveEffect", [id]);
|
||||||
li.slideUp(200, () => this.render(false));
|
li.slideUp(200, () => this.render(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a change to a property of an embedded effect depending on the `data-property` attribute of the
|
||||||
|
* {@link HTMLInputElement} that has been changed and its new value.
|
||||||
|
*
|
||||||
|
* @param event - The originating change event
|
||||||
|
*/
|
||||||
protected onChangeEffect(event: JQuery.ChangeEvent): void {
|
protected onChangeEffect(event: JQuery.ChangeEvent): void {
|
||||||
event.preventDefault();
|
return this.onChangeEmbeddedDocument(event, ".effect", "ActiveEffect");
|
||||||
const currentTarget = $(event.currentTarget);
|
}
|
||||||
const element: HTMLFormElement = currentTarget.get(0);
|
|
||||||
const id = currentTarget.parents(".effect").data("effectId");
|
/**
|
||||||
const property: string | undefined = currentTarget.data("property");
|
* Applies a change to a property of an embedded document of the actor belonging to this sheet. The change depends
|
||||||
const inverted = Boolean(currentTarget.data("inverted"));
|
* on the `data-property` attribute of the {@link HTMLInputElement} that has been changed and its new value.
|
||||||
|
*
|
||||||
if (element.disabled || element.getAttribute("disabled")) return;
|
* @param event - The originating change event
|
||||||
if (property === undefined) {
|
* @param documentSelector - The selector for the closest parent of the changed {@link HTMLInputElement}, which
|
||||||
throw TypeError("HTML element does not provide 'data-property' attribute");
|
* contains the `data-id` attribute providing the `id` of the embedded document to be
|
||||||
|
* changed.
|
||||||
|
* @param documentName - The name of the embedded document to be changed.
|
||||||
|
*/
|
||||||
|
protected onChangeEmbeddedDocument(
|
||||||
|
event: JQuery.ChangeEvent,
|
||||||
|
documentSelector: string,
|
||||||
|
documentName: "Item" | "ActiveEffect",
|
||||||
|
): void {
|
||||||
|
event.preventDefault();
|
||||||
|
const element = $(event.currentTarget).get(0);
|
||||||
|
enforce(element instanceof HTMLInputElement);
|
||||||
|
if (element.disabled) return;
|
||||||
|
|
||||||
|
const effectElement = element.closest(documentSelector);
|
||||||
|
enforce(effectElement instanceof HTMLElement);
|
||||||
|
const id = effectElement.dataset["id"];
|
||||||
|
const property = element.dataset["property"];
|
||||||
|
const inverted = Boolean(element.dataset["inverted"]);
|
||||||
|
enforce(property !== undefined, TypeError("HTML element does not provide 'data-property' attribute"));
|
||||||
|
|
||||||
|
const newValue = this.parseValue(element, inverted);
|
||||||
|
this.actor.updateEmbeddedDocuments(documentName, [{ _id: id, [property]: newValue }]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the value of the given {@link HTMLInputElement} depending on the element's type
|
||||||
|
* The value is parsed to:
|
||||||
|
* - checkbox: `boolean`
|
||||||
|
* - text input: `string`
|
||||||
|
* - number: `number`
|
||||||
|
*
|
||||||
|
* @param element - The input element to parse the value from
|
||||||
|
* @param inverted - Whether or not the value should be inverted
|
||||||
|
*/
|
||||||
|
protected parseValue(element: HTMLInputElement, inverted = false): boolean | string | number {
|
||||||
|
switch (element.type) {
|
||||||
|
case "checkbox": {
|
||||||
|
const value: boolean = element.checked;
|
||||||
|
return inverted ? !value : value;
|
||||||
|
}
|
||||||
|
case "text": {
|
||||||
|
const value: string = element.value;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
case "number": {
|
||||||
|
const value = Number(element.value.trim());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new TypeError(
|
||||||
|
"Binding of item property to this type of HTML element not supported; given: " + element,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const newValue = this.getValue(element, inverted);
|
|
||||||
this.actor.updateEmbeddedDocuments("ActiveEffect", [{ _id: id, [property]: newValue }]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -299,9 +311,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
const id = $(event.currentTarget).parents(".item").data("itemId");
|
const id = $(event.currentTarget).parents(".item").data("itemId");
|
||||||
const item = this.actor.items.get(id);
|
const item = this.actor.items.get(id);
|
||||||
if (!item) {
|
enforce(item, getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
||||||
throw new Error(getGame().i18n.format("DS4.ErrorActorDoesNotHaveItem", { id, actor: this.actor.name }));
|
|
||||||
}
|
|
||||||
item.roll().catch((e) => notifications.error(e, { log: true }));
|
item.roll().catch((e) => notifications.error(e, { log: true }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,7 +333,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
const check = target.dataset.check;
|
const check = target.dataset.check;
|
||||||
if (!check) return super._onDragStart(event);
|
if (!check) return super._onDragStart(event);
|
||||||
|
|
||||||
if (!isCheck(check)) throw new Error(getGame().i18n.format("DS4.ErrorCannotDragMissingCheck", { check }));
|
enforce(isCheck(check), getGame().i18n.format("DS4.ErrorCannotDragMissingCheck", { check }));
|
||||||
|
|
||||||
const dragData = {
|
const dragData = {
|
||||||
actorId: this.actor.id,
|
actorId: this.actor.id,
|
||||||
|
@ -338,7 +348,7 @@ export class DS4ActorSheet extends ActorSheet<ActorSheet.Options, DS4ActorSheetD
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
protected async _onDropItem(event: DragEvent, data: ActorSheet.DropData.Item): Promise<unknown> {
|
protected async _onDropItem(event: DragEvent, data: ActorSheet.DropData.Item): Promise<unknown> {
|
||||||
const item = await DS4Item.fromDropData(data);
|
const item = await Item.fromDropData(data);
|
||||||
if (item && !this.actor.canOwnItemType(item.data.type)) {
|
if (item && !this.actor.canOwnItemType(item.data.type)) {
|
||||||
notifications.warn(
|
notifications.warn(
|
||||||
getGame().i18n.format("DS4.WarningActorCannotOwnItem", {
|
getGame().i18n.format("DS4.WarningActorCannotOwnItem", {
|
||||||
|
|
|
@ -5,10 +5,12 @@
|
||||||
import { getGame } from "./helpers";
|
import { getGame } from "./helpers";
|
||||||
|
|
||||||
export function registerSystemSettings(): void {
|
export function registerSystemSettings(): void {
|
||||||
|
const game = getGame();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track the migrations version of the latest migration that has been applied
|
* Track the migrations version of the latest migration that has been applied
|
||||||
*/
|
*/
|
||||||
getGame().settings.register("ds4", "systemMigrationVersion", {
|
game.settings.register("ds4", "systemMigrationVersion", {
|
||||||
name: "System Migration Version",
|
name: "System Migration Version",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: false,
|
config: false,
|
||||||
|
@ -16,7 +18,7 @@ export function registerSystemSettings(): void {
|
||||||
default: -1,
|
default: -1,
|
||||||
});
|
});
|
||||||
|
|
||||||
getGame().settings.register("ds4", "useSlayingDiceForAutomatedChecks", {
|
game.settings.register("ds4", "useSlayingDiceForAutomatedChecks", {
|
||||||
name: "DS4.SettingUseSlayingDiceForAutomatedChecksName",
|
name: "DS4.SettingUseSlayingDiceForAutomatedChecksName",
|
||||||
hint: "DS4.SettingUseSlayingDiceForAutomatedChecksHint",
|
hint: "DS4.SettingUseSlayingDiceForAutomatedChecksHint",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
|
@ -25,7 +27,7 @@ export function registerSystemSettings(): void {
|
||||||
default: false,
|
default: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
getGame().settings.register("ds4", "showSlayerPoints", {
|
game.settings.register("ds4", "showSlayerPoints", {
|
||||||
name: "DS4.SettingShowSlayerPointsName",
|
name: "DS4.SettingShowSlayerPointsName",
|
||||||
hint: "DS4.SettingShowSlayerPointsHint",
|
hint: "DS4.SettingShowSlayerPointsHint",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
|
@ -42,9 +44,10 @@ export interface DS4Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDS4Settings(): DS4Settings {
|
export function getDS4Settings(): DS4Settings {
|
||||||
|
const game = getGame();
|
||||||
return {
|
return {
|
||||||
systemMigrationVersion: getGame().settings.get("ds4", "systemMigrationVersion"),
|
systemMigrationVersion: game.settings.get("ds4", "systemMigrationVersion"),
|
||||||
useSlayingDiceForAutomatedChecks: getGame().settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
|
useSlayingDiceForAutomatedChecks: game.settings.get("ds4", "useSlayingDiceForAutomatedChecks"),
|
||||||
showSlayerPoints: getGame().settings.get("ds4", "showSlayerPoints"),
|
showSlayerPoints: game.settings.get("ds4", "showSlayerPoints"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
10
src/module/utils.ts
Normal file
10
src/module/utils.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { getGame } from "./helpers";
|
||||||
|
|
||||||
|
export function enforce(value: unknown, message?: string | Error): asserts value {
|
||||||
|
if (!value) {
|
||||||
|
if (!message) {
|
||||||
|
message = getGame().i18n.localize("DS4.ErrorUnexpectedError");
|
||||||
|
}
|
||||||
|
throw message instanceof Error ? message : new Error(message);
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,8 +12,8 @@ SPDX-License-Identifier: MIT
|
||||||
!-- @param type: An optional property to use as data-type attribute
|
!-- @param type: An optional property to use as data-type attribute
|
||||||
}}
|
}}
|
||||||
<div>
|
<div>
|
||||||
<a class="control-{{documentType}} {{documentType}}-create" title="{{localize title}}" data-action="create" {{#if
|
<a class="control-{{documentType}}" title="{{localize title}}" data-action="create" {{#if type}}data-type="{{type}}"
|
||||||
type}}data-type="{{type}}" {{/if}}>
|
{{/if}}>
|
||||||
<i class="fas fa-plus"></i>
|
<i class="fas fa-plus"></i>
|
||||||
{{localize "DS4.UserInteractionAdd"}}
|
{{localize "DS4.UserInteractionAdd"}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -7,14 +7,14 @@ SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
{{!--
|
{{!--
|
||||||
!-- Render a group of an "edit" and a "delete" button.
|
!-- Render a group of an "edit" and a "delete" button.
|
||||||
!-- The current item is defined by the data-item-id HTML property of the parent li element.
|
!-- The current item is defined by the data-id attribute of the parent li element.
|
||||||
!-- @param documentType: The type of document that is controlled by this button group, item or effect
|
!-- @param documentType: The type of document that is controlled by this button group, item or effect
|
||||||
!-- @param editTitle: The title to use for the edit link element (will be localized)
|
!-- @param editTitle: The title to use for the edit link element (will be localized)
|
||||||
!-- @param deleteTitle: The title to use for the delete link element (will be localized)
|
!-- @param deleteTitle: The title to use for the delete link element (will be localized)
|
||||||
--}}
|
--}}
|
||||||
<div class="ds4-control-button-group">
|
<div class="ds4-control-button-group">
|
||||||
<a class="ds4-control-button-group__button control-{{documentType}} {{documentType}}-edit" data-action="edit"
|
<a class="ds4-control-button-group__button control-{{documentType}}" data-action="edit"
|
||||||
title="{{localize editTitle}}"><i class="fas fa-edit"></i></a>
|
title="{{localize editTitle}}"><i class="fas fa-edit"></i></a>
|
||||||
<a class="ds4-control-button-group__button control-{{documentType}} {{documentType}}-delete" data-action="delete"
|
<a class="ds4-control-button-group__button control-{{documentType}}" data-action="delete"
|
||||||
title="{{localize deleteTitle}}"><i class="fas fa-trash"></i></a>
|
title="{{localize deleteTitle}}"><i class="fas fa-trash"></i></a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: MIT
|
||||||
<div class="ds4-currency">
|
<div class="ds4-currency">
|
||||||
{{#each data.data.currency as |value key|}}
|
{{#each data.data.currency as |value key|}}
|
||||||
<label for="data.currency.{{key}}" class="flex05">{{lookup ../config.i18n.characterCurrency key}}</label>
|
<label for="data.currency.{{key}}" class="flex05">{{lookup ../config.i18n.characterCurrency key}}</label>
|
||||||
<input class="ds4-currency__value ds4-currency__value--{{key}} item-change" type="number" min="0" step="1"
|
<input class="ds4-currency__value ds4-currency__value--{{key}} change-item" type="number" min="0" step="1"
|
||||||
name="data.currency.{{key}}" id="data.currency.{{key}}" value="{{value}}" data-dtype="Number" />
|
name="data.currency.{{key}}" id="data.currency.{{key}}" value="{{value}}" data-dtype="Number" />
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -9,7 +9,7 @@ SPDX-License-Identifier: MIT
|
||||||
!-- Render an effect list entry row.
|
!-- Render an effect list entry row.
|
||||||
!-- @param effectData: The data of the item.
|
!-- @param effectData: The data of the item.
|
||||||
--}}
|
--}}
|
||||||
<li class="ds4-effect-list__row effect" data-effect-id="{{effectData._id}}">
|
<li class="ds4-effect-list__row effect" data-id="{{effectData._id}}">
|
||||||
{{!-- enabled --}}
|
{{!-- enabled --}}
|
||||||
<input class="ds4-effect-list__editable ds4-effect-list__editable--checkbox change-effect" type="checkbox" {{checked
|
<input class="ds4-effect-list__editable ds4-effect-list__editable--checkbox change-effect" type="checkbox" {{checked
|
||||||
(ne effectData.disabled true)}} data-dtype="Boolean" data-property="disabled" data-inverted="true"
|
(ne effectData.disabled true)}} data-dtype="Boolean" data-property="disabled" data-inverted="true"
|
||||||
|
|
|
@ -8,7 +8,7 @@ SPDX-License-Identifier: MIT
|
||||||
{{!--
|
{{!--
|
||||||
!-- Render an effect list header row.
|
!-- Render an effect list header row.
|
||||||
--}}
|
--}}
|
||||||
<li class="ds4-effect-list__row ds4-effect-list__row--header" data-effect-id="{{effectData._id}}">
|
<li class="ds4-effect-list__row ds4-effect-list__row--header">
|
||||||
{{!-- enabled --}}
|
{{!-- enabled --}}
|
||||||
<div title="{{localize 'DS4.EffectEnabled'}}">{{localize 'DS4.EffectEnabledAbbr'}}</div>
|
<div title="{{localize 'DS4.EffectEnabled'}}">{{localize 'DS4.EffectEnabledAbbr'}}</div>
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,10 @@ SPDX-License-Identifier: MIT
|
||||||
!-- @param hideDescription: A flag to disable the description column.
|
!-- @param hideDescription: A flag to disable the description column.
|
||||||
!-- @param @partial-block: Custom column headers can be passed using the partial block.
|
!-- @param @partial-block: Custom column headers can be passed using the partial block.
|
||||||
--}}
|
--}}
|
||||||
<li class="ds4-item-list__row item" data-item-id="{{itemData._id}}">
|
<li class="ds4-item-list__row item" data-id="{{itemData._id}}">
|
||||||
{{!-- equipped --}}
|
{{!-- equipped --}}
|
||||||
{{#if isEquipable}}
|
{{#if isEquipable}}
|
||||||
<input class="ds4-item-list__editable ds4-item-list__editable--checkbox item-change" type="checkbox" {{checked
|
<input class="ds4-item-list__editable ds4-item-list__editable--checkbox change-item" type="checkbox" {{checked
|
||||||
itemData.data.equipped}} data-dtype="Boolean" data-property="data.equipped"
|
itemData.data.equipped}} data-dtype="Boolean" data-property="data.equipped"
|
||||||
title="{{localize 'DS4.ItemEquipped'}}">
|
title="{{localize 'DS4.ItemEquipped'}}">
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -30,12 +30,12 @@ SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
{{!-- amount --}}
|
{{!-- amount --}}
|
||||||
{{#if hasQuantity}}
|
{{#if hasQuantity}}
|
||||||
<input class="ds4-item-list__editable item-change" type="number" min="0" step="1" value="{{itemData.data.quantity}}"
|
<input class="ds4-item-list__editable change-item" type="number" min="0" step="1" value="{{itemData.data.quantity}}"
|
||||||
data-dtype="Number" data-property="data.quantity" title="{{localize 'DS4.Quantity'}}" />
|
data-dtype="Number" data-property="data.quantity" title="{{localize 'DS4.Quantity'}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{!-- name --}}
|
{{!-- name --}}
|
||||||
<input class="ds4-item-list__editable item-change" type="text" value="{{itemData.name}}" data-dtype="String"
|
<input class="ds4-item-list__editable change-item" type="text" value="{{itemData.name}}" data-dtype="String"
|
||||||
data-property="name" title="{{htmlToPlainText itemData.data.description}}" />
|
data-property="name" title="{{htmlToPlainText itemData.data.description}}" />
|
||||||
|
|
||||||
{{!-- item type specifics --}}
|
{{!-- item type specifics --}}
|
||||||
|
|
|
@ -117,7 +117,7 @@ documentType='item' type='shield'}}
|
||||||
{{#> systems/ds4/templates/sheets/actor/components/item-list-entry.hbs itemData=itemData isEquipable=true
|
{{#> systems/ds4/templates/sheets/actor/components/item-list-entry.hbs itemData=itemData isEquipable=true
|
||||||
hasQuantity=true}}
|
hasQuantity=true}}
|
||||||
{{!-- storage location --}}
|
{{!-- storage location --}}
|
||||||
<input class="ds4-item-list__editable item-change" type="text" value="{{itemData.data.storageLocation}}"
|
<input class="ds4-item-list__editable change-item" type="text" value="{{itemData.data.storageLocation}}"
|
||||||
data-dtype="String" data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
data-dtype="String" data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
||||||
{{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}}
|
{{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -137,7 +137,7 @@ documentType='item' type='equipment'}}
|
||||||
{{#each itemsByType.loot as |itemData id|}}
|
{{#each itemsByType.loot as |itemData id|}}
|
||||||
{{#> systems/ds4/templates/sheets/actor/components/item-list-entry.hbs itemData=itemData hasQuantity=true}}
|
{{#> systems/ds4/templates/sheets/actor/components/item-list-entry.hbs itemData=itemData hasQuantity=true}}
|
||||||
{{!-- storage location --}}
|
{{!-- storage location --}}
|
||||||
<input class="ds4-item-list__editable item-change" type="text" value="{{itemData.data.storageLocation}}"
|
<input class="ds4-item-list__editable change-item" type="text" value="{{itemData.data.storageLocation}}"
|
||||||
data-dtype="String" data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
data-dtype="String" data-property="data.storageLocation" title="{{localize 'DS4.StorageLocation'}}">
|
||||||
{{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}}
|
{{/systems/ds4/templates/sheets/actor/components/item-list-entry.hbs}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -18,7 +18,7 @@ disable the input element
|
||||||
!-- @param localizeString: The string to use as key for the localized tooltip
|
!-- @param localizeString: The string to use as key for the localized tooltip
|
||||||
--}}
|
--}}
|
||||||
{{#*inline "talentRankValue"}}
|
{{#*inline "talentRankValue"}}
|
||||||
<input class="ds4-talent-rank-equation__value item-change" data-dtype="Number" type="number" min="0" step="1" {{#if (eq
|
<input class="ds4-talent-rank-equation__value change-item" data-dtype="Number" type="number" min="0" step="1" {{#if (eq
|
||||||
property 'base' ) }}max="{{talentRank.max}}" {{/if}} {{disabled}} data-property="data.rank.{{property}}"
|
property 'base' ) }}max="{{talentRank.max}}" {{/if}} {{disabled}} data-property="data.rank.{{property}}"
|
||||||
value="{{lookup talentRank property}}" title="{{localize localizeString}}" />
|
value="{{lookup talentRank property}}" title="{{localize localizeString}}" />
|
||||||
{{/inline}}
|
{{/inline}}
|
||||||
|
|
|
@ -76,7 +76,7 @@ titleKey=titleKey}}
|
||||||
title="{{lookup ../../config.i18n.spellTypes itemData.data.spellType}}" />
|
title="{{lookup ../../config.i18n.spellTypes itemData.data.spellType}}" />
|
||||||
|
|
||||||
{{!-- spell bonus --}}
|
{{!-- spell bonus --}}
|
||||||
<input class="ds4-item-list__editable item-change" type="text" data-dtype="String" data-property="data.bonus"
|
<input class="ds4-item-list__editable change-item" type="text" data-dtype="String" data-property="data.bonus"
|
||||||
value="{{itemData.data.bonus}}" title="{{localize 'DS4.SpellBonus'}}" />
|
value="{{itemData.data.bonus}}" title="{{localize 'DS4.SpellBonus'}}" />
|
||||||
|
|
||||||
{{!-- max. distance --}}
|
{{!-- max. distance --}}
|
||||||
|
|
Loading…
Reference in a new issue