Begin work on the updated delve dice HUD that is better in every way than the other version

This commit is contained in:
Oliver-Akins 2025-02-27 22:56:36 -07:00
parent 00228d3aae
commit c7342b6402
13 changed files with 169 additions and 7 deletions

View file

@ -0,0 +1,106 @@
import { filePath } from "../consts.mjs";
import { Logger } from "../utils/Logger.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
const conditions = [
{ label: `RipCrypt.common.difficulties.easy`, value: 4 },
{ label: `RipCrypt.common.difficulties.normal`, value: 5 },
{ label: `RipCrypt.common.difficulties.tough`, value: 6 },
{ label: `RipCrypt.common.difficulties.hard`, value: 7 },
];
export class DelveDiceHUD extends HandlebarsApplicationMixin(ApplicationV2) {
// #region Options
static DEFAULT_OPTIONS = {
id: `ripcrypt-delve-dice`,
tag: `aside`,
classes: [
`ripcrypt`,
`ripcrypt--DelveDiceHUD`
],
window: {
frame: false,
positioned: false,
},
actions: {
tourDelta: this.#tourDelta,
},
};
static PARTS = {
previousTour: {
template: filePath(`templates/Apps/DelveDiceHUD/tour/previous.hbs`),
},
difficulty: {
template: filePath(`templates/Apps/DelveDiceHUD/difficulty.hbs`),
},
fateCompass: {
template: filePath(`templates/Apps/DelveDiceHUD/fateCompass.hbs`),
},
currentTour: {
template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`),
},
nextTour: {
template: filePath(`templates/Apps/DelveDiceHUD/tour/next.hbs`),
},
};
// #endregion
// #region Lifecycle
/**
* Injects the element into the Foundry UI in the top middle
*/
_insertElement(element) {
const existing = document.getElementById(element.id);
if (existing) {
existing.replaceWith(element);
} else {
const parent = document.getElementById(`ui-top`);
parent.prepend(element);
};
};
async _onRender(context, options) {
await super._onRender(context, options);
// Shortcut because users can't edit
if (!game.user.isGM) { return };
};
async _preparePartContext(partId, ctx, opts) {
ctx = await super._preparePartContext(partId, ctx, opts);
ctx.meta ??= {};
ctx.meta.editable = game.user.isGM;
switch (partId) {
case `currentTour`: {
await this._prepareTourContext(ctx);
break;
};
case `difficulty`: {
await this._prepareDifficultyContext(ctx);
break;
};
};
Logger.log(`${partId} Context`, ctx);
return ctx;
};
async _prepareTourContext(ctx) {
ctx.tour = game.settings.get(`ripcrypt`, `sandsOfFate`);
};
async _prepareDifficultyContext(ctx) {
ctx.dc = game.settings.get(`ripcrypt`, `dc`);
}
// #endregion
// #region Actions
static async #tourDelta() {
ui.notifications.info(`Button Clicked!`, { console: false });
};
// #endregion
};

View file

@ -1,6 +1,7 @@
// Applications
import { AllItemSheetV1 } from "../Apps/ItemSheets/AllItemSheetV1.mjs";
import { CombinedHeroSheet } from "../Apps/ActorSheets/CombinedHeroSheet.mjs";
import { DelveDiceHUD } from "../Apps/DelveDiceHUD.mjs";
import { DelveTourApp } from "../Apps/DelveTourApp.mjs";
import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs";
import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs";
@ -39,6 +40,8 @@ Hooks.once(`init`, () => {
CONFIG.Combat.initiative.decimals = 2;
CONFIG.ui.crypt = DelveTourApp;
CONFIG.ui.delveDice = DelveDiceHUD;
// globalThis.delveDice = new DelveDiceHUD();
// #region Settings
registerMetaSettings();

View file

@ -23,6 +23,8 @@ Hooks.once(`ready`, () => {
ui.crypt.render({ force: true });
};
ui.delveDice.render({ force: true });
// MARK: 1-time updates
if (!game.settings.get(`ripcrypt`, `firstLoadFinished`)) {
// Update the turnMarker to be the RipCrypt defaults

View file

@ -5,20 +5,25 @@ export function registerMetaSettings() {
config: false,
requiresReload: false,
onChange: () => {
ui.crypt.render({ parts: [ `delveConditions` ]});
ui.delveDice.render({ parts: [`difficulty`] });
},
});
game.settings.register(`ripcrypt`, `sandsOfFate`, {
scope: `world`,
type: Number,
initial: 8,
config: false,
requiresReload: false,
onChange: async () => {},
});
game.settings.register(`ripcrypt`, `currentFate`, {
scope: `world`,
type: String,
config: false,
requiresReload: false,
onChange: async () => {
await ui.crypt.render({ parts: [ `fate` ] });
await game.combat.setupTurns();
await ui.combat.render({ parts: [ `tracker` ] });
},
onChange: async () => {},
});
game.settings.register(`ripcrypt`, `whoFirst`, {

View file

@ -0,0 +1,3 @@
<div>
Difficulty: {{dc}}
</div>

View file

@ -0,0 +1,3 @@
<div id="fate-compass">
North
</div>

View file

@ -0,0 +1,18 @@
#ripcrypt-delve-dice {
display: grid;
grid-template-columns: max-content 1fr 1fr 1fr max-content;
gap: 8px;
padding: 4px 1.5rem;
background: var(--DelveDice-background);
align-items: center;
justify-items: center;
pointer-events: all;
border-radius: 0 0 999px 999px;
button {
&:hover {
cursor: pointer;
}
}
}

View file

@ -0,0 +1,3 @@
<div>
The Hourglass
</div>

View file

@ -0,0 +1,7 @@
<button
type="button"
class="icon"
data-action="tourDelta"
>
&gt;
</button>

View file

@ -0,0 +1,7 @@
<button
type="button"
class="icon"
data-action="tourDelta"
>
&lt;
</button>

View file

@ -1,6 +1,7 @@
@import url("./AllItemSheetV1/style.css");
@import url("./CombinedHeroSheet/style.css");
@import url("./CryptApp/style.css");
@import url("./DelveDiceHUD/style.css");
@import url("./DicePool/style.css");
@import url("./HeroSummaryCardV1/style.css");
@import url("./HeroSkillsCardV1/style.css");

View file

@ -1,4 +1,4 @@
.ripcrypt > .window-content button {
.ripcrypt button {
all: revert;
outline: none;
border: none;

View file

@ -41,4 +41,8 @@
--pill-input-background: var(--accent-2);
--pill-input-disabled-text: white;
--pill-input-disabled-background: black;
/* Custom HUD Components */
--DelveDice-background: var(--accent-1);
--DelveDice-text: white;
}