ripcrypt/module/Apps/ActorSheets/BookGeistSheet.mjs

217 lines
5.1 KiB
JavaScript

import { filePath } from "../../consts.mjs";
import { GenericAppMixin } from "../mixins/GenericApp.mjs";
import { LaidOutAppMixin } from "../mixins/LaidOutAppMixin.mjs";
import { localizer } from "../../utils/Localizer.mjs";
import { editItemFromElement, deleteItemFromElement } from "../utils.mjs";
import { gameTerms } from "../../gameTerms.mjs";
const { HandlebarsApplicationMixin } = foundry.applications.api;
const { ActorSheetV2 } = foundry.applications.sheets;
const { ContextMenu, TextEditor } = foundry.applications.ux;
export class BookGeistSheet extends
LaidOutAppMixin(
GenericAppMixin(
HandlebarsApplicationMixin(
ActorSheetV2,
))) {
// #region Options
static DEFAULT_OPTIONS = {
classes: [
`ripcrypt--actor`,
`BookGeistSheet`,
],
position: {
width: `auto`,
height: `auto`,
},
window: {
resizable: true,
},
form: {
submitOnChange: true,
closeOnSubmite: false,
},
};
static PARTS = {
layout: {
root: true,
template: filePath(`templates/Apps/BookGeistSheet/layout.hbs`),
},
image: { template: filePath(`templates/Apps/BookGeistSheet/image.hbs`) },
header: { template: filePath(`templates/Apps/BookGeistSheet/header.hbs`) },
stats: { template: filePath(`templates/Apps/BookGeistSheet/stats.hbs`) },
items: { template: filePath(`templates/Apps/BookGeistSheet/items.hbs`) },
};
// #endregion Options
// #region Lifecycle
async _onRender() {
await super._onRender();
new ContextMenu.implementation(
this.element,
`[data-ctx-menu="item"]`,
[
{
name: localizer(`RipCrypt.common.edit`),
condition: (el) => {
const itemId = el.dataset.itemId;
return itemId !== ``;
},
callback: editItemFromElement,
},
{
name: localizer(`RipCrypt.common.delete`),
condition: (el) => {
const itemId = el.dataset.itemId;
return itemId !== ``;
},
callback: deleteItemFromElement,
},
],
{ jQuery: false, fixed: true },
);
};
// #endregion Lifecycle
// #region Data Prep
async _preparePartContext(partID, ctx) {
switch (partID) {
case `layout`: await this._prepareLayoutContext(ctx); break;
case `image`: await this._prepareImageContext(ctx); break;
case `header`: await this._prepareHeaderContext(ctx); break;
case `stats`: await this._prepareStatsContext(ctx); break;
case `items`: await this._prepareItemsContext(ctx); break;
};
return ctx;
};
async _prepareLayoutContext(ctx) {
ctx.imageVisible = true;
};
async _prepareImageContext(ctx) {
ctx.url = this.actor.img;
};
async _prepareHeaderContext(ctx) {
ctx.name = this.actor.name;
ctx.rank = this.actor.system.level.rank;
ctx.ranks = Object.values(gameTerms.Rank)
.map((value, index) => ({
value,
label: index
}));
ctx.description = await TextEditor.implementation.enrichHTML(this.actor.system.description);
};
async _prepareStatsContext(ctx) {
const system = this.actor.system;
const fate = system.fate;
if (fate) {
ctx.path = {
full: localizer(`RipCrypt.common.ordinals.${fate}.full`),
abbv: localizer(`RipCrypt.common.ordinals.${fate}.abbv`),
};
}
else {
ctx.path = {
full: null,
abbv: localizer(`RipCrypt.common.empty`),
};
};
Object.assign(ctx, system.ability);
ctx.guts = system.guts;
ctx.speed = system.speed;
};
async _prepareItemsContext(ctx) {
const armours = this.actor.system.equippedArmour;
const shield = this.actor.system.equippedShield;
let defenses = [];
for (const [location, armour] of Object.entries(armours)) {
if (!armour) { continue }
const defense = {
name: localizer(`RipCrypt.common.anatomy.${location}`),
tooltip: null,
protection: 0,
shielded: false,
};
if (armour) {
defense.armourUUID = armour.uuid;
defense.tooltip = armour.name,
defense.protection = armour.system.protection;
}
if (shield?.system.location.has(location)) {
defense.shieldUUID = shield.uuid;
defense.shielded = true;
defense.protection += shield.system.protection;
};
if (defense.protection > 0) {
defenses.push(defense);
};
};
ctx.defenses = defenses
ctx.traits = []; // Array<{name: string}>
for (const item of this.actor.items) {
switch (item.type) {
case `weapon`: {
if (!item.system.equipped) { continue };
ctx.attacks ??= [];
ctx.attacks.push(this._prepareWeapon(item));
break;
};
case `craft`: {
ctx.crafts ??= [];
ctx.crafts.push(this._prepareCraft(item));
break;
};
case `trait`: {
ctx.traits.push(this._prepareTrait(item));
break;
};
};
};
};
_prepareWeapon(weapon) {
const hasShortRange = weapon.system.range.short != null;
const hasLongRange = weapon.system.range.long != null;
const isRanged = hasShortRange || hasLongRange;
return {
uuid: weapon.uuid,
name: weapon.name,
damage: weapon.system.damage,
isRanged,
range: weapon.system.range,
};
};
_prepareCraft(craft) {
return {
uuid: craft.uuid,
name: craft.name,
};
};
_prepareTrait(trait) {
return {
uuid: trait.uuid,
name: trait.name,
description: trait.system.description,
};
};
// #endregion Data Prep
// #region Actions
// #endregion Actions
};