foundry-vtt-system-midgard5/source/module/sheets/M5CharacterSheet.ts

315 lines
9.0 KiB
TypeScript

import Logger from "../../utils/Logger";
import { M5Character } from "../actors/M5Character";
import { M5Item } from "../items/M5Item";
import { M5SkillLearned, M5SkillUnlearned } from "../M5Base";
import { M5Roll } from "../rolls/M5Roll";
export default class M5CharacterSheet extends ActorSheet {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
template: "systems/midgard5/templates/sheets/character/main.hbs",
width: 800,
height: 800,
classes: ["midgard5", "sheet", "character"],
tabs: [{ navSelector: ".sheet-navigation", contentSelector: ".sheet-content", initial: "base_values" }],
});
}
// get template() {
// return "systems/midgard5/templates/character_sheet/main.hbs"
// }Options extends ActorSheet.Options = ActorSheet.Options, Data extends object = ActorSheet.Data<Options>
override getData(options?: Partial<ActorSheet.Options>): ActorSheet.Data<ActorSheet.Options> | Promise<ActorSheet.Data<ActorSheet.Options>> {
const actor = this.actor as M5Character;
//console.log("Sheet getData", (actor as any).data)
return Promise.resolve(super.getData(options)).then((context) => {
actor.prepareDerivedData();
context.actor = (actor as any).toObject(false);
context.data = (actor as any).system;
//console.log("Sheet Promise", context.actor, context.data)
return context;
});
}
override setPosition(options = {}) {
const position = super.setPosition(options);
const fillerWidth = this.element.find(".attributes .filler:first").width();
this.element.find(".attributes .attribute-filler-fixed").width(fillerWidth);
return position;
}
override activateListeners(html: JQuery) {
super.activateListeners(html);
html.find(".update-lp").on("click", async (event) => {
const valueStr = event.target.dataset["value"];
const value = parseInt(valueStr);
this.actor.update({
data: {
lp: {
value: value + 1,
},
},
});
});
html.find(".update-ap").on("click", async (event) => {
const valueStr = event.target.dataset["value"];
const value = parseInt(valueStr);
this.actor.update({
data: {
ap: {
value: value + 1,
},
},
});
});
html.find(".roll-attribute-button").on("click", async (event) => {
let elem = event.target;
let attributeStr = elem.dataset["attribute"];
while (!attributeStr) {
elem = elem.parentElement;
if (!elem) return;
attributeStr = elem.dataset["attribute"];
}
const attributeValue = parseInt(elem.dataset["value"]);
const roll = M5Roll.fromAttributeValue(this.actor, attributeStr, attributeValue);
//console.log("roll-attribute-button", parent, attributeStr, attributeValue, roll)
await roll.toMessage();
});
html.find(".edit-item").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
console.log("edit-item", item);
item.sheet.render(true);
});
html.find(".quantity-increase").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
if (!item.system.quantity) {
item.system.quantity = 0;
}
item.system.quantity += 1;
this.render();
});
html.find(".quantity-decrease").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
if (item.system.quantity > 0) {
item.system.quantity -= 1;
}
this.render();
});
html.find(".roll-consumable-item").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
if (item.system.quantity > 0) {
item.system.quantity -= 1;
}
await item.roll();
this.render();
});
html.find(".item-delete").on("click", async (event) => {
let row = event.target.parentElement;
let itemId = row.dataset["item"];
while (!itemId) {
row = row.parentElement;
if (!row) return;
itemId = row.dataset["item"];
}
const context = this.actor as any;
const item = context.items.get(itemId);
item.delete();
this.render(false);
});
html.find(".roll-learned-button").on("click", async (event) => {
const row = event.target.parentElement.parentElement;
let skillId = row.dataset["item"];
const actor = this.actor as any;
const item = actor.items.get(skillId) as M5Item;
await item.roll();
});
html.find(".roll-general-button").on("click", async (event) => {
const row = event.target.parentElement.parentElement;
let skillName = row.dataset["skill"];
const data = this.actor.system;
const unlearnedSkill = data.skills.general[skillName] as M5SkillUnlearned;
const roll = M5Roll.fromUnlearnedSkill(this.actor, unlearnedSkill, skillName);
await roll.toMessage();
});
html.find(".learn-button").on("click", async (event) => {
const row = event.target.parentElement.parentElement;
let skillName = row.dataset["skill"];
const data = this.actor.system;
const unlearnedSkill = data.skills.general[skillName] as M5SkillUnlearned;
const character = this.actor as M5Character;
character.createSkill((game as Game).i18n.localize("midgard5." + skillName)).then((skill) => {
const item = skill as any;
item.update({
data: {
fw: unlearnedSkill.initial,
attribute: unlearnedSkill.attribute,
skill: skillName,
type: "general",
},
});
});
});
html.find(".roll-weapon-button").on("click", async (event) => {
const row = event.target.parentElement.parentElement;
let itemId = row.dataset["item"];
const context = this.actor as any;
const item = context.items.get(itemId) as M5Item;
await item.roll();
this.render();
});
html.find(".roll-brawl-button").on("click", async (event) => {
const roll = M5Roll.brawl(this.actor);
await roll.toMessage();
});
html.find(".roll-perception-button").on("click", async (event) => {
const roll = M5Roll.perception(this.actor);
await roll.toMessage();
});
html.find(".roll-drinking-button").on("click", async (event) => {
const roll = M5Roll.drinking(this.actor);
await roll.toMessage();
});
html.find(".roll-defense-button").on("click", async (event) => {
const roll = M5Roll.defense(this.actor);
await roll.toMessage();
});
html.find(".roll-resistanceMind-button").on("click", async (event) => {
const roll = M5Roll.resistanceMind(this.actor);
await roll.toMessage();
});
html.find(".roll-resistanceBody-button").on("click", async (event) => {
const roll = M5Roll.resistanceBody(this.actor);
await roll.toMessage();
});
// Drag & Drop
const dragDrop = new DragDrop({
dragSelector: ".items-list .item",
dropSelector: ".sheet-body",
permissions: { dragstart: this._canDragStart.bind(this), drop: this._canDragDrop.bind(this) },
callbacks: { dragstart: this._onTransferItemDragStart.bind(this), drop: this._onTransferItemDrop.bind(this) },
});
dragDrop.bind(html[0]);
}
_canDragStart(selector) {
return this.options.editable && this.actor.isOwner;
}
_canDragDrop(selector) {
return true;
}
_onTransferItemDragStart(event) {
const li = event.currentTarget;
$(event.currentTarget).attr("data-item-actorid", this.actor.id);
const item = this.actor.items.get(li.dataset.itemId);
// limit transfer on personal weapons/armour/gear
if (["skill", "item", "weapon", "defensiveWeapon", "armor", "spell", "effect", "kampfkunst"].includes(item.type)) {
const dragData = {
type: "Transfer",
actorId: this.actor.id,
data: item.toObject(false),
tokenId: null,
};
if (this.actor.isToken) dragData.tokenId = this.actor.token.id;
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
} else {
return false;
}
}
async _onTransferItemDrop(event) {
// Try to extract the data
let data = null;
try {
data = JSON.parse(event.dataTransfer.getData("text/plain"));
if (data.type !== "Transfer") return false;
} catch (err) {
return false;
}
if (!data.data) return false;
if (data.actorId === this.actor.id) return false;
try {
this.actor.createEmbeddedDocuments("Item", [duplicate(data.data)]); // Create a new Item
const actor = (game as any).actors.get(data.actorId);
await actor.items.get(data.data._id)?.delete(); // Delete originating item from other actor
} catch (e) {
console.error("Error transfering item between actors", e);
return false;
}
return true;
}
}