diff --git a/module/Apps/DelveDiceHUD.mjs b/module/Apps/DelveDiceHUD.mjs index a487480..4e0d358 100644 --- a/module/Apps/DelveDiceHUD.mjs +++ b/module/Apps/DelveDiceHUD.mjs @@ -1,7 +1,17 @@ +import { distanceBetweenFates } from "../utils/distanceBetweenFates.mjs"; import { filePath } from "../consts.mjs"; +import { gameTerms } from "../gameTerms.mjs"; import { Logger } from "../utils/Logger.mjs"; const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api; +const { FatePath } = gameTerms; + +const CompassRotations = { + [FatePath.NORTH]: -90, + [FatePath.EAST]: 0, + [FatePath.SOUTH]: 90, + [FatePath.WEST]: 180, +}; const conditions = [ { label: `RipCrypt.common.difficulties.easy`, value: 4 }, @@ -17,7 +27,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { tag: `aside`, classes: [ `ripcrypt`, - `ripcrypt--DelveDiceHUD` + `ripcrypt--DelveDiceHUD`, ], window: { frame: false, @@ -25,6 +35,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { }, actions: { tourDelta: this.#tourDelta, + setFate: this.#setFate, }, }; @@ -38,7 +49,7 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { fateCompass: { template: filePath(`templates/Apps/DelveDiceHUD/fateCompass.hbs`), }, - currentTour: { + sandsOfFate: { template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`), }, nextTour: { @@ -47,6 +58,24 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { }; // #endregion + // #region Instance Data + /** + * The current number of degrees the compass pointer should be rotated, this + * is not stored in the DB since we only care about the initial rotation on + * reload, which is derived from the current fate. + * @type {Number} + */ + _rotation; + + constructor(...args) { + super(...args); + this._sandsOfFate = game.settings.get(`ripcrypt`, `sandsOfFate`); + this._currentFate = game.settings.get(`ripcrypt`, `currentFate`); + this._rotation = CompassRotations[this._currentFate]; + this._difficulty = game.settings.get(`ripcrypt`, `dc`); + }; + // #endregion + // #region Lifecycle /** * Injects the element into the Foundry UI in the top middle @@ -75,16 +104,17 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { ctx.meta.editable = game.user.isGM; switch (partId) { - case `currentTour`: { - await this._prepareTourContext(ctx); + case `sandsOfFate`: { + ctx.sandsOfFate = this._sandsOfFate; break; }; case `difficulty`: { - await this._prepareDifficultyContext(ctx); + ctx.dc = this._difficulty; break; }; case `fateCompass`: { - await this._prepareFateCompassContext(ctx); + ctx.fate = this._currentFate; + ctx.rotation = `${this._rotation}deg`; break; }; }; @@ -93,26 +123,40 @@ export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) { return ctx; }; - async _prepareTourContext(ctx) { - ctx.tour = game.settings.get(`ripcrypt`, `sandsOfFate`); + async animate({ parts = [] } = {}) { + if (parts.includes(`fateCompass`)) { + this.#animateCompassTo(); + }; + + if (parts.includes(`sandsOfFate`)) {}; }; - async _prepareDifficultyContext(ctx) { - ctx.dc = game.settings.get(`ripcrypt`, `dc`); - }; + #animateCompassTo(newFate) { + /** @type {HTMLElement|undefined} */ + const pointer = this.element.querySelector(`.compass-pointer`); + if (!pointer) { return }; - async _prepareFateCompassContext(ctx) { - ctx.direction = game.settings.get(`ripcrypt`, `currentFate`); - } + let distance = distanceBetweenFates(this._currentFate, newFate); + Logger.table({ newFate, fate: this._currentFate, distance, _rotation: this._rotation }); + if (distance === 3) { distance = -1 }; + + this._rotation += distance * 90; + + pointer.style.setProperty(`transform`, `rotate(${this._rotation}deg)`); + }; // #endregion // #region Actions - static async #tourDelta() { - ui.notifications.info(`Delve Tour Changed`, { console: false }); - }; + static async #tourDelta() {}; - static async #setFate() { - ui.notifications.info(`Fate Set!`, { console: false }); + /** @this {DelveDiceHUD} */ + static async #setFate(_event, element) { + const fate = element.dataset.toFate; + this.#animateCompassTo(fate); + + // must be done after animate, otherwise it won't change the rotation + this._currentFate = fate; + game.settings.set(`ripcrypt`, `currentFate`, fate); }; // #endregion }; diff --git a/templates/Apps/DelveDiceHUD/fateCompass.hbs b/templates/Apps/DelveDiceHUD/fateCompass.hbs index 75c0ed5..e4b74c0 100644 --- a/templates/Apps/DelveDiceHUD/fateCompass.hbs +++ b/templates/Apps/DelveDiceHUD/fateCompass.hbs @@ -1,16 +1,64 @@