Merge branch 'master' into 005_item_editing
This commit is contained in:
commit
110a523268
10 changed files with 109 additions and 60 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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>;
|
||||||
|
}
|
||||||
|
|
|
@ -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 }),
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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`;
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
Loading…
Reference in a new issue