diff --git a/daggerheart.mjs b/daggerheart.mjs index 7e77fbb3..a0cfd1b6 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -13,6 +13,8 @@ import { dualityRollEnricher } from './module/enrichers/DualityRollEnricher.mjs' import { getCommandTarget, rollCommandToJSON, setDiceSoNiceForDualityRoll } from './module/helpers/utils.mjs'; import { abilities } from './module/config/actorConfig.mjs'; import Resources from './module/applications/resources.mjs'; +import Countdowns from './module/applications/countdowns.mjs'; +import DhCountdowns from './module/data/countdowns.mjs'; globalThis.SYSTEM = SYSTEM; @@ -96,6 +98,7 @@ Hooks.once('init', () => { CONFIG.Token.rulerClass = DhpTokenRuler; CONFIG.ui.resources = Resources; + CONFIG.ui.countdowns = Countdowns; game.socket.on(`system.${SYSTEM.id}`, handleSocketEvent); @@ -111,6 +114,9 @@ Hooks.once('init', () => { Hooks.on('ready', () => { ui.resources = new CONFIG.ui.resources(); ui.resources.render({ force: true }); + + /* Temporary for ease of development. Countdown application should be opened through buttons somewhere */ + new CONFIG.ui.countdowns(DhCountdowns.CountdownCategories.narrative).render({ force: true }); }); Hooks.once('dicesoniceready', () => {}); diff --git a/lang/en.json b/lang/en.json index 39d5225c..bd5507a8 100755 --- a/lang/en.json +++ b/lang/en.json @@ -893,6 +893,29 @@ "Title": "Downtime" } }, + "Countdown": { + "FIELDS": { + "countdowns": { + "element": { + "name": { "label": "Name" }, + "progress": { + "current": { "label": "Current" }, + "max": { "label": "Max" }, + "type": { + "value": { "label": "Value" }, + "label": { "label": "Label", "hint": "Used for custom" } + } + } + } + } + }, + "Type": { + "Spotlight": "Spotlight", + "Custom": "Custom" + }, + "NewCountdown": "New Countdown", + "Title": "Countdowns" + }, "Sheets": { "PC": { "Name": "Name", diff --git a/module/applications/countdowns.mjs b/module/applications/countdowns.mjs new file mode 100644 index 00000000..bed16373 --- /dev/null +++ b/module/applications/countdowns.mjs @@ -0,0 +1,74 @@ +const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; + +export default class Countdowns extends HandlebarsApplicationMixin(ApplicationV2) { + constructor(basePath) { + super(); + + this.basePath = basePath; + } + + static DEFAULT_OPTIONS = { + id: 'countdown', + classes: [], + tag: 'form', + window: { + frame: true, + title: 'Countdowns', + resizable: true, + minimizable: true + }, + actions: { + addCountdown: this.addCountdown, + removeCountdown: this.removeCountdown + }, + form: { handler: this.updateData, submitOnChange: true } + }; + + static PARTS = { + countdowns: { + template: 'systems/daggerheart/templates/views/countdowns.hbs' + } + }; + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + const countdownData = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns)[this.basePath]; + + context.base = this.basePath; + context.source = countdownData.toObject(); + context.systemFields = countdownData.schema.fields; + context.countdownFields = context.systemFields.countdowns.element.fields; + + return context; + } + + static async updateData(event, _, formData) { + const data = foundry.utils.expandObject(formData.object); + const newSetting = foundry.utils.mergeObject( + game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns).toObject(), + data + ); + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, newSetting); + this.render(); + } + + static async addCountdown() { + const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); + await countdownSetting.updateSource({ + [`${this.basePath}.countdowns.${foundry.utils.randomID()}`]: { + name: game.i18n.localize('DAGGERHEART.Countdown.NewCountdown') + } + }); + + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject()); + this.render(); + } + + static async removeCountdown(_, target) { + const countdownSetting = game.settings.get(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns); + await countdownSetting.updateSource({ [`${this.basePath}.countdowns.-=${target.dataset.countdown}`]: null }); + + await game.settings.set(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, countdownSetting.toObject()); + this.render(); + } +} diff --git a/module/applications/settings.mjs b/module/applications/settings.mjs index a7eed1b9..be581093 100644 --- a/module/applications/settings.mjs +++ b/module/applications/settings.mjs @@ -4,6 +4,7 @@ import DhAppearance from '../data/settings/Appearance.mjs'; import DHAppearanceSettings from './settings/appearanceSettings.mjs'; import DhVariantRules from '../data/settings/VariantRules.mjs'; import DHVariantRuleSettings from './settings/variantRuleSettings.mjs'; +import DhCountdowns from '../data/countdowns.mjs'; class DhpAutomationSettings extends FormApplication { constructor(object = {}, options = {}) { @@ -287,6 +288,12 @@ export const registerDHSettings = () => { default: defaultLevelTiers }); + game.settings.register(SYSTEM.id, SYSTEM.SETTINGS.gameSettings.Countdowns, { + scope: 'world', + config: false, + type: DhCountdowns + }); + game.settings.registerMenu(SYSTEM.id, SYSTEM.SETTINGS.menu.Automation.Name, { name: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Name'), label: game.i18n.localize('DAGGERHEART.Settings.Menu.Automation.Label'), diff --git a/module/config/generalConfig.mjs b/module/config/generalConfig.mjs index fb596347..78a05ece 100644 --- a/module/config/generalConfig.mjs +++ b/module/config/generalConfig.mjs @@ -311,3 +311,14 @@ export const abilityCosts = { label: 'Stress' } }; + +export const countdownTypes = { + spotlight: { + id: 'spotlight', + label: 'DAGGERHEART.Countdown.Type.Spotlight' + }, + custom: { + id: 'custom', + label: 'DAGGERHEART.Countdown.Type.Custom' + } +}; diff --git a/module/config/settingsConfig.mjs b/module/config/settingsConfig.mjs index 3a33e61b..cbca6112 100644 --- a/module/config/settingsConfig.mjs +++ b/module/config/settingsConfig.mjs @@ -33,6 +33,7 @@ export const gameSettings = { }, DualityRollColor: 'DualityRollColor', LevelTiers: 'LevelTiers', + Countdowns: 'Countdowns', appearance: 'Appearance', variantRules: 'VariantRules' }; diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs new file mode 100644 index 00000000..280e49c6 --- /dev/null +++ b/module/data/countdowns.mjs @@ -0,0 +1,62 @@ +import { countdownTypes } from '../config/generalConfig.mjs'; + +export default class DhCountdowns extends foundry.abstract.DataModel { + static defineSchema() { + const fields = foundry.data.fields; + + return { + narrative: new fields.EmbeddedDataField(DhCountdownData), + combat: new fields.EmbeddedDataField(DhCountdownData) + }; + } + + static CountdownCategories = { narrative: 'narrative', combat: 'combat' }; +} + +class DhCountdownData extends foundry.abstract.DataModel { + static LOCALIZATION_PREFIXES = ['DAGGERHEART.Countdown']; // Nots ure why this won't work. Setting labels manually for now + + static defineSchema() { + const fields = foundry.data.fields; + return { + countdowns: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCountdown)) + }; + } +} + +class DhCountdown extends foundry.abstract.DataModel { + static defineSchema() { + const fields = foundry.data.fields; + return { + name: new fields.StringField({ + required: true, + label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.name.label' + }), + progress: new fields.SchemaField({ + current: new fields.NumberField({ + required: true, + integer: true, + initial: 0, + label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.progress.current.label' + }), + max: new fields.NumberField({ + required: true, + integer: true, + initial: 0, + label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.progress.max.label' + }), + type: new fields.SchemaField({ + value: new fields.StringField({ + required: true, + choices: countdownTypes, + initial: countdownTypes.spotlight.id, + label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.progress.type.value.label' + }), + label: new fields.StringField({ + label: 'DAGGERHEART.Countdown.FIELDS.countdowns.element.progress.type.label.label' + }) + }) + }) + }; + } +} diff --git a/templates/views/countdowns.hbs b/templates/views/countdowns.hbs new file mode 100644 index 00000000..2dade189 --- /dev/null +++ b/templates/views/countdowns.hbs @@ -0,0 +1,13 @@ +
\ No newline at end of file