From 044ecd9d55c18b273a54a697afdf92584cc472c8 Mon Sep 17 00:00:00 2001 From: WBHarry Date: Fri, 22 May 2026 17:17:21 +0200 Subject: [PATCH] Added an app to work on campaign frame things in --- daggerheart.mjs | 23 ++++++++++ lang/en.json | 3 ++ module/applications/_module.mjs | 1 + module/applications/campaignFrame/_module.mjs | 1 + .../campaignFrame/campaignFrames.mjs | 46 +++++++++++++++++++ .../sidebar/tabs/daggerheartMenu.mjs | 7 ++- module/data/_module.mjs | 1 + module/data/campaignFrames.mjs | 29 ++++++++++++ styles/less/dialog/campaign-frame/sheet.less | 32 +++++++++++++ styles/less/dialog/index.less | 2 + templates/campaignFrames/campaign-frames.hbs | 41 +++++++++++++++++ templates/sidebar/daggerheart-menu/main.hbs | 2 + 12 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 module/applications/campaignFrame/_module.mjs create mode 100644 module/applications/campaignFrame/campaignFrames.mjs create mode 100644 module/data/campaignFrames.mjs create mode 100644 styles/less/dialog/campaign-frame/sheet.less create mode 100644 templates/campaignFrames/campaign-frames.hbs diff --git a/daggerheart.mjs b/daggerheart.mjs index 363430be..b298829e 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -104,6 +104,7 @@ Hooks.once('init', () => { fields }; + game.system.campaignFrames = new game.system.api.data.CampaignFrames(); game.system.registeredTriggers = new game.system.api.data.RegisteredTriggers(); const { DocumentSheetConfig } = foundry.applications.apps; @@ -318,6 +319,28 @@ Hooks.on('ready', async () => { } } + /* Temporary for testing */ + game.system.campaignFrames.register({ + witherwild: { + name: 'Witherwild', + img: 'CampaignFrameStuff/Witherwild.png', + complexityRating: 1, + pitch: `
Fanewick was once a place of great abundance and peace + dangerous to those unfamiliar with the land, but a cornucopia + to those who respected its ways. When Haven invaded the + wilds and forced the land into eternal spring, a dangerous + bloom known as the Witherwild took hold and now threatens + the lives of all who live there. In a Witherwild campaign, + you’ll play unlikely heroes from humble beginnings who are + reckoning with their newfound duty to save Fanewick’s people + from dangerous corruption.
`, + toneAndFeel: 'Adventurous, Dynamic, Epic, Heroic, Thrilling, Uncanny, Whimsical', + themes: 'Cultural Clash, Ends Justify Means, Grief, People vs. Nature, Transformation and Change, Survival', + touchstones: 'Princess Mononoke, The Legend of Zelda, The Dark Crystal, Nausicaä of the Valley of the Wind' + } + }); + /* Temporary for testing */ + runMigrations(); }); diff --git a/lang/en.json b/lang/en.json index 0a9448c4..ecd7ed70 100755 --- a/lang/en.json +++ b/lang/en.json @@ -354,6 +354,9 @@ "Attribution": { "title": "Attribution" }, + "CampaignFrames": { + "title": "Campaign Frames" + }, "CharacterCreation": { "tabs": { "ancestry": "Ancestry", diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs index b2d3001a..796edd20 100644 --- a/module/applications/_module.mjs +++ b/module/applications/_module.mjs @@ -1,3 +1,4 @@ +export * as campaignFrame from './campaignFrame/_module.mjs'; export * as characterCreation from './characterCreation/_module.mjs'; export * as dialogs from './dialogs/_module.mjs'; export * as hud from './hud/_module.mjs'; diff --git a/module/applications/campaignFrame/_module.mjs b/module/applications/campaignFrame/_module.mjs new file mode 100644 index 00000000..e151e679 --- /dev/null +++ b/module/applications/campaignFrame/_module.mjs @@ -0,0 +1 @@ +export { default as CampaignFrames } from './campaignFrames.mjs'; diff --git a/module/applications/campaignFrame/campaignFrames.mjs b/module/applications/campaignFrame/campaignFrames.mjs new file mode 100644 index 00000000..c70fac28 --- /dev/null +++ b/module/applications/campaignFrame/campaignFrames.mjs @@ -0,0 +1,46 @@ +const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; +export default class DhCampaignFrames extends HandlebarsApplicationMixin(ApplicationV2) { + constructor() { + super({}); + } + + get title() { + return game.i18n.format('DAGGERHEART.APPLICATIONS.CampaignFrames.title'); + } + + static DEFAULT_OPTIONS = { + classes: ['daggerheart', 'dh-style', 'campaign-frame'], + position: { width: 640, height: 'auto' }, + window: { icon: 'fa-solid fa-globe' }, + actions: {} + }; + + static PARTS = { + application: { + id: 'campaign-frames', + template: 'systems/daggerheart/templates/campaignFrames/campaign-frames.hbs' + } + }; + + getCampaignFrameTabs(frames) { + for (const v of Object.values(frames)) { + v.active = this.tabGroups[v.group] + ? this.tabGroups[v.group] === v.id + : this.tabGroups.primary !== 'equipment' + ? v.active + : false; + v.cssClass = v.active ? 'active' : ''; + } + + return tabs; + } + + async _prepareContext(_options) { + const context = await super._prepareContext(_options); + + context.campaignFrames = game.system.campaignFrames.frames; + // context.campaignFrameTabs = this.getCampaignFrameTabs(context.campaignFrames); + + return context; + } +} diff --git a/module/applications/sidebar/tabs/daggerheartMenu.mjs b/module/applications/sidebar/tabs/daggerheartMenu.mjs index 86c1b8cb..5e1ec9a5 100644 --- a/module/applications/sidebar/tabs/daggerheartMenu.mjs +++ b/module/applications/sidebar/tabs/daggerheartMenu.mjs @@ -32,7 +32,8 @@ export default class DaggerheartMenu extends HandlebarsApplicationMixin(Abstract actions: { selectRefreshable: DaggerheartMenu.#selectRefreshable, refreshActors: DaggerheartMenu.#refreshActors, - createFallCollisionDamage: DaggerheartMenu.#createFallCollisionDamage + createFallCollisionDamage: DaggerheartMenu.#createFallCollisionDamage, + openCampaignFrames: DaggerheartMenu.#openCampaignFrames } }; @@ -91,4 +92,8 @@ export default class DaggerheartMenu extends HandlebarsApplicationMixin(Abstract sound: CONFIG.sounds.dice }); } + + static async #openCampaignFrames() { + new game.system.api.applications.campaignFrame.CampaignFrames().render({ force: true }); + } } diff --git a/module/data/_module.mjs b/module/data/_module.mjs index a54da0e1..028b3c8e 100644 --- a/module/data/_module.mjs +++ b/module/data/_module.mjs @@ -1,3 +1,4 @@ +export { default as CampaignFrames } from './campaignFrames.mjs'; export { default as DhCombat } from './combat.mjs'; export { default as DhCombatant } from './combatant.mjs'; export { default as DhRollTable } from './rollTable.mjs'; diff --git a/module/data/campaignFrames.mjs b/module/data/campaignFrames.mjs new file mode 100644 index 00000000..0a3a4150 --- /dev/null +++ b/module/data/campaignFrames.mjs @@ -0,0 +1,29 @@ +export default class DhCampaignFrames extends foundry.abstract.TypeDataModel { + static defineSchema() { + const fields = foundry.data.fields; + + return { + frames: new fields.TypedObjectField(new fields.EmbeddedDataField(DhCampaignFrame)) + }; + } + + register(frames) { + this.updateSource({ frames }); + } +} + +class DhCampaignFrame extends foundry.abstract.DataModel { + static defineSchema() { + const fields = foundry.data.fields; + + return { + name: new fields.StringField({ required: true }), + img: new fields.FilePathField({ initial: 'icons/svg/mountain.svg', categories: ['IMAGE'], base64: false }), + complexityRating: new fields.NumberField({ required: true, integer: true }), + pitch: new fields.HTMLField(), + toneAndFeel: new fields.StringField(), + themes: new fields.StringField(), + touchstones: new fields.StringField() + }; + } +} diff --git a/styles/less/dialog/campaign-frame/sheet.less b/styles/less/dialog/campaign-frame/sheet.less new file mode 100644 index 00000000..d7264a58 --- /dev/null +++ b/styles/less/dialog/campaign-frame/sheet.less @@ -0,0 +1,32 @@ +.application.daggerheart.dh-style.campaign-frame { + .campaign-frames-container { + display: flex; + flex-direction: column; + gap: 8px; + + .campaign-frame-container { + display: flex; + flex-direction: column; + gap: 8px; + + .information-container { + display: flex; + flex-direction: column; + gap: 4px; + + label { + font-size: var(--font-size-20); + } + + .subtext { + color: var(--beige-50); + font-style: italic; + } + + .italic { + font-style: italic; + } + } + } + } +} \ No newline at end of file diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index 11d9635e..183ea01a 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -42,3 +42,5 @@ @import './character-reset/sheet.less'; @import './compendiumBrowserPackDialog/sheet.less'; + +@import './campaign-frame/sheet.less'; \ No newline at end of file diff --git a/templates/campaignFrames/campaign-frames.hbs b/templates/campaignFrames/campaign-frames.hbs new file mode 100644 index 00000000..f81d5dc2 --- /dev/null +++ b/templates/campaignFrames/campaign-frames.hbs @@ -0,0 +1,41 @@ +
+ {{!-- --}} +
+ {{#each campaignFrames as |frame|}} + {{> ".frame" }} + {{/each}} +
+
+ +{{#*inline ".frame"}} +
+ {{name}} + +
+ +
+ +
{{localize "Read this section to your players to to introduce them to the campaign."}}
+
{{{pitch}}}
+
+
+ +
{{toneAndFeel}}
+
+
+ +
{{themes}}
+
+
+ +
{{touchstones}}
+
+
+
+{{/inline}} diff --git a/templates/sidebar/daggerheart-menu/main.hbs b/templates/sidebar/daggerheart-menu/main.hbs index a1ea8730..5c7c2d5b 100644 --- a/templates/sidebar/daggerheart-menu/main.hbs +++ b/templates/sidebar/daggerheart-menu/main.hbs @@ -35,4 +35,6 @@ + +