mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-01-12 03:31:07 +01:00
Merge branch 'development' into feature/313-preset-measured-templates
This commit is contained in:
commit
b75b4c8fcb
24 changed files with 239 additions and 109 deletions
|
|
@ -16,7 +16,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
|
|||
this.action =
|
||||
config.data.attack?._id == config.source.action
|
||||
? config.data.attack
|
||||
: this.item.system.actions.get(config.source.action);
|
||||
: this.item.system.actionsList?.find(a => a.id === config.source.action);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ export default function DHApplicationMixin(Base) {
|
|||
deleteDoc: DHSheetV2.#deleteDoc,
|
||||
toChat: DHSheetV2.#toChat,
|
||||
useItem: DHSheetV2.#useItem,
|
||||
viewItem: DHSheetV2.#viewItem,
|
||||
toggleEffect: DHSheetV2.#toggleEffect,
|
||||
toggleExtended: DHSheetV2.#toggleExtended,
|
||||
addNewItem: DHSheetV2.#addNewItem,
|
||||
|
|
@ -203,11 +204,19 @@ export default function DHApplicationMixin(Base) {
|
|||
this.relatedDocs.filter(doc => doc).map(doc => delete doc.apps[this.id]);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
async _renderHTML(context, options) {
|
||||
const rendered = await super._renderHTML(context, options);
|
||||
for (const result of Object.values(rendered)) {
|
||||
await this.#prepareInventoryDescription(result);
|
||||
}
|
||||
return rendered;
|
||||
}
|
||||
|
||||
/**@inheritdoc */
|
||||
async _onRender(context, options) {
|
||||
await super._onRender(context, options);
|
||||
this._createTagifyElements(this.options.tagifyConfigs);
|
||||
await this.#prepareInventoryDescription(context);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
|
@ -215,8 +224,8 @@ export default function DHApplicationMixin(Base) {
|
|||
/* -------------------------------------------- */
|
||||
|
||||
/**@inheritdoc */
|
||||
_syncPartState(partId, newElement, priorElement, state) {
|
||||
super._syncPartState(partId, newElement, priorElement, state);
|
||||
_preSyncPartState(partId, newElement, priorElement, state) {
|
||||
super._preSyncPartState(partId, newElement, priorElement, state);
|
||||
for (const el of priorElement.querySelectorAll('.extensible.extended')) {
|
||||
const { actionId, itemUuid } = el.parentElement.dataset;
|
||||
const selector = `${actionId ? `[data-action-id="${actionId}"]` : `[data-item-uuid="${itemUuid}"]`} .extensible`;
|
||||
|
|
@ -496,11 +505,12 @@ export default function DHApplicationMixin(Base) {
|
|||
|
||||
/**
|
||||
* Prepares and enriches an inventory item or action description for display.
|
||||
* @param {HTMLElement} element the element to enrich the inventory items of
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async #prepareInventoryDescription(context) {
|
||||
async #prepareInventoryDescription(element) {
|
||||
// Get all inventory item elements with a data-item-uuid attribute
|
||||
const inventoryItems = this.element.querySelectorAll('.inventory-item[data-item-uuid]');
|
||||
const inventoryItems = element.querySelectorAll('.inventory-item[data-item-uuid]');
|
||||
for (const el of inventoryItems) {
|
||||
// Get the doc uuid from the element
|
||||
const { itemUuid } = el?.dataset || {};
|
||||
|
|
@ -701,7 +711,7 @@ export default function DHApplicationMixin(Base) {
|
|||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #toChat(_event, target) {
|
||||
let doc = await getDocFromElement(target);
|
||||
const doc = await getDocFromElement(target);
|
||||
return doc.toChat(doc.uuid);
|
||||
}
|
||||
|
||||
|
|
@ -710,10 +720,19 @@ export default function DHApplicationMixin(Base) {
|
|||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #useItem(event, target) {
|
||||
let doc = await getDocFromElement(target);
|
||||
const doc = await getDocFromElement(target);
|
||||
await doc.use(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* View an item by opening its sheet
|
||||
* @type {ApplicationClickAction}
|
||||
*/
|
||||
static async #viewItem(_, target) {
|
||||
const doc = await getDocFromElement(target);
|
||||
await doc.sheet.render({ force: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle a ActiveEffect
|
||||
* @type {ApplicationClickAction}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ export default class DHBaseItemSheet extends DHApplicationMixin(ItemSheetV2) {
|
|||
|
||||
/**@inheritdoc */
|
||||
async _prepareContext(options) {
|
||||
const context = super._prepareContext(options);
|
||||
const context = await super._prepareContext(options);
|
||||
context.showAttribution = !game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance)
|
||||
.hideAttribution;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,49 @@
|
|||
export default class DhSidebar extends Sidebar {
|
||||
export default class DhSidebar extends foundry.applications.sidebar.Sidebar {
|
||||
/** @override */
|
||||
static TABS = {
|
||||
...super.TABS,
|
||||
chat: {
|
||||
documentName: 'ChatMessage'
|
||||
},
|
||||
combat: {
|
||||
documentName: 'Combat'
|
||||
},
|
||||
scenes: {
|
||||
documentName: 'Scene',
|
||||
gmOnly: true
|
||||
},
|
||||
actors: {
|
||||
documentName: 'Actor'
|
||||
},
|
||||
items: {
|
||||
documentName: 'Item'
|
||||
},
|
||||
journal: {
|
||||
documentName: 'JournalEntry',
|
||||
tooltip: 'SIDEBAR.TabJournal'
|
||||
},
|
||||
tables: {
|
||||
documentName: 'RollTable'
|
||||
},
|
||||
cards: {
|
||||
documentName: 'Cards'
|
||||
},
|
||||
macros: {
|
||||
documentName: 'Macro'
|
||||
},
|
||||
playlists: {
|
||||
documentName: 'Playlist'
|
||||
},
|
||||
compendium: {
|
||||
tooltip: 'SIDEBAR.TabCompendium',
|
||||
icon: 'fa-solid fa-book-atlas'
|
||||
},
|
||||
daggerheartMenu: {
|
||||
tooltip: 'DAGGERHEART.UI.Sidebar.daggerheartMenu.title',
|
||||
img: 'systems/daggerheart/assets/logos/FoundryBorneLogoWhite.svg'
|
||||
},
|
||||
settings: {
|
||||
tooltip: 'SIDEBAR.TabSettings',
|
||||
icon: 'fa-solid fa-gears'
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
this.selectedMenu = { path: [], data: null };
|
||||
this.config = CONFIG.DH.ITEMBROWSER.compendiumConfig;
|
||||
this.presets = {};
|
||||
this.compendiumBrowserTypeKey = 'compendiumBrowserDefault';
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
|
|
@ -84,10 +85,25 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
/** @inheritDoc */
|
||||
async _preRender(context, options) {
|
||||
this.presets = options.presets ?? {};
|
||||
|
||||
const width = this.presets?.render?.noFolder === true || this.presets?.render?.lite === true ? 600 : 850;
|
||||
if (this.rendered) this.setPosition({ width });
|
||||
else options.position.width = width;
|
||||
const noFolder = this.presets?.render?.noFolder;
|
||||
if (noFolder === true) {
|
||||
this.compendiumBrowserTypeKey = 'compendiumBrowserNoFolder';
|
||||
}
|
||||
const lite = this.presets?.render?.lite;
|
||||
if (lite === true) {
|
||||
this.compendiumBrowserTypeKey = 'compendiumBrowserLite';
|
||||
}
|
||||
const userPresetPosition = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS[`${this.compendiumBrowserTypeKey}`].position) ;
|
||||
|
||||
options.position = userPresetPosition ?? ItemBrowser.DEFAULT_OPTIONS.position;
|
||||
|
||||
if (!userPresetPosition) {
|
||||
const width = noFolder === true || lite === true ? 600 : 850;
|
||||
if (this.rendered)
|
||||
this.setPosition({ width });
|
||||
else
|
||||
options.position.width = width;
|
||||
}
|
||||
|
||||
await super._preRender(context, options);
|
||||
}
|
||||
|
|
@ -113,6 +129,10 @@ export class ItemBrowser extends HandlebarsApplicationMixin(ApplicationV2) {
|
|||
});
|
||||
}
|
||||
|
||||
_onPosition(position) {
|
||||
game.user.setFlag(CONFIG.DH.id, CONFIG.DH.FLAGS[`${this.compendiumBrowserTypeKey}`].position, position);
|
||||
}
|
||||
|
||||
_attachPartListeners(partId, htmlElement, options) {
|
||||
super._attachPartListeners(partId, htmlElement, options);
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,18 @@ export const encounterCountdown = {
|
|||
position: 'countdown-encounter-position'
|
||||
};
|
||||
|
||||
export const compendiumBrowserDefault = {
|
||||
position: 'compendium-browser-default-position'
|
||||
};
|
||||
|
||||
export const compendiumBrowserNoFolder = {
|
||||
position: 'compendium-browser-no-folder-position'
|
||||
};
|
||||
|
||||
export const compendiumBrowserLite = {
|
||||
position: 'compendium-browser-lite-position'
|
||||
};
|
||||
|
||||
export const itemAttachmentSource = 'attachmentSource';
|
||||
|
||||
export const userFlags = {
|
||||
|
|
|
|||
|
|
@ -370,19 +370,6 @@ export const typeConfig = {
|
|||
label: 'DAGGERHEART.ITEMS.Subclass.spellcastingTrait'
|
||||
}
|
||||
],
|
||||
filters: []
|
||||
},
|
||||
beastforms: {
|
||||
columns: [
|
||||
{
|
||||
key: 'system.tier',
|
||||
label: 'DAGGERHEART.GENERAL.Tiers.singular'
|
||||
},
|
||||
{
|
||||
key: 'system.mainTrait',
|
||||
label: 'DAGGERHEART.GENERAL.Trait.single'
|
||||
}
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
key: 'system.linkedClass.uuid',
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export default class CostField extends fields.ArrayField {
|
|||
static calcCosts(costs) {
|
||||
const resources = CostField.getResources.call(this, costs);
|
||||
let filteredCosts = costs;
|
||||
if (this.parent.metadata.isQuantifiable && this.parent.consumeOnUse === false) {
|
||||
if (this.parent?.metadata.isQuantifiable && this.parent.consumeOnUse === false) {
|
||||
filteredCosts = filteredCosts.filter(c => c.key !== 'quantity');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -501,6 +501,7 @@ export default class DhpActor extends Actor {
|
|||
/**@inheritdoc */
|
||||
getRollData() {
|
||||
const rollData = super.getRollData();
|
||||
rollData.name = this.name;
|
||||
rollData.system = this.system.getRollData();
|
||||
rollData.prof = this.system.proficiency ?? 1;
|
||||
rollData.cast = this.system.spellcastModifier ?? 1;
|
||||
|
|
|
|||
|
|
@ -1,29 +1,8 @@
|
|||
import { parseInlineParams } from './parser.mjs';
|
||||
|
||||
export default function DhDamageEnricher(match, _options) {
|
||||
const parts = match[1].split('|').map(x => x.trim());
|
||||
|
||||
let value = null,
|
||||
type = null,
|
||||
inline = false;
|
||||
|
||||
parts.forEach(part => {
|
||||
const split = part.split(':').map(x => x.toLowerCase().trim());
|
||||
if (split.length === 2) {
|
||||
switch (split[0]) {
|
||||
case 'value':
|
||||
value = split[1];
|
||||
break;
|
||||
case 'type':
|
||||
type = split[1];
|
||||
break;
|
||||
case 'inline':
|
||||
inline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!value || !value) return match[0];
|
||||
|
||||
const { value, type, inline } = parseInlineParams(match[1]);
|
||||
if (!value || !type) return match[0];
|
||||
return getDamageMessage(value, type, inline, match[0]);
|
||||
}
|
||||
|
||||
|
|
|
|||
8
module/enrichers/LookupEnricher.mjs
Normal file
8
module/enrichers/LookupEnricher.mjs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { parseInlineParams } from './parser.mjs';
|
||||
|
||||
export default function DhLookupEnricher(match, { rollData }) {
|
||||
const results = parseInlineParams(match[1], { first: 'formula'});
|
||||
const element = document.createElement('span');
|
||||
element.textContent = Roll.replaceFormulaData(String(results.formula), rollData);
|
||||
return element;
|
||||
}
|
||||
|
|
@ -1,49 +1,18 @@
|
|||
import { parseInlineParams } from './parser.mjs';
|
||||
|
||||
export default function DhTemplateEnricher(match, _options) {
|
||||
const parts = match[1].split('|').map(x => x.trim());
|
||||
|
||||
let type = null,
|
||||
range = null,
|
||||
angle = CONFIG.MeasuredTemplate.defaults.angle,
|
||||
direction = 0,
|
||||
inline = false;
|
||||
|
||||
parts.forEach(part => {
|
||||
const split = part.split(':').map(x => x.toLowerCase().trim());
|
||||
if (split.length === 2) {
|
||||
switch (split[0]) {
|
||||
case 'type':
|
||||
const matchedType = Object.values(CONFIG.DH.GENERAL.templateTypes).find(
|
||||
x => x.toLowerCase() === split[1]
|
||||
);
|
||||
type = matchedType;
|
||||
break;
|
||||
case 'range':
|
||||
if (Number.isNaN(Number(split[1]))) {
|
||||
const matchedRange = Object.values(CONFIG.DH.GENERAL.templateRanges).find(
|
||||
x => x.id.toLowerCase() === split[1] || x.short === split[1]
|
||||
);
|
||||
range = matchedRange?.id;
|
||||
} else {
|
||||
range = split[1];
|
||||
}
|
||||
break;
|
||||
case 'inline':
|
||||
inline = true;
|
||||
break;
|
||||
case 'angle':
|
||||
angle = split[1];
|
||||
break;
|
||||
case 'direction':
|
||||
direction = split[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!type || !range) return match[0];
|
||||
const params = parseInlineParams(match[1]);
|
||||
const { type, angle = CONFIG.MeasuredTemplate.defaults.angle, inline = false } = params;
|
||||
const direction = Number(params.direction) || 0;
|
||||
const range =
|
||||
params.range && Number.isNaN(params.range)
|
||||
? Object.values(CONFIG.DH.GENERAL.templateRanges).find(
|
||||
x => x.id.toLowerCase() === split[1] || x.short === split[1]
|
||||
)?.id
|
||||
: params.range;
|
||||
if (!(type in CONFIG.MeasuredTemplate.types) || !range) return match[0];
|
||||
|
||||
const label = game.i18n.localize(`DAGGERHEART.CONFIG.TemplateTypes.${type}`);
|
||||
|
||||
const rangeDisplay = Number.isNaN(Number(range)) ? game.i18n.localize(`DAGGERHEART.CONFIG.Range.${range}.name`) : range;
|
||||
|
||||
let angleDisplay = '';
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { default as DhDamageEnricher, renderDamageButton } from './DamageEnriche
|
|||
import { default as DhDualityRollEnricher, renderDualityButton } from './DualityRollEnricher.mjs';
|
||||
import { default as DhEffectEnricher } from './EffectEnricher.mjs';
|
||||
import { default as DhTemplateEnricher, renderMeasuredTemplate } from './TemplateEnricher.mjs';
|
||||
import { default as DhLookupEnricher } from './LookupEnricher.mjs';
|
||||
|
||||
export { DhDamageEnricher, DhDualityRollEnricher, DhEffectEnricher, DhTemplateEnricher };
|
||||
|
||||
|
|
@ -21,6 +22,10 @@ export const enricherConfig = [
|
|||
{
|
||||
pattern: /@Template\[(.*)\]({.*})?/g,
|
||||
enricher: DhTemplateEnricher
|
||||
},
|
||||
{
|
||||
pattern: /@Lookup\[(.*)\]({.*})?/g,
|
||||
enricher: DhLookupEnricher
|
||||
}
|
||||
];
|
||||
|
||||
|
|
|
|||
20
module/enrichers/parser.mjs
Normal file
20
module/enrichers/parser.mjs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* @param {string} paramString The parameter inside the brackets of something like @Template[] to parse
|
||||
* @param {Object} options
|
||||
* @param {string} options.first If set, the first parameter is treated as a value with this as its key
|
||||
* @returns {Record<string, string | undefined> | null}
|
||||
*/
|
||||
export function parseInlineParams(paramString, { first } = {}) {
|
||||
const parts = paramString.split('|').map(x => x.trim());
|
||||
const params = {};
|
||||
for (const [idx, param] of parts.entries()) {
|
||||
if (first && idx === 0) {
|
||||
params[first] = param;
|
||||
} else {
|
||||
const parts = param.split(':');
|
||||
params[parts[0]] = parts.length > 1 ? parts[1] : true;
|
||||
}
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue