Merge branch 'master' into 005_item_editing

This commit is contained in:
Gesina Schwalbe 2020-12-28 19:55:47 +01:00
commit 110a523268
10 changed files with 109 additions and 60 deletions

4
package-lock.json generated
View file

@ -2678,8 +2678,8 @@
} }
}, },
"foundry-pc-types": { "foundry-pc-types": {
"version": "gitlab:foundry-projects/foundry-pc/foundry-pc-types#e9cca6fbbe811fb439a3d0cdba7433746530cd97", "version": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#211c36bdde13400f02421dc0f911b255767dac76",
"from": "gitlab:foundry-projects/foundry-pc/foundry-pc-types", "from": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/jquery": "^3.5.1", "@types/jquery": "^3.5.1",

View file

@ -9,7 +9,7 @@
"build:watch": "gulp watch", "build:watch": "gulp watch",
"link": "gulp link", "link": "gulp link",
"clean": "gulp clean && gulp link --clean", "clean": "gulp clean && gulp link --clean",
"update": "npm install --save-dev gitlab:foundry-projects/foundry-pc/foundry-pc-types", "update": "npm install --save-dev git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes",
"lint": "eslint 'src/**/*.ts' --cache", "lint": "eslint 'src/**/*.ts' --cache",
"lint:fix": "eslint 'src/**/*.ts' --cache --fix" "lint:fix": "eslint 'src/**/*.ts' --cache --fix"
}, },
@ -23,7 +23,7 @@
"eslint": "^7.16.0", "eslint": "^7.16.0",
"eslint-config-prettier": "^7.1.0", "eslint-config-prettier": "^7.1.0",
"eslint-plugin-prettier": "^3.3.0", "eslint-plugin-prettier": "^3.3.0",
"foundry-pc-types": "gitlab:foundry-projects/foundry-pc/foundry-pc-types", "foundry-pc-types": "git+https://git.f3l.de/dungeonslayers/foundry-pc-types.git#f3l-fixes",
"fs-extra": "^9.0.1", "fs-extra": "^9.0.1",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-git": "^2.10.1", "gulp-git": "^2.10.1",

View file

@ -1,2 +1,26 @@
// TODO: Actually add a type for data export interface DS4ActorDataType {
export type DS4ActorDataType = unknown; attributes: DS4ActorDataAttributes;
traits: DS4ActorDataTraits;
}
interface DS4ActorDataAttributes {
body: BodyAttribute;
mobility: ExtensibleData<number>;
mind: ExtensibleData<number>;
}
interface ExtensibleData<T extends any> {
initial: T;
}
// Blueprint in case we need more detailed differentiation
type BodyAttribute = ExtensibleData<number>;
interface DS4ActorDataTraits {
strength: ExtensibleData<number>;
constitution: ExtensibleData<number>;
agility: ExtensibleData<number>;
dexterity: ExtensibleData<number>;
intellect: ExtensibleData<number>;
aura: ExtensibleData<number>;
}

View file

@ -19,18 +19,6 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor> {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */
getData(): ActorSheetData<DS4ActorDataType> {
// TODO: replace ["..."] access with .
const data = super.getData();
data["dtypes"] = ["String", "Number", "Boolean"];
for (const attr of Object.values(data.data["attributes"])) {
attr["isCheckbox"] = attr["dtype"] === "Boolean";
}
console.log(data);
return data;
}
/** @override */ /** @override */
activateListeners(html: JQuery): void { activateListeners(html: JQuery): void {
super.activateListeners(html); super.activateListeners(html);
@ -39,17 +27,17 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor> {
if (!this.options.editable) return; if (!this.options.editable) return;
// Add Inventory Item // Add Inventory Item
html.find(".item-create").click(this._onItemCreate.bind(this)); html.find(".item-create").on("click", this._onItemCreate.bind(this));
// Update Inventory Item // Update Inventory Item
html.find(".item-edit").click((ev) => { html.find(".item-edit").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
const item = this.actor.getOwnedItem(li.data("itemId")); const item = this.actor.getOwnedItem(li.data("itemId"));
item.sheet.render(true); item.sheet.render(true);
}); });
// Delete Inventory Item // Delete Inventory Item
html.find(".item-delete").click((ev) => { html.find(".item-delete").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.deleteOwnedItem(li.data("itemId")); this.actor.deleteOwnedItem(li.data("itemId"));
li.slideUp(200, () => this.render(false)); li.slideUp(200, () => this.render(false));
@ -66,7 +54,7 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor> {
* @param {Event} event The originating click event * @param {Event} event The originating click event
* @private * @private
*/ */
_onItemCreate(event: JQuery.ClickEvent): Promise<Item> { private _onItemCreate(event: JQuery.ClickEvent): Promise<Item> {
event.preventDefault(); event.preventDefault();
const header = event.currentTarget; const header = event.currentTarget;
// Get the type of item to create. // Get the type of item to create.
@ -93,13 +81,13 @@ export class DS4ActorSheet extends ActorSheet<DS4ActorDataType, DS4Actor> {
* @param {Event} event The originating click event * @param {Event} event The originating click event
* @private * @private
*/ */
_onRoll(event: JQuery.ClickEvent): void { private _onRoll(event: JQuery.ClickEvent): void {
event.preventDefault(); event.preventDefault();
const element = event.currentTarget; const element = event.currentTarget;
const dataset = element.dataset; const dataset = element.dataset;
if (dataset.roll) { if (dataset.roll) {
const roll = new Roll(dataset.roll, this.actor.data.data as Record<string, unknown>); const roll = new Roll(dataset.roll, this.actor.data.data);
const label = dataset.label ? `Rolling ${dataset.label}` : ""; const label = dataset.label ? `Rolling ${dataset.label}` : "";
roll.roll().toMessage({ roll.roll().toMessage({
speaker: ChatMessage.getSpeaker({ actor: this.actor }), speaker: ChatMessage.getSpeaker({ actor: this.actor }),

View file

@ -11,29 +11,27 @@ export class DS4Actor extends Actor<DS4ActorDataType> {
this._prepareCombatValues(data); this._prepareCombatValues(data);
} }
_prepareCombatValues(data: ActorData<DS4ActorDataType>): void { private _prepareCombatValues(data: ActorData<DS4ActorDataType>): void {
const hitPointsModifier = getProperty(data, "data.combatValues.hitPoints.modifier") || 0; const hitPointsModifier = getProperty(data, "data.combatValues.hitPoints.modifier") || 0;
const actorData = data.data;
setProperty( setProperty(
data, data,
"data.combatValues.hitPoints.max", "data.combatValues.hitPoints.max",
data.data["attributes"]["body"].initial + // TODO: replace ["..."] actorData.attributes.body.initial + actorData.traits.constitution.initial + 10 + hitPointsModifier,
data.data["traits"]["constitution"].initial + // TODO: replace ["..."]
10 +
hitPointsModifier,
); );
const defenseModifier = getProperty(data, "data.combatValues.defense.modifier") || 0; const defenseModifier = getProperty(data, "data.combatValues.defense.modifier") || 0;
setProperty( setProperty(
data, data,
"data.combatValues.defense.value", "data.combatValues.defense.value",
data.data["attributes"]["body"].initial + // TODO: replace ["..."] actorData.attributes.body.initial +
data.data["traits"]["constitution"].initial + // TODO: replace ["..."] actorData.traits.constitution.initial +
this._getArmorValue() + this._getArmorValue() +
defenseModifier, defenseModifier,
); );
} }
_getArmorValue(): number { private _getArmorValue(): number {
return this.data["items"] return this.data["items"]
.filter((item) => ["armor", "shield"].includes(item.type)) .filter((item) => ["armor", "shield"].includes(item.type))
.filter((item) => item.data.equipped) .filter((item) => item.data.equipped)

View file

@ -1,11 +1,11 @@
export const DS4 = { export const DS4 = {
// ASCII Artwork // ASCII Artwork
ASCII: `_____________________________________________________________________________________________ ASCII: String.raw`_____________________________________________________________________________________________
____ _ _ _ _ ____ _____ ___ _ _ ____ _ _ __ _______ ____ ____ _ _ ____ _ _ _ _ ____ _____ ___ _ _ ____ _ _ __ _______ ____ ____ _ _
| _ \\| | | | \\ | |/ ___| ____/ _ \\| \\ | / ___|| | / \\\\ \\ / / ____| _ \\/ ___| | || | | _ \| | | | \ | |/ ___| ____/ _ \| \ | / ___|| | / \\ \ / / ____| _ \/ ___| | || |
| | | | | | | \\| | | _| _|| | | | \\| \\___ \\| | / _ \\\\ V /| _| | |_) \\___ \\ | || |_ | | | | | | | \| | | _| _|| | | | \| \___ \| | / _ \\ V /| _| | |_) \___ \ | || |_
| |_| | |_| | |\\ | |_| | |__| |_| | |\\ |___) | |___ / ___ \\| | | |___| _ < ___) | |__ _| | |_| | |_| | |\ | |_| | |__| |_| | |\ |___) | |___ / ___ \| | | |___| _ < ___) | |__ _|
|____/ \\___/|_| \\_|\\____|_____\\___/|_| \\_|____/|_____/_/ \\_\\_| |_____|_| \\_\\____/ |_| |____/ \___/|_| \_|\____|_____\___/|_| \_|____/|_____/_/ \_\_| |_____|_| \_\____/ |_|
=============================================================================================`, =============================================================================================`,
/** /**
@ -49,7 +49,7 @@ export const DS4 = {
*/ */
armorTypes: { armorTypes: {
body: "DS4.ArmorTypeBody", body: "DS4.ArmorTypeBody",
helment: "DS4.ArmorTypeHelmet", helmet: "DS4.ArmorTypeHelmet",
vambrace: "DS4.ArmorTypeVambrace", vambrace: "DS4.ArmorTypeVambrace",
greaves: "DS4.ArmorTypeGreaves", greaves: "DS4.ArmorTypeGreaves",
vambraceGreaves: "DS4.ArmorTypeVambraceGreaves", vambraceGreaves: "DS4.ArmorTypeVambraceGreaves",

View file

@ -18,8 +18,8 @@ Hooks.once("init", async function () {
CONFIG.DS4 = DS4; CONFIG.DS4 = DS4;
// Define custom Entity classes // Define custom Entity classes
CONFIG.Actor.entityClass = DS4Actor as typeof Actor; // TODO: Can we remove the casts? CONFIG.Actor.entityClass = DS4Actor as typeof Actor;
CONFIG.Item.entityClass = DS4Item as typeof Item; // TODO: Can we remove the casts? CONFIG.Item.entityClass = DS4Item as typeof Item;
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet);

View file

@ -1,2 +1,38 @@
// TODO: Actually add a type for data // TODO: Actually add a type for data
export type DS4ItemDataType = unknown; export type DS4ItemDataType = DS4Weapon | DS4Armor | DS4Shield | DS4Trinket | DS4Equipment;
// types
interface DS4Weapon extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {
attackType: "melee" | "ranged" | "meleeRanged";
weaponBonus: number;
opponentDefense: number;
}
interface DS4Armor extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {
armorMaterialType: "cloth" | "leather" | "chain" | "plate";
armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
}
interface DS4Shield extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {}
interface DS4Trinket extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {}
interface DS4Equipment extends DS4ItemBase, DS4ItemPhysical {}
// templates
interface DS4ItemBase {
description: string;
}
interface DS4ItemPhysical {
quantity: number;
price: number;
availability: "hamlet" | "village" | "city" | "elves" | "dwarves" | "none";
}
interface DS4ItemEquipable {
equipped: boolean;
}
interface DS4ItemProtective {
armorValue: number;
}

View file

@ -1,4 +1,3 @@
import { DS4ActorDataType } from "../actor/actor-data";
import { DS4Item } from "./item"; import { DS4Item } from "./item";
import { DS4ItemDataType } from "./item-data"; import { DS4ItemDataType } from "./item-data";
@ -6,7 +5,7 @@ import { DS4ItemDataType } from "./item-data";
* Extend the basic ItemSheet with some very simple modifications * Extend the basic ItemSheet with some very simple modifications
* @extends {ItemSheet} * @extends {ItemSheet}
*/ */
export class DS4ItemSheet extends ItemSheet<DS4ActorDataType, DS4Item> { export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
/** @override */ /** @override */
static get defaultOptions(): FormApplicationOptions { static get defaultOptions(): FormApplicationOptions {
return mergeObject(super.defaultOptions, { return mergeObject(super.defaultOptions, {
@ -26,7 +25,7 @@ export class DS4ItemSheet extends ItemSheet<DS4ActorDataType, DS4Item> {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
getData(): ItemSheetData<DS4ItemDataType> { getData(): ItemSheetData<DS4ItemDataType, DS4Item> {
const data = { ...super.getData(), config: CONFIG.DS4 }; const data = { ...super.getData(), config: CONFIG.DS4 };
console.log(data); console.log(data);
return data; return data;
@ -35,11 +34,15 @@ export class DS4ItemSheet extends ItemSheet<DS4ActorDataType, DS4Item> {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}): unknown { setPosition(options: ApplicationPosition = {}): ApplicationPosition {
const position = super.setPosition(options); const position = super.setPosition(options);
const sheetBody = (this.element as JQuery).find(".sheet-body"); // TODO: Why is the cast necessary? if ("find" in this.element) {
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - 192; const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight); sheetBody.css("height", bodyHeight);
} else {
console.log("Failure setting position.");
}
return position; return position;
} }
@ -51,16 +54,16 @@ export class DS4ItemSheet extends ItemSheet<DS4ActorDataType, DS4Item> {
if (!this.options.editable) return; if (!this.options.editable) return;
html.find(".effect-create").click(this._onEffectCreate.bind(this)); html.find(".effect-create").on("click", this._onEffectCreate.bind(this));
html.find(".effect-edit").click((ev) => { html.find(".effect-edit").on("click", (ev) => {
const li = $(ev.currentTarget).parents(".effect"); const li = $(ev.currentTarget).parents(".effect");
console.log(li.data("effectId")); console.log(li.data("effectId"));
const effect = this.item["effects"].get(li.data("effectId")); // TODO: replace ["..."] const effect = this.item["effects"].get(li.data("effectId")); // TODO: replace ["..."]
effect.sheet.render(true); effect.sheet.render(true);
}); });
html.find(".effect-delete").click(async (ev) => { html.find(".effect-delete").on("click", async (ev) => {
const li = $(ev.currentTarget).parents(".effect"); const li = $(ev.currentTarget).parents(".effect");
await this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId")); await this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId"));
}); });
@ -71,7 +74,7 @@ export class DS4ItemSheet extends ItemSheet<DS4ActorDataType, DS4Item> {
* @param {Event} event The originating click event * @param {Event} event The originating click event
* @private * @private
*/ */
async _onEffectCreate(event: JQuery.ClickEvent): Promise<unknown> { private async _onEffectCreate(event: JQuery.ClickEvent): Promise<unknown> {
event.preventDefault(); event.preventDefault();
const label = `New Effect`; const label = `New Effect`;

View file

@ -51,24 +51,24 @@
}, },
"equipable": { "equipable": {
"equipped": false "equipped": false
},
"protective": {
"armorValue": 0
} }
}, },
"weapon": { "weapon": {
"templates": ["base", "physical", "equipable"], "templates": ["base", "physical", "equipable"],
"attackType": "melee", "attackType": "melee",
"weaponBonus": 0, "weaponBonus": 0,
"opponentDefense": 0, "opponentDefense": 0
"properties": {}
}, },
"armor": { "armor": {
"templates": ["base", "physical", "equipable"], "templates": ["base", "physical", "equipable", "protective"],
"armorMaterialType": "cloth", "armorMaterialType": "cloth",
"armorType": "body", "armorType": "body"
"armorValue": 0
}, },
"shield": { "shield": {
"templates": ["base", "physical", "equipable"], "templates": ["base", "physical", "equipable", "protective"]
"armorValue": 0
}, },
"trinket": { "trinket": {
"templates": ["base", "physical", "equipable"] "templates": ["base", "physical", "equipable"]