import { diceSoNicePresets } from '../config/generalConfig.mjs'; export const loadCompendiumOptions = async compendiums => { const compendiumValues = []; for (var compendium of compendiums) { const values = await getCompendiumOptions(compendium); compendiumValues.push(values); } return compendiumValues; }; const getCompendiumOptions = async compendium => { const compendiumPack = await game.packs.get(compendium); const values = []; for (var value of compendiumPack.index) { const document = await compendiumPack.getDocument(value._id); values.push(document); } return values; }; export const getWidthOfText = (txt, fontsize, allCaps, bold) => { const text = allCaps ? txt.toUpperCase() : txt; if (getWidthOfText.c === undefined) { getWidthOfText.c = document.createElement('canvas'); getWidthOfText.ctx = getWidthOfText.c.getContext('2d'); } var fontspec = `${bold ? 'bold' : ''} ${fontsize}px` + ' ' + 'Signika, sans-serif'; if (getWidthOfText.ctx.font !== fontspec) getWidthOfText.ctx.font = fontspec; return getWidthOfText.ctx.measureText(text).width; }; export const padArray = (arr, len, fill) => { return arr.concat(Array(len).fill(fill)).slice(0, len); }; export const getTier = (level, asNr) => { switch (Math.floor((level + 1) / 3)) { case 1: return asNr ? 1 : 'tier1'; case 2: return asNr ? 2 : 'tier2'; case 3: return asNr ? 3 : 'tier3'; default: return asNr ? 0 : 'tier0'; } }; export const capitalize = string => { return string.charAt(0).toUpperCase() + string.slice(1); }; export const getPathValue = (path, entity, numeric) => { const pathValue = foundry.utils.getProperty(entity, path); if (pathValue) return numeric ? Number.parseInt(pathValue) : pathValue; return numeric ? Number.parseInt(path) : path; }; export const generateId = (title, length) => { const id = title .split(' ') .map((w, i) => { const p = w.slugify({ replacement: '', strict: true }); return i ? p.titleCase() : p; }) .join(''); return Number.isNumeric(length) ? id.slice(0, length).padEnd(length, '0') : id; }; export function rollCommandToJSON(text) { if (!text) return {}; // Match key="quoted string" OR key=unquotedValue const PAIR_RE = /(\w+)=("(?:[^"\\]|\\.)*"|\S+)/g; const result = {}; for (const [, key, raw] of text.matchAll(PAIR_RE)) { let value; if (raw.startsWith('"') && raw.endsWith('"')) { // Strip the surrounding quotes, un-escape any \" sequences value = raw.slice(1, -1).replace(/\\"/g, '"'); } else if (/^(true|false)$/i.test(raw)) { // Boolean value = raw.toLowerCase() === 'true'; } else if (!Number.isNaN(Number(raw))) { // Numeric value = Number(raw); } else { // Fallback to string value = raw; } result[key] = value; } return Object.keys(result).length > 0 ? result : null; } export const getCommandTarget = () => { let target = game.canvas.tokens.controlled.length > 0 ? game.canvas.tokens.controlled[0].actor : null; if (!game.user.isGM) { target = game.user.character; if (!target) { ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.NoAssignedPlayerCharacter')); return null; } } if (!target) { ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.NoSelectedToken')); return null; } if (target.type !== 'pc') { ui.notifications.error(game.i18n.localize('DAGGERHEART.Notification.Error.OnlyUseableByPC')); return null; } return target; }; export const setDiceSoNiceForDualityRoll = (rollResult, advantage, disadvantage) => { rollResult.dice[0].options.appearance = diceSoNicePresets.hope; rollResult.dice[1].options.appearance = diceSoNicePresets.fear; if (advantage) { rollResult.dice[2].options.appearance = diceSoNicePresets.advantage; } else if (disadvantage) { rollResult.dice[2].options.appearance = diceSoNicePresets.disadvantage; } };