Merge remote-tracking branch 'origin/dev' into feature/region-behaviours
This commit is contained in:
commit
85d820a9de
37 changed files with 650 additions and 201 deletions
|
|
@ -11,6 +11,11 @@ ARISO:
|
||||||
Abdulloh Fauzan:
|
Abdulloh Fauzan:
|
||||||
- icons/info-circle.svg (https://thenounproject.com/icon/information-4176576/) : Rights Purchased
|
- icons/info-circle.svg (https://thenounproject.com/icon/information-4176576/) : Rights Purchased
|
||||||
|
|
||||||
|
QOLBIN SALIIM:
|
||||||
|
- icons/arrow-left.svg (https://thenounproject.com/icon/arrow-1933583/) : Rights Purchased
|
||||||
|
- icons/arrow-right.svg (https://thenounproject.com/icon/arrow-1933581/) : Rights Purchased
|
||||||
|
- icons/arrow-compass.svg (https://thenounproject.com/icon/arrow-2052607/) : Rights Purchased
|
||||||
|
|
||||||
Soetarman Atmodjo:
|
Soetarman Atmodjo:
|
||||||
- icons/roll.svg (https://thenounproject.com/icon/dice-5195278/) : Rights Purchased
|
- icons/roll.svg (https://thenounproject.com/icon/dice-5195278/) : Rights Purchased
|
||||||
|
|
||||||
|
|
|
||||||
3
assets/icons/arrow-compass.svg
Normal file
3
assets/icons/arrow-compass.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m38.418 8.5469 59.746 36.863c2.2617 1.2695 2.4023 7.9102 0 9.3203l-59.746 36.863c-51.27 31.781-51.129-115.39 0-83.051z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 236 B |
3
assets/icons/arrow-left.svg
Normal file
3
assets/icons/arrow-left.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m41.461 8.6953-41.461 39.906c14.129 13.355 28.105 26.707 42.234 40.062 2.6406 2.6406 8.2305-1.707 8.2305-5.4336v-15.684c44.875 7.918 49.379 27.176 49.535 24.379 2.1758-50.621-49.535-56.523-49.535-61.801v-15.219c0-4.1914-5.9023-9.1602-9.0078-6.2109z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 366 B |
3
assets/icons/arrow-right.svg
Normal file
3
assets/icons/arrow-right.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg version="1.1" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m58.539 8.6953 41.461 39.906c-14.129 13.355-28.105 26.707-42.234 40.062-2.6406 2.6406-8.2305-1.707-8.2305-5.4336v-15.684c-44.875 7.918-49.379 27.176-49.535 24.379-2.1758-50.621 49.535-56.523 49.535-61.801v-15.219c0-4.1914 6.0547-9.1602 9.0078-6.2109z" fill-rule="evenodd"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 368 B |
|
|
@ -67,8 +67,10 @@
|
||||||
"easy": "Easy",
|
"easy": "Easy",
|
||||||
"normal": "Normal",
|
"normal": "Normal",
|
||||||
"tough": "Tough",
|
"tough": "Tough",
|
||||||
"hard": "Hard"
|
"hard": "Hard",
|
||||||
|
"random": "Random Condition"
|
||||||
},
|
},
|
||||||
|
"difficulty": "Difficulty",
|
||||||
"drag": "Drag",
|
"drag": "Drag",
|
||||||
"edit": "Edit",
|
"edit": "Edit",
|
||||||
"edge": "Edge",
|
"edge": "Edge",
|
||||||
|
|
@ -80,11 +82,23 @@
|
||||||
"guts": "Guts",
|
"guts": "Guts",
|
||||||
"location": "Location",
|
"location": "Location",
|
||||||
"move": "Move",
|
"move": "Move",
|
||||||
"path": {
|
"ordinals": {
|
||||||
"North": "North",
|
"North": {
|
||||||
"East": "East",
|
"full": "North",
|
||||||
"South": "South",
|
"abbv": "N"
|
||||||
"West": "West"
|
},
|
||||||
|
"East": {
|
||||||
|
"full": "East",
|
||||||
|
"abbv": "E"
|
||||||
|
},
|
||||||
|
"South": {
|
||||||
|
"full": "South",
|
||||||
|
"abbv": "S"
|
||||||
|
},
|
||||||
|
"West": {
|
||||||
|
"full": "West",
|
||||||
|
"abbv": "W"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"protection": "Protection",
|
"protection": "Protection",
|
||||||
"quantity": "Quantity",
|
"quantity": "Quantity",
|
||||||
|
|
@ -121,6 +135,20 @@
|
||||||
"condensedRange": {
|
"condensedRange": {
|
||||||
"name": "Condense Weapon Range Input",
|
"name": "Condense Weapon Range Input",
|
||||||
"hint": "With this enabled, the weapon range will be displayed as \"X / Y\" when editing a weapon. While disabled it will be as displayed as two different rows, one for Short Range and one for Long Range"
|
"hint": "With this enabled, the weapon range will be displayed as \"X / Y\" when editing a weapon. While disabled it will be as displayed as two different rows, one for Short Range and one for Long Range"
|
||||||
|
},
|
||||||
|
"sandsOfFateInitial": {
|
||||||
|
"name": "Sands of Fate Initial",
|
||||||
|
"hint": "What value should The Hourglass reset to when a Cryptic Event occurs"
|
||||||
|
},
|
||||||
|
"onCrypticEvent": {
|
||||||
|
"name": "Cryptic Event Alert",
|
||||||
|
"hint": "What happens when a cryptic event occurs by clicking the \"Next Delve Tour\" button in the HUD",
|
||||||
|
"options": {
|
||||||
|
"notif": "Notification",
|
||||||
|
"pause": "Pause Game",
|
||||||
|
"both": "Notification and Pause Game",
|
||||||
|
"nothing": "Do Nothing"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Apps": {
|
"Apps": {
|
||||||
|
|
@ -153,10 +181,17 @@
|
||||||
},
|
},
|
||||||
"warn": {
|
"warn": {
|
||||||
"cannot-go-negative": "\"{name}\" is unable to be a negative number."
|
"cannot-go-negative": "\"{name}\" is unable to be a negative number."
|
||||||
|
},
|
||||||
|
"info": {
|
||||||
|
"cryptic-event-alert": "A Cryptic Event Has Occured!"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"tooltips": {
|
"tooltips": {
|
||||||
"shield-bonus": "Shield Bonus: {value}"
|
"shield-bonus": "Shield Bonus: {value}",
|
||||||
|
"set-fate-to": "Set Fate to {ordinal}",
|
||||||
|
"current-tour": "Current Delve Tour",
|
||||||
|
"next-tour": "Next Delve Tour",
|
||||||
|
"prev-tour": "Previous Delve Tour"
|
||||||
},
|
},
|
||||||
"region": {
|
"region": {
|
||||||
"difficultyDelta": {
|
"difficultyDelta": {
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,7 @@ export class HeroSummaryCardV1 extends GenericAppMixin(HandlebarsApplicationMixi
|
||||||
ctx.fate.options = [
|
ctx.fate.options = [
|
||||||
{ label: `RipCrypt.common.empty`, v: `` },
|
{ label: `RipCrypt.common.empty`, v: `` },
|
||||||
...Object.values(gameTerms.FatePath)
|
...Object.values(gameTerms.FatePath)
|
||||||
.map(v => ({ label: `RipCrypt.common.path.${v}`, value: v })),
|
.map(v => ({ label: `RipCrypt.common.ordinals.${v}.full`, value: v })),
|
||||||
];
|
];
|
||||||
return ctx;
|
return ctx;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
251
module/Apps/DelveDiceHUD.mjs
Normal file
251
module/Apps/DelveDiceHUD.mjs
Normal file
|
|
@ -0,0 +1,251 @@
|
||||||
|
import { distanceBetweenFates, nextFate, previousFate } from "../utils/fates.mjs";
|
||||||
|
import { filePath } from "../consts.mjs";
|
||||||
|
import { gameTerms } from "../gameTerms.mjs";
|
||||||
|
import { localizer } from "../utils/Localizer.mjs";
|
||||||
|
import { Logger } from "../utils/Logger.mjs";
|
||||||
|
|
||||||
|
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
|
const { ContextMenu } = foundry.applications.ui;
|
||||||
|
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 },
|
||||||
|
{ 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`,
|
||||||
|
`hud`,
|
||||||
|
],
|
||||||
|
window: {
|
||||||
|
frame: false,
|
||||||
|
positioned: false,
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
tourDelta: this.#tourDelta,
|
||||||
|
setFate: this.#setFate,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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`),
|
||||||
|
},
|
||||||
|
sandsOfFate: {
|
||||||
|
template: filePath(`templates/Apps/DelveDiceHUD/tour/current.hbs`),
|
||||||
|
},
|
||||||
|
nextTour: {
|
||||||
|
template: filePath(`templates/Apps/DelveDiceHUD/tour/next.hbs`),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
// #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
|
||||||
|
*/
|
||||||
|
_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 };
|
||||||
|
|
||||||
|
new ContextMenu(
|
||||||
|
this.element,
|
||||||
|
`#delve-difficulty`,
|
||||||
|
[
|
||||||
|
...conditions.map(condition => ({
|
||||||
|
name: localizer(condition.label),
|
||||||
|
callback: DelveDiceHUD.#setDifficulty.bind(this, condition.value),
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
name: localizer(`RipCrypt.common.difficulties.random`),
|
||||||
|
callback: () => {
|
||||||
|
const condition = conditions[Math.floor(Math.random() * conditions.length)];
|
||||||
|
DelveDiceHUD.#setDifficulty.bind(this)(condition.value);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
{ jQuery: false, fixed: true },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
async _preparePartContext(partId, ctx, opts) {
|
||||||
|
ctx = await super._preparePartContext(partId, ctx, opts);
|
||||||
|
ctx.meta ??= {};
|
||||||
|
|
||||||
|
ctx.meta.editable = game.user.isGM;
|
||||||
|
|
||||||
|
switch (partId) {
|
||||||
|
case `sandsOfFate`: {
|
||||||
|
ctx.sandsOfFate = this._sandsOfFate;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `difficulty`: {
|
||||||
|
ctx.dc = this._difficulty;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
case `fateCompass`: {
|
||||||
|
ctx.fate = this._currentFate;
|
||||||
|
ctx.rotation = `${this._rotation}deg`;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Logger.log(`${partId} Context`, ctx);
|
||||||
|
return ctx;
|
||||||
|
};
|
||||||
|
|
||||||
|
async animate({ parts = [] } = {}) {
|
||||||
|
if (parts.includes(`fateCompass`)) {
|
||||||
|
this.#animateCompassTo();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (parts.includes(`sandsOfFate`)) {
|
||||||
|
this.#animateSandsTo();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#animateCompassTo(newFate) {
|
||||||
|
if (newFate === this._currentFate) { return };
|
||||||
|
|
||||||
|
/** @type {HTMLElement|undefined} */
|
||||||
|
const pointer = this.element.querySelector(`.compass-pointer`);
|
||||||
|
if (!pointer) { return };
|
||||||
|
|
||||||
|
newFate ??= game.settings.get(`ripcrypt`, `currentFate`);
|
||||||
|
|
||||||
|
let distance = distanceBetweenFates(this._currentFate, newFate);
|
||||||
|
if (distance === 3) { distance = -1 };
|
||||||
|
|
||||||
|
this._rotation += distance * 90;
|
||||||
|
|
||||||
|
pointer.style.setProperty(`transform`, `rotate(${this._rotation}deg)`);
|
||||||
|
this._currentFate = newFate;
|
||||||
|
};
|
||||||
|
|
||||||
|
#animateSandsTo(newSands) {
|
||||||
|
/** @type {HTMLElement|undefined} */
|
||||||
|
const sands = this.element.querySelector(`.sands-value`);
|
||||||
|
if (!sands) { return };
|
||||||
|
|
||||||
|
newSands ??= game.settings.get(`ripcrypt`, `sandsOfFate`);
|
||||||
|
|
||||||
|
sands.innerHTML = newSands;
|
||||||
|
this._sandsOfFate = newSands;
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Actions
|
||||||
|
/** @this {DelveDiceHUD} */
|
||||||
|
static async #tourDelta(_event, element) {
|
||||||
|
const delta = parseInt(element.dataset.delta);
|
||||||
|
const initial = game.settings.get(`ripcrypt`, `sandsOfFateInitial`);
|
||||||
|
let newSands = this._sandsOfFate + delta;
|
||||||
|
|
||||||
|
if (newSands > initial) {
|
||||||
|
Logger.info(`Cannot go to a previous Delve Tour above the initial value`);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newSands === 0) {
|
||||||
|
newSands = initial;
|
||||||
|
await this.alertCrypticEvent();
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (Math.sign(delta)) {
|
||||||
|
case -1: {
|
||||||
|
game.settings.set(`ripcrypt`, `currentFate`, nextFate(this._currentFate));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
game.settings.set(`ripcrypt`, `currentFate`, previousFate(this._currentFate));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.#animateSandsTo(newSands);
|
||||||
|
game.settings.set(`ripcrypt`, `sandsOfFate`, newSands);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @this {DelveDiceHUD} */
|
||||||
|
static async #setFate(_event, element) {
|
||||||
|
const fate = element.dataset.toFate;
|
||||||
|
this.#animateCompassTo(fate);
|
||||||
|
game.settings.set(`ripcrypt`, `currentFate`, fate);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** @this {DelveDiceHUD} */
|
||||||
|
static async #setDifficulty(value) {
|
||||||
|
this._difficulty = value;
|
||||||
|
game.settings.set(`ripcrypt`, `dc`, value);
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
|
||||||
|
// #region Public API
|
||||||
|
async alertCrypticEvent() {
|
||||||
|
const alertType = game.settings.get(`ripcrypt`, `onCrypticEvent`);
|
||||||
|
if (alertType === `nothing`) { return };
|
||||||
|
|
||||||
|
if ([`both`, `notif`].includes(alertType)) {
|
||||||
|
ui.notifications.info(
|
||||||
|
localizer(`RipCrypt.notifs.info.cryptic-event-alert`),
|
||||||
|
{ console: false },
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
if ([`both`, `pause`].includes(alertType) && game.user.isGM) {
|
||||||
|
game.togglePause(true, { broadcast: true });
|
||||||
|
};
|
||||||
|
};
|
||||||
|
// #endregion
|
||||||
|
};
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
import { filePath } from "../consts.mjs";
|
|
||||||
import { GenericAppMixin } from "./GenericApp.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 DelveTourApp extends GenericAppMixin(HandlebarsApplicationMixin(ApplicationV2)) {
|
|
||||||
// #region Options
|
|
||||||
static DEFAULT_OPTIONS = {
|
|
||||||
classes: [
|
|
||||||
`ripcrypt--CryptApp`,
|
|
||||||
],
|
|
||||||
window: {
|
|
||||||
title: `Delve Tour`,
|
|
||||||
frame: true,
|
|
||||||
positioned: true,
|
|
||||||
resizable: false,
|
|
||||||
minimizable: false,
|
|
||||||
},
|
|
||||||
position: {
|
|
||||||
width: `auto`,
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
randomCondition: this.#randomCondition,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
static PARTS = {
|
|
||||||
turnCount: {
|
|
||||||
template: filePath(`templates/Apps/CryptApp/turnCount.hbs`),
|
|
||||||
},
|
|
||||||
delveConditions: {
|
|
||||||
template: filePath(`templates/Apps/CryptApp/delveConditions.hbs`),
|
|
||||||
},
|
|
||||||
fate: {
|
|
||||||
template: filePath(`templates/Apps/CryptApp/fate.hbs`),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
// #endregion
|
|
||||||
|
|
||||||
// #region Lifecycle
|
|
||||||
async _renderFrame(options) {
|
|
||||||
const frame = await super._renderFrame(options);
|
|
||||||
this.window.close.remove(); // Prevent closing
|
|
||||||
return frame;
|
|
||||||
};
|
|
||||||
|
|
||||||
async _onRender(context, options) {
|
|
||||||
await super._onRender(context, options);
|
|
||||||
|
|
||||||
// Shortcut because users can't edit
|
|
||||||
if (!game.user.isGM) { return };
|
|
||||||
|
|
||||||
// Add event listener for the dropdown
|
|
||||||
if (options.parts.includes(`delveConditions`)) {
|
|
||||||
const select = this.element.querySelector(`#${this.id}-difficulty`);
|
|
||||||
select.addEventListener(`change`, async (ev) => {
|
|
||||||
const newDifficulty = parseInt(ev.target.value);
|
|
||||||
if (!Number.isNaN(newDifficulty)) {
|
|
||||||
await game.settings.set(`ripcrypt`, `dc`, newDifficulty);
|
|
||||||
};
|
|
||||||
this.render({ parts: [`delveConditions`] });
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
async _preparePartContext(partId, ctx, opts) {
|
|
||||||
ctx = await super._preparePartContext(partId, ctx, opts);
|
|
||||||
|
|
||||||
ctx.meta.editable = game.user.isGM;
|
|
||||||
|
|
||||||
switch (partId) {
|
|
||||||
case `delveConditions`: {
|
|
||||||
ctx = this._prepareDifficulty(ctx);
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
Logger.log(`${partId} Context`, ctx);
|
|
||||||
return ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
_prepareDifficulty(ctx) {
|
|
||||||
ctx.options = conditions;
|
|
||||||
ctx.difficulty = game.settings.get(`ripcrypt`, `dc`);
|
|
||||||
return ctx;
|
|
||||||
};
|
|
||||||
// #endregion
|
|
||||||
|
|
||||||
// #region Actions
|
|
||||||
static async #randomCondition() {
|
|
||||||
const dc = conditions[Math.floor(Math.random() * conditions.length)];
|
|
||||||
await game.settings.set(`ripcrypt`, `dc`, dc.value);
|
|
||||||
await this.render({ parts: [`delveConditions`] });
|
|
||||||
};
|
|
||||||
// #endregion
|
|
||||||
};
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { HeroSummaryCardV1 } from "./Apps/ActorSheets/HeroSummaryCardV1.mjs";
|
||||||
import { RichEditor } from "./Apps/RichEditor.mjs";
|
import { RichEditor } from "./Apps/RichEditor.mjs";
|
||||||
|
|
||||||
// Util imports
|
// Util imports
|
||||||
|
import { distanceBetweenFates, nextFate, previousFate } from "./utils/fates.mjs";
|
||||||
import { documentSorter } from "./consts.mjs";
|
import { documentSorter } from "./consts.mjs";
|
||||||
|
|
||||||
const { deepFreeze } = foundry.utils;
|
const { deepFreeze } = foundry.utils;
|
||||||
|
|
@ -24,6 +25,9 @@ Object.defineProperty(
|
||||||
},
|
},
|
||||||
utils: {
|
utils: {
|
||||||
documentSorter,
|
documentSorter,
|
||||||
|
distanceBetweenFates,
|
||||||
|
nextFate,
|
||||||
|
previousFate,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
writable: false,
|
writable: false,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { distanceBetweenFates } from "../utils/distanceBetweenFates.mjs";
|
import { distanceBetweenFates } from "../utils/fates.mjs";
|
||||||
|
|
||||||
export class RipCryptCombatant extends Combatant {
|
export class RipCryptCombatant extends Combatant {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
// Applications
|
// Applications
|
||||||
import { AllItemSheetV1 } from "../Apps/ItemSheets/AllItemSheetV1.mjs";
|
import { AllItemSheetV1 } from "../Apps/ItemSheets/AllItemSheetV1.mjs";
|
||||||
import { CombinedHeroSheet } from "../Apps/ActorSheets/CombinedHeroSheet.mjs";
|
import { CombinedHeroSheet } from "../Apps/ActorSheets/CombinedHeroSheet.mjs";
|
||||||
import { DelveTourApp } from "../Apps/DelveTourApp.mjs";
|
import { DelveDiceHUD } from "../Apps/DelveDiceHUD.mjs";
|
||||||
import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs";
|
import { HeroSkillsCardV1 } from "../Apps/ActorSheets/HeroSkillsCardV1.mjs";
|
||||||
import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs";
|
import { HeroSummaryCardV1 } from "../Apps/ActorSheets/HeroSummaryCardV1.mjs";
|
||||||
import { RipCryptCombatTracker } from "../Apps/sidebar/CombatTracker.mjs";
|
import { RipCryptCombatTracker } from "../Apps/sidebar/CombatTracker.mjs";
|
||||||
|
|
@ -39,7 +39,7 @@ Hooks.once(`init`, () => {
|
||||||
Logger.log(`Initializing`);
|
Logger.log(`Initializing`);
|
||||||
|
|
||||||
CONFIG.Combat.initiative.decimals = 2;
|
CONFIG.Combat.initiative.decimals = 2;
|
||||||
CONFIG.ui.crypt = DelveTourApp;
|
CONFIG.ui.delveDice = DelveDiceHUD;
|
||||||
|
|
||||||
// #region Settings
|
// #region Settings
|
||||||
registerMetaSettings();
|
registerMetaSettings();
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,7 @@ Hooks.once(`ready`, () => {
|
||||||
if (game.paused) { game.togglePause() };
|
if (game.paused) { game.togglePause() };
|
||||||
};
|
};
|
||||||
|
|
||||||
if (game.settings.get(`ripcrypt`, `showDelveTour`)) {
|
ui.delveDice.render({ force: true });
|
||||||
ui.crypt.render({ force: true });
|
|
||||||
};
|
|
||||||
|
|
||||||
// MARK: 1-time updates
|
// MARK: 1-time updates
|
||||||
if (!game.settings.get(`ripcrypt`, `firstLoadFinished`)) {
|
if (!game.settings.get(`ripcrypt`, `firstLoadFinished`)) {
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
import { gameTerms } from "../gameTerms.mjs";
|
||||||
|
|
||||||
|
const { StringField } = foundry.data.fields;
|
||||||
|
const { FatePath } = gameTerms;
|
||||||
|
|
||||||
export function registerMetaSettings() {
|
export function registerMetaSettings() {
|
||||||
game.settings.register(`ripcrypt`, `dc`, {
|
game.settings.register(`ripcrypt`, `dc`, {
|
||||||
scope: `world`,
|
scope: `world`,
|
||||||
|
|
@ -5,19 +10,32 @@ export function registerMetaSettings() {
|
||||||
config: false,
|
config: false,
|
||||||
requiresReload: false,
|
requiresReload: false,
|
||||||
onChange: () => {
|
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 () => {
|
||||||
|
ui.delveDice.animate({ parts: [`sandsOfFate`] });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
game.settings.register(`ripcrypt`, `currentFate`, {
|
game.settings.register(`ripcrypt`, `currentFate`, {
|
||||||
scope: `world`,
|
scope: `world`,
|
||||||
type: String,
|
type: new StringField({
|
||||||
|
blank: false,
|
||||||
|
nullable: false,
|
||||||
|
initial: FatePath.NORTH,
|
||||||
|
}),
|
||||||
config: false,
|
config: false,
|
||||||
requiresReload: false,
|
requiresReload: false,
|
||||||
onChange: async () => {
|
onChange: async () => {
|
||||||
await ui.crypt.render({ parts: [ `fate` ] });
|
ui.delveDice.animate({ parts: [`fateCompass`] });
|
||||||
await game.combat.setupTurns();
|
|
||||||
await ui.combat.render({ parts: [ `tracker` ] });
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,42 @@
|
||||||
|
const { NumberField, StringField } = foundry.data.fields;
|
||||||
|
|
||||||
export function registerWorldSettings() {
|
export function registerWorldSettings() {
|
||||||
game.settings.register(`ripcrypt`, `showDelveTour`, {
|
game.settings.register(`ripcrypt`, `sandsOfFateInitial`, {
|
||||||
name: `Delve Tour Popup`,
|
name: `RipCrypt.setting.sandsOfFateInitial.name`,
|
||||||
|
hint: `RipCrypt.setting.sandsOfFateInitial.hint`,
|
||||||
scope: `world`,
|
scope: `world`,
|
||||||
type: Boolean,
|
|
||||||
config: true,
|
config: true,
|
||||||
default: true,
|
|
||||||
requiresReload: false,
|
requiresReload: false,
|
||||||
|
type: new NumberField({
|
||||||
|
required: true,
|
||||||
|
min: 1,
|
||||||
|
step: 1,
|
||||||
|
max: 10,
|
||||||
|
initial: 8,
|
||||||
|
}),
|
||||||
|
onChange: async (newInitialSands) => {
|
||||||
|
const currentSands = game.settings.get(`ripcrypt`, `sandsOfFate`);
|
||||||
|
if (newInitialSands <= currentSands) {
|
||||||
|
game.settings.set(`ripcrypt`, `sandsOfFate`, newInitialSands);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.register(`ripcrypt`, `onCrypticEvent`, {
|
||||||
|
name: `RipCrypt.setting.onCrypticEvent.name`,
|
||||||
|
hint: `RipCrypt.setting.onCrypticEvent.hint`,
|
||||||
|
scope: `world`,
|
||||||
|
config: true,
|
||||||
|
requiresReload: false,
|
||||||
|
type: new StringField({
|
||||||
|
required: true,
|
||||||
|
initial: `notif`,
|
||||||
|
choices: {
|
||||||
|
"notif": `RipCrypt.setting.onCrypticEvent.options.notif`,
|
||||||
|
"pause": `RipCrypt.setting.onCrypticEvent.options.pause`,
|
||||||
|
"both": `RipCrypt.setting.onCrypticEvent.options.both`,
|
||||||
|
"nothing": `RipCrypt.setting.onCrypticEvent.options.nothing`,
|
||||||
|
},
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,38 @@ export function distanceBetweenFates(start, end) {
|
||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isOppositeFates(start, end)) {
|
if (start === end) {
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isOppositeFates(start, end) || isOppositeFates(end, start)) {
|
||||||
return 2;
|
return 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
let isForward = start === FatePath.SOUTH && end === FatePath.WEST;
|
let isForward = start === FatePath.SOUTH && end === FatePath.WEST;
|
||||||
isForward ||= start === FatePath.NORTH && end === FatePath.EAST;
|
isForward ||= start === FatePath.NORTH && end === FatePath.EAST;
|
||||||
|
isForward ||= start === FatePath.WEST && end === FatePath.NORTH;
|
||||||
|
isForward ||= start === FatePath.EAST && end === FatePath.SOUTH;
|
||||||
if (isForward) {
|
if (isForward) {
|
||||||
return 1;
|
return 1;
|
||||||
};
|
};
|
||||||
return 3;
|
return 3;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fateOrder = [
|
||||||
|
FatePath.WEST, // to make the .find not integer overflow
|
||||||
|
FatePath.NORTH,
|
||||||
|
FatePath.EAST,
|
||||||
|
FatePath.SOUTH,
|
||||||
|
FatePath.WEST,
|
||||||
|
];
|
||||||
|
|
||||||
|
export function nextFate(fate) {
|
||||||
|
const fateIndex = fateOrder.findIndex(f => f === fate);
|
||||||
|
return fateOrder[fateIndex + 1];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function previousFate(fate) {
|
||||||
|
const fateIndex = fateOrder.lastIndexOf(fate);
|
||||||
|
return fateOrder[fateIndex - 1];
|
||||||
|
};
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
<div>
|
|
||||||
<rc-border
|
|
||||||
var:border-color="var(--accent-1)"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
|
||||||
Difficulty
|
|
||||||
</div>
|
|
||||||
<div slot="content">
|
|
||||||
<span>{{ difficulty }}</span>
|
|
||||||
{{#if meta.editable}}
|
|
||||||
<div class="row">
|
|
||||||
<select id="{{meta.idp}}-difficulty">
|
|
||||||
{{ rc-options difficulty options localize=true }}
|
|
||||||
</select>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
data-action="randomCondition"
|
|
||||||
>
|
|
||||||
<rc-icon
|
|
||||||
name="icons/roll"
|
|
||||||
var:size="20px"
|
|
||||||
var:fill="var(--accent-3)"
|
|
||||||
></rc-icon>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
</rc-border>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<div>
|
|
||||||
<rc-border
|
|
||||||
var:border-color="var(--accent-1)"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
|
||||||
Fate
|
|
||||||
</div>
|
|
||||||
<div slot="content">
|
|
||||||
N
|
|
||||||
</div>
|
|
||||||
</rc-border>
|
|
||||||
</div>
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
.ripcrypt.ripcrypt--CryptApp {
|
|
||||||
max-width: initial;
|
|
||||||
min-width: initial;
|
|
||||||
|
|
||||||
> .window-header .window-title {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
> .window-content {
|
|
||||||
background: var(--base-background);
|
|
||||||
padding: 4px;
|
|
||||||
};
|
|
||||||
|
|
||||||
.row {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
<div>
|
|
||||||
<rc-border
|
|
||||||
var:border-color="var(--accent-1)"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
|
||||||
Turn
|
|
||||||
</div>
|
|
||||||
<div slot="content">
|
|
||||||
1
|
|
||||||
</div>
|
|
||||||
</rc-border>
|
|
||||||
</div>
|
|
||||||
14
templates/Apps/DelveDiceHUD/difficulty.hbs
Normal file
14
templates/Apps/DelveDiceHUD/difficulty.hbs
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
<div id="delve-difficulty">
|
||||||
|
<div
|
||||||
|
class="icon-container"
|
||||||
|
data-tooltip="RipCrypt.common.difficulty"
|
||||||
|
>
|
||||||
|
<span class="large">{{dc}}</span>
|
||||||
|
<rc-icon
|
||||||
|
class="hourglass"
|
||||||
|
name="icons/d8-outline"
|
||||||
|
var:size="34px"
|
||||||
|
var:fill="var(--accent-2)"
|
||||||
|
></rc-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
64
templates/Apps/DelveDiceHUD/fateCompass.hbs
Normal file
64
templates/Apps/DelveDiceHUD/fateCompass.hbs
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
<div id="fate-compass">
|
||||||
|
<div class="compass-container">
|
||||||
|
<div class="compass">
|
||||||
|
<rc-icon
|
||||||
|
class="compass-pointer"
|
||||||
|
name="icons/arrow-compass"
|
||||||
|
var:fill="var(--accent-3)"
|
||||||
|
var:size="1rem"
|
||||||
|
style="transform: rotate({{rotation}})"
|
||||||
|
></rc-icon>
|
||||||
|
{{#if meta.editable}}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: N;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="North"
|
||||||
|
data-tooltip="{{rc-i18n "RipCrypt.tooltips.set-fate-to" ordinal="@RipCrypt.common.ordinals.North.full"}}"
|
||||||
|
data-tooltip-direction="LEFT"
|
||||||
|
>
|
||||||
|
{{rc-i18n "RipCrypt.common.ordinals.North.abbv"}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: W;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="West"
|
||||||
|
data-tooltip="{{rc-i18n "RipCrypt.tooltips.set-fate-to" ordinal="@RipCrypt.common.ordinals.West.full"}}"
|
||||||
|
data-tooltip-direction="LEFT"
|
||||||
|
>
|
||||||
|
{{rc-i18n "RipCrypt.common.ordinals.West.abbv"}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: E;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="East"
|
||||||
|
data-tooltip="{{rc-i18n "RipCrypt.tooltips.set-fate-to" ordinal="@RipCrypt.common.ordinals.East.full"}}"
|
||||||
|
data-tooltip-direction="RIGHT"
|
||||||
|
>
|
||||||
|
{{rc-i18n "RipCrypt.common.ordinals.East.abbv"}}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="transparent"
|
||||||
|
style="grid-area: S;"
|
||||||
|
data-action="setFate"
|
||||||
|
data-to-fate="South"
|
||||||
|
data-tooltip="{{rc-i18n "RipCrypt.tooltips.set-fate-to" ordinal="@RipCrypt.common.ordinals.South.full"}}"
|
||||||
|
data-tooltip-direction="DOWN"
|
||||||
|
>
|
||||||
|
{{rc-i18n "RipCrypt.common.ordinals.South.abbv"}}
|
||||||
|
</button>
|
||||||
|
{{else}}
|
||||||
|
<span style="grid-area: N;">{{rc-i18n "RipCrypt.common.ordinals.North.abbv"}}</span>
|
||||||
|
<span style="grid-area: W;">{{rc-i18n "RipCrypt.common.ordinals.West.abbv"}}</span>
|
||||||
|
<span style="grid-area: E;">{{rc-i18n "RipCrypt.common.ordinals.East.abbv"}}</span>
|
||||||
|
<span style="grid-area: S;">{{rc-i18n "RipCrypt.common.ordinals.South.abbv"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
88
templates/Apps/DelveDiceHUD/style.css
Normal file
88
templates/Apps/DelveDiceHUD/style.css
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
#ripcrypt-delve-dice {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: max-content 2rem 90px 2rem 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#fate-compass {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: visible;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.compass-container {
|
||||||
|
position: absolute;
|
||||||
|
background: var(--DelveDice-background);
|
||||||
|
border-radius: 0 0 999px 999px;
|
||||||
|
padding: 4px;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compass {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
|
grid-template-rows: repeat(3, minmax(0, 1fr));
|
||||||
|
grid-template-areas:
|
||||||
|
". N ."
|
||||||
|
"W A E"
|
||||||
|
". S .";
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
background: var(--accent-2);
|
||||||
|
border-radius: 999px;
|
||||||
|
aspect-ratio: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.compass-pointer {
|
||||||
|
grid-area: A;
|
||||||
|
transition: 500ms transform;
|
||||||
|
transform: rotate(-90deg); /* North by default */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#the-hourglass,
|
||||||
|
#delve-difficulty {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.icon-container {
|
||||||
|
position: absolute;
|
||||||
|
width: 34px;
|
||||||
|
display: grid;
|
||||||
|
padding: 4px 0;
|
||||||
|
background: var(--accent-1);
|
||||||
|
border-radius: 8px;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
grid-row: 1 / -1;
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
z-index: 2;
|
||||||
|
align-self: center;
|
||||||
|
justify-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc-svg {
|
||||||
|
inset: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
templates/Apps/DelveDiceHUD/tour/current.hbs
Normal file
16
templates/Apps/DelveDiceHUD/tour/current.hbs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
<div id="the-hourglass">
|
||||||
|
<div
|
||||||
|
class="icon-container"
|
||||||
|
data-tooltip="RipCrypt.tooltips.current-tour"
|
||||||
|
>
|
||||||
|
<span class="sands-value">
|
||||||
|
{{sandsOfFate}}
|
||||||
|
</span>
|
||||||
|
<rc-svg
|
||||||
|
aria-hidden="true"
|
||||||
|
class="hourglass"
|
||||||
|
name="icons/hourglass"
|
||||||
|
var:fill="var(--accent-2)"
|
||||||
|
></rc-svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
22
templates/Apps/DelveDiceHUD/tour/next.hbs
Normal file
22
templates/Apps/DelveDiceHUD/tour/next.hbs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
<div>
|
||||||
|
{{!-- This is here to prevent height collapsing --}}
|
||||||
|
​
|
||||||
|
|
||||||
|
{{#if meta.editable}}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="icon"
|
||||||
|
data-action="tourDelta"
|
||||||
|
data-delta="-1"
|
||||||
|
aria-label="{{rc-i18n "RipCrypt.tooltips.next-tour"}}"
|
||||||
|
data-tooltip="RipCrypt.tooltips.next-tour"
|
||||||
|
data-tooltip-direction="RIGHT"
|
||||||
|
>
|
||||||
|
<rc-icon
|
||||||
|
name="icons/arrow-right"
|
||||||
|
var:size="0.75rem"
|
||||||
|
var:fill="currentColor"
|
||||||
|
></rc-icon>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
23
templates/Apps/DelveDiceHUD/tour/previous.hbs
Normal file
23
templates/Apps/DelveDiceHUD/tour/previous.hbs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<div>
|
||||||
|
{{!-- This is here to prevent height collapsing --}}
|
||||||
|
​
|
||||||
|
|
||||||
|
{{#if meta.editable}}
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="icon"
|
||||||
|
data-action="tourDelta"
|
||||||
|
data-delta="1"
|
||||||
|
aria-label="{{rc-i18n "RipCrypt.tooltips.prev-tour"}}"
|
||||||
|
data-tooltip="RipCrypt.tooltips.prev-tour"
|
||||||
|
data-tooltip-direction="LEFT"
|
||||||
|
>
|
||||||
|
<rc-icon
|
||||||
|
name="icons/arrow-left"
|
||||||
|
var:size="0.75rem"
|
||||||
|
var:fill="currentColor"
|
||||||
|
></rc-icon>
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
@import url("./AllItemSheetV1/style.css");
|
@import url("./AllItemSheetV1/style.css");
|
||||||
@import url("./CombinedHeroSheet/style.css");
|
@import url("./CombinedHeroSheet/style.css");
|
||||||
@import url("./CryptApp/style.css");
|
@import url("./CryptApp/style.css");
|
||||||
|
@import url("./DelveDiceHUD/style.css");
|
||||||
@import url("./DicePool/style.css");
|
@import url("./DicePool/style.css");
|
||||||
@import url("./HeroSummaryCardV1/style.css");
|
@import url("./HeroSummaryCardV1/style.css");
|
||||||
@import url("./HeroSkillsCardV1/style.css");
|
@import url("./HeroSkillsCardV1/style.css");
|
||||||
|
|
|
||||||
|
|
@ -30,4 +30,4 @@
|
||||||
label, input, select {
|
label, input, select {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
|
.ripcrypt.hud button,
|
||||||
.ripcrypt > .window-content button {
|
.ripcrypt > .window-content button {
|
||||||
all: revert;
|
all: revert;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 2px 4px;
|
padding: 2px 4px;
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: inherit;
|
||||||
background: var(--button-background);
|
background: var(--button-background);
|
||||||
color: var(--button-text);
|
color: var(--button-text);
|
||||||
|
|
||||||
|
|
@ -23,4 +26,10 @@
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.transparent {
|
||||||
|
background: inherit;
|
||||||
|
color: inherit;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud,
|
||||||
.ripcrypt > .window-content {
|
.ripcrypt > .window-content {
|
||||||
input, .input {
|
input, .input {
|
||||||
all: revert;
|
all: revert;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud,
|
||||||
.ripcrypt > .window-content {
|
.ripcrypt > .window-content {
|
||||||
ol {
|
ol {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud p,
|
||||||
.ripcrypt > .window-content p {
|
.ripcrypt > .window-content p {
|
||||||
&.warning {
|
&.warning {
|
||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud .pill-bar,
|
||||||
.ripcrypt > .window-content .pill-bar {
|
.ripcrypt > .window-content .pill-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud select,
|
||||||
.ripcrypt > .window-content select {
|
.ripcrypt > .window-content select {
|
||||||
all: revert;
|
all: revert;
|
||||||
appearance: auto;
|
appearance: auto;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud span,
|
||||||
.ripcrypt > .window-content span {
|
.ripcrypt > .window-content span {
|
||||||
&.small {
|
&.small {
|
||||||
font-size: var(--font-size-10)
|
font-size: var(--font-size-10)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
.ripcrypt.hud table,
|
||||||
.ripcrypt > .window-content table {
|
.ripcrypt > .window-content table {
|
||||||
all: revert;
|
all: revert;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,8 @@
|
||||||
--pill-input-background: var(--accent-2);
|
--pill-input-background: var(--accent-2);
|
||||||
--pill-input-disabled-text: white;
|
--pill-input-disabled-text: white;
|
||||||
--pill-input-disabled-background: black;
|
--pill-input-disabled-background: black;
|
||||||
|
|
||||||
|
/* Custom HUD Components */
|
||||||
|
--DelveDice-background: var(--accent-1);
|
||||||
|
--DelveDice-text: white;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,4 @@
|
||||||
|
|
||||||
--base-text: black;
|
--base-text: black;
|
||||||
--base-background: white;
|
--base-background: white;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue