diff --git a/system/CONSTANTS.mjs b/system/CONSTANTS.mjs index b34acb2..d839d23 100644 --- a/system/CONSTANTS.mjs +++ b/system/CONSTANTS.mjs @@ -1,14 +1,8 @@ +import { HELPERS } from "./helpers/HELPERS.mjs"; + export const SYSTEM_ID = "black-flag"; export const SYSTEM_NAME = "Black Flag 🏴"; -function isDebugging() { - return game.modules.get("_dev-mode")?.api?.getPackageDebugValue(SYSTEM_ID); -} - -function log(...args) { - if ( isDebugging() ) console.log(`${SYSTEM_NAME} |`, ...args); -} - /** * The expected distance units. * @type {{label: string}} @@ -252,10 +246,9 @@ const CHARACTER_BUILDER_MODES = { * @type {Object} */ export const SYSTEM = { + ...HELPERS, id: SYSTEM_ID, name: SYSTEM_NAME, - log, - isDebugging, TOOL_TYPES, SKILL_TYPES, PROFICIENCY_TYPES, diff --git a/system/datamodels/item/common/duration.mjs b/system/datamodels/item/common/duration.mjs new file mode 100644 index 0000000..ff8a3cc --- /dev/null +++ b/system/datamodels/item/common/duration.mjs @@ -0,0 +1,34 @@ +/** + * Data model template for a Duration, as may be used by Powers + * + * @property {string} type + * @mixin + */ +export default class DurationDataModel extends foundry.abstract.DataModel { + + /** @inheritdoc */ + static _enableV10Validation = true; + + /** @inheritDoc */ + static defineSchema() { + const fields = foundry.data.fields; + return { + // Store duration internally as rounds, translating into human readable on the fly + rounds: new fields.NumberField({ + required: false + }), + + // Describes when during a round an effect might end + // e.g. "end of target's turn" or "end of caster's turn" + special: new fields.StringField({ + required: false + }), + + type: new fields.StringField({ + required: true, + choices: ["instantaneous", "time", "permanent", "special"], + initial: "instantaneous" + }) + }; + } +} diff --git a/system/helpers/HELPERS.mjs b/system/helpers/HELPERS.mjs new file mode 100644 index 0000000..75133d8 --- /dev/null +++ b/system/helpers/HELPERS.mjs @@ -0,0 +1,9 @@ +import {isDebugging, log} from "./debug.mjs"; +import {convertToRounds, formatRounds} from "./roundHelpers.mjs"; + +export const HELPERS = { + convertToRounds, + formatRounds, + isDebugging, + log +}; diff --git a/system/helpers/debug.mjs b/system/helpers/debug.mjs new file mode 100644 index 0000000..148dc4e --- /dev/null +++ b/system/helpers/debug.mjs @@ -0,0 +1,9 @@ + +export function isDebugging() { + return game.modules.get("_dev-mode")?.api?.getPackageDebugValue(SYSTEM_ID); +} + +export function log(...args) { + if ( isDebugging() ) console.log(`${SYSTEM_NAME} |`, ...args); +} + diff --git a/system/helpers/roundHelpers.mjs b/system/helpers/roundHelpers.mjs new file mode 100644 index 0000000..83b84d5 --- /dev/null +++ b/system/helpers/roundHelpers.mjs @@ -0,0 +1,87 @@ +/** + * Formats rounds for human readable display + * + * 1 round is nominally a "turn" + * 10 rounds is a minute + * 600 rounds is an hour + * 14400 rounds is a day + * 1008000 is a week + * 4032000 is a month + * 48384000 is a year + * + * @param {number} rounds + * @returns {{number: number, unit: string}} + */ +export function formatRounds(rounds) { + if (rounds < 10) { + return { + number: rounds, + unit: "turns" + }; + } + + if (rounds < 600) { + return { + number: Math.floor(rounds / 10), + unit: "minutes" + }; + } + + if (rounds < 14400) { + return { + number: Math.floor(rounds / 600), + unit: "hours" + }; + } + + if (rounds < 1008000) { + return { + number: Math.floor(rounds / 14400), + unit: "days" + }; + } + + if (rounds < 4032000) { + return { + number: Math.floor(rounds / 1008000), + unit: "weeks" + }; + } + + if (rounds < 48384000) { + return { + number: Math.floor(rounds / 4032000), + unit: "months" + }; + } + + return { + number: Math.floor(rounds / 48384000), + unit: "years" + }; +} + +/** + * Converts an object of number and unit into a number of rounds + * @param {number} number + * @param {string} unit + * @returns {number} - a number of rounds + */ +export function convertToRounds(number, unit) { + switch (unit) { + case "turns": + return number; + case "minutes": + return number * 10; + case "hours": + return number * 600; + case "days": + return number * 14400; + case "weeks": + return number * 1008000; + case "months": + return number * 4032000; + case "years": + return number * 48384000; + } +}