Add animation and editing support for the fate compass
This commit is contained in:
parent
7c8d6a7208
commit
7639962130
2 changed files with 115 additions and 23 deletions
|
|
@ -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
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,16 +1,64 @@
|
|||
<div id="fate-compass">
|
||||
<div class="compass-container">
|
||||
<div class="compass">
|
||||
<button type="button" class="transparent" style="grid-area: N;">N</button>
|
||||
<button type="button" class="transparent" style="grid-area: W;">W</button>
|
||||
<rc-icon
|
||||
class="compass-pointer"
|
||||
name="icons/arrow-compass"
|
||||
var:fill="var(--accent-3)"
|
||||
var:size="1rem"
|
||||
style="transform: rotate({{rotation}})"
|
||||
></rc-icon>
|
||||
<button type="button" class="transparent" style="grid-area: E;">E</button>
|
||||
<button type="button" class="transparent" style="grid-area: S;">S</button>
|
||||
{{#if meta.editable}}
|
||||
<button
|
||||
type="button"
|
||||
class="transparent"
|
||||
style="grid-area: N;"
|
||||
data-action="setFate"
|
||||
data-to-fate="North"
|
||||
data-tooltip="Set Fate to North"
|
||||
data-tooltip-direction="LEFT"
|
||||
>
|
||||
N
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="transparent"
|
||||
style="grid-area: W;"
|
||||
data-action="setFate"
|
||||
data-to-fate="West"
|
||||
data-tooltip="Set Fate to West"
|
||||
data-tooltip-direction="LEFT"
|
||||
>
|
||||
W
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="transparent"
|
||||
style="grid-area: E;"
|
||||
data-action="setFate"
|
||||
data-to-fate="East"
|
||||
data-tooltip="Set Fate to East"
|
||||
data-tooltip-direction="RIGHT"
|
||||
>
|
||||
E
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="transparent"
|
||||
style="grid-area: S;"
|
||||
data-action="setFate"
|
||||
data-to-fate="South"
|
||||
data-tooltip="Set Fate to South"
|
||||
data-tooltip-direction="DOWN"
|
||||
>
|
||||
S
|
||||
</button>
|
||||
{{else}}
|
||||
<span style="grid-area: N;">N</span>
|
||||
<span style="grid-area: W;">W</span>
|
||||
<span style="grid-area: E;">E</span>
|
||||
<span style="grid-area: S;">S</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue