mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-21 18:09:54 +02:00
rework fear tracker application, add static positions to hold the tracker, enhance token and bar display, create custom dragger and resize methods
This commit is contained in:
parent
79d6522614
commit
6f040532aa
9 changed files with 469 additions and 112 deletions
10
lang/en.json
10
lang/en.json
|
|
@ -2687,6 +2687,9 @@
|
||||||
"displayFear": {
|
"displayFear": {
|
||||||
"label": "Display Fear"
|
"label": "Display Fear"
|
||||||
},
|
},
|
||||||
|
"fearPosition": {
|
||||||
|
"label": "Fear Position"
|
||||||
|
},
|
||||||
"displayCountdownUI": {
|
"displayCountdownUI": {
|
||||||
"label": "Display Countdown UI"
|
"label": "Display Countdown UI"
|
||||||
},
|
},
|
||||||
|
|
@ -2738,6 +2741,13 @@
|
||||||
"token": "Tokens",
|
"token": "Tokens",
|
||||||
"bar": "Bar",
|
"bar": "Bar",
|
||||||
"hide": "Hide"
|
"hide": "Hide"
|
||||||
|
},
|
||||||
|
"fearPosition": {
|
||||||
|
"free": "Free",
|
||||||
|
"topCenter": "Top + Center",
|
||||||
|
"bottomCenter": "Bottom + Center",
|
||||||
|
"rightTop": "Right + Top",
|
||||||
|
"leftBottom": "Left + Bottom"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Automation": {
|
"Automation": {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs';
|
import { enrichedDualityRoll } from '../../enrichers/DualityRollEnricher.mjs';
|
||||||
import { enrichedFateRoll, getFateTypeData } from '../../enrichers/FateRollEnricher.mjs';
|
import { enrichedFateRoll, getFateTypeData } from '../../enrichers/FateRollEnricher.mjs';
|
||||||
import { getCommandTarget, rollCommandToJSON } from '../../helpers/utils.mjs';
|
import { getCommandTarget, rollCommandToJSON } from '../../helpers/utils.mjs';
|
||||||
|
import FearTracker from './fearTracker.mjs';
|
||||||
|
|
||||||
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
|
export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLog {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
|
@ -297,4 +298,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
const actor = game.actors.get(event.target.dataset.actorId);
|
const actor = game.actors.get(event.target.dataset.actorId);
|
||||||
new game.system.api.applications.dialogs.RiskItAllDialog(actor, resourceValue).render({ force: true });
|
new game.system.api.applications.dialogs.RiskItAllDialog(actor, resourceValue).render({ force: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_toggleNotifications({ closing = false } = {}) {
|
||||||
|
super._toggleNotifications(closing)
|
||||||
|
FearTracker.handleOffSet();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,14 @@ const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api;
|
||||||
export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV2) {
|
export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV2) {
|
||||||
constructor(options = {}) {
|
constructor(options = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
|
this._dragData = {
|
||||||
|
isDragging: false,
|
||||||
|
startX: 0,
|
||||||
|
startY: 0,
|
||||||
|
startLeft: 0,
|
||||||
|
startTop: 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @inheritDoc */
|
/** @inheritDoc */
|
||||||
|
|
@ -21,19 +29,20 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
classes: [],
|
classes: [],
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
window: {
|
window: {
|
||||||
frame: true,
|
frame: false,
|
||||||
title: 'DAGGERHEART.GENERAL.fear',
|
title: 'DAGGERHEART.GENERAL.fear',
|
||||||
positioned: true,
|
positioned: true,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minimizable: false
|
minimizable: false
|
||||||
},
|
},
|
||||||
|
classes: ['daggerheart', 'dh-style', 'fear-tracker'],
|
||||||
actions: {
|
actions: {
|
||||||
setFear: FearTracker.setFear,
|
setFear: FearTracker.setFear,
|
||||||
increaseFear: FearTracker.increaseFear
|
increaseFear: FearTracker.increaseFear
|
||||||
},
|
},
|
||||||
position: {
|
position: {
|
||||||
width: 222,
|
width: 540,
|
||||||
height: 222
|
height: 'auto'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -53,6 +62,10 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear;
|
return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).maxFear;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get fearPosition() {
|
||||||
|
return game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).fearPosition;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Rendering */
|
/* Rendering */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
@ -63,15 +76,51 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
current = this.currentFear,
|
current = this.currentFear,
|
||||||
max = this.maxFear,
|
max = this.maxFear,
|
||||||
percent = (current / max) * 100,
|
percent = (current / max) * 100,
|
||||||
isGM = game.user.isGM;
|
isGM = game.user.isGM,
|
||||||
|
locked = false,
|
||||||
|
isFree = this.fearPosition == 'free';
|
||||||
|
|
||||||
return { display, current, max, percent, isGM };
|
return { display, current, max, percent, isGM, locked, isFree };
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
async _preFirstRender(context, options) {
|
async _onRender(context, options) {
|
||||||
options.position =
|
await super._onRender(context, options);
|
||||||
game.user.getFlag(CONFIG.DH.id, 'app.resources.position') ?? FearTracker.DEFAULT_OPTIONS.position;
|
|
||||||
|
this.#setupDragging();
|
||||||
|
this.#setupResizing();
|
||||||
|
|
||||||
|
const fearPosition = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.appearance).fearPosition;
|
||||||
|
|
||||||
|
if (options.isFirstRender) FearTracker.handleOffSet();
|
||||||
|
if (!options.force) return;
|
||||||
|
|
||||||
|
switch (fearPosition) {
|
||||||
|
case 'topCenter':
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
document.getElementById('ui-top')?.appendChild(this.element);
|
||||||
|
break;
|
||||||
|
case 'bottomCenter':
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
document.getElementById('ui-bottom')?.prepend(this.element);
|
||||||
|
break;
|
||||||
|
case 'rightTop':
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
||||||
|
break;
|
||||||
|
case 'leftBottom':
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
document.getElementById('ui-left-column-1')?.appendChild(this.element);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
document.body?.appendChild(this.element);
|
||||||
|
const position =
|
||||||
|
game.user.getFlag(CONFIG.DH.id, 'app.resources.position') ?? FearTracker.DEFAULT_OPTIONS.position;
|
||||||
|
this.setPosition(position);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
|
|
@ -80,13 +129,39 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, this.maxFear);
|
await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear, this.maxFear);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPosition(position) {
|
handleStyleElement(fearPosition) {
|
||||||
game.user.setFlag(CONFIG.DH.id, 'app.resources.position', position);
|
const positions = {
|
||||||
|
free: 'free',
|
||||||
|
topCenter: 'top-center',
|
||||||
|
bottomCenter: 'bottom-center',
|
||||||
|
rightTop: 'right-top',
|
||||||
|
leftBottom: 'left-bottom'
|
||||||
|
}
|
||||||
|
|
||||||
|
const containsStyle = position => this.element.classList.contains(position);
|
||||||
|
|
||||||
|
Object.entries(positions).forEach(([key, value]) => {
|
||||||
|
if (containsStyle(value)) this.element.classList.remove(value);
|
||||||
|
})
|
||||||
|
|
||||||
|
this.element.classList.add(positions[fearPosition]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async close(options = {}) {
|
static handleOffSet() {
|
||||||
if (!options.allowed) return;
|
const fearTracker = document.getElementById('resources');
|
||||||
else super.close(options);
|
const hotbar = document.getElementById('hotbar');
|
||||||
|
|
||||||
|
if (!fearTracker) return;
|
||||||
|
|
||||||
|
const offset = Number(hotbar.style.getPropertyValue('--offset').replace(/px$/, '')) || 0;
|
||||||
|
|
||||||
|
if (offset > 0) return;
|
||||||
|
|
||||||
|
fearTracker.style.setProperty('--offset', `${offset - 13}px`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onPosition(position) {
|
||||||
|
game.user.setFlag(CONFIG.DH.id, 'app.resources.position', position);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setFear(event, target) {
|
static async setFear(event, target) {
|
||||||
|
|
@ -110,4 +185,118 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Dragging handlers */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
#setupDragging() {
|
||||||
|
const dragHandle = this.element.querySelector('.drag-handle');
|
||||||
|
if (!dragHandle) return;
|
||||||
|
dragHandle.addEventListener('mousedown', this.#onDragStart.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
#onDragStart(event) {
|
||||||
|
if (event.button !== 0) return;
|
||||||
|
this._dragData.isDragging = true;
|
||||||
|
this._dragData.startX = event.clientX;
|
||||||
|
this._dragData.startY = event.clientY;
|
||||||
|
const rect = this.element.getBoundingClientRect();
|
||||||
|
this._dragData.startLeft = rect.left;
|
||||||
|
this._dragData.startTop = rect.top;
|
||||||
|
this.element.style.cursor = 'grabbing';
|
||||||
|
|
||||||
|
this._dragHandler = this.#onDragging.bind(this);
|
||||||
|
this._dragEndHandler = this.#onDragEnd.bind(this);
|
||||||
|
window.addEventListener('mousemove', this._dragHandler);
|
||||||
|
window.addEventListener('mouseup', this._dragEndHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onDragging(event) {
|
||||||
|
if (!this._dragData.isDragging) return;
|
||||||
|
|
||||||
|
const dragX = event.clientX - this._dragData.startX;
|
||||||
|
const dragY = event.clientY - this._dragData.startY;
|
||||||
|
|
||||||
|
this.element.style.left = `${this._dragData.startLeft + dragX}px`;
|
||||||
|
this.element.style.top = `${this._dragData.startTop + dragY}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
#onDragEnd() {
|
||||||
|
if (!this._dragData.isDragging) return;
|
||||||
|
this._dragData.isDragging = false;
|
||||||
|
this.element.style.cursor = '';
|
||||||
|
|
||||||
|
if (this._dragHandler) window.removeEventListener('mousemove', this._dragHandler);
|
||||||
|
if (this._dragEndHandler) window.removeEventListener('mouseup', this._dragEndHandler);
|
||||||
|
|
||||||
|
const rect = this.element.getBoundingClientRect();
|
||||||
|
const pos = { top: rect.top, left: rect.left };
|
||||||
|
|
||||||
|
this.setPosition(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Resize handlers */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
#setupResizing() {
|
||||||
|
const resizeHandle = this.element.querySelector('.resize-handle');
|
||||||
|
if (!resizeHandle) return;
|
||||||
|
resizeHandle.addEventListener('mousedown', this.#onResizeStart.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
#onResizeStart(e) {
|
||||||
|
if (e.button !== 0) return;
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
let maxAllowedWidth = 10000;
|
||||||
|
|
||||||
|
this._resizeData = {
|
||||||
|
isResizing: true,
|
||||||
|
startX: e.clientX,
|
||||||
|
startY: e.clientY,
|
||||||
|
startWidth: this.element.offsetWidth,
|
||||||
|
startHeight: this.element.offsetHeight,
|
||||||
|
maxAllowedWidth: Math.max(50, maxAllowedWidth)
|
||||||
|
};
|
||||||
|
|
||||||
|
this._resizeHandler = this.#onResizing.bind(this);
|
||||||
|
this._resizeEndHandler = this.#onResizeEnd.bind(this);
|
||||||
|
window.addEventListener('mousemove', this._resizeHandler);
|
||||||
|
window.addEventListener('mouseup', this._resizeEndHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
#onResizing(e) {
|
||||||
|
if (!this._resizeData?.isResizing) return;
|
||||||
|
|
||||||
|
const currentDx = e.clientX - this._resizeData.startX;
|
||||||
|
const potentialWidth = Math.max(50, this._resizeData.startWidth + currentDx);
|
||||||
|
|
||||||
|
const width = Math.min(potentialWidth, this._resizeData.maxAllowedWidth);
|
||||||
|
|
||||||
|
this.element.style.width = `${width}px`;
|
||||||
|
|
||||||
|
if (width < 100) {
|
||||||
|
this.element.classList.add('narrow');
|
||||||
|
} else {
|
||||||
|
this.element.classList.remove('narrow');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#onResizeEnd() {
|
||||||
|
if (!this._resizeData?.isResizing) return;
|
||||||
|
this._resizeData.isResizing = false;
|
||||||
|
|
||||||
|
if (this._resizeHandler) window.removeEventListener('mousemove', this._resizeHandler);
|
||||||
|
if (this._resizeEndHandler) window.removeEventListener('mouseup', this._resizeEndHandler);
|
||||||
|
|
||||||
|
let width = parseFloat(this.element.style.width);
|
||||||
|
|
||||||
|
|
||||||
|
if (isNaN(width)) {
|
||||||
|
width = this.element.getBoundingClientRect().width;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setPosition({ width: width });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -924,6 +924,14 @@ export const fearDisplay = {
|
||||||
hide: { value: 'hide', label: 'DAGGERHEART.SETTINGS.Appearance.fearDisplay.hide' }
|
hide: { value: 'hide', label: 'DAGGERHEART.SETTINGS.Appearance.fearDisplay.hide' }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fearPosition = {
|
||||||
|
free: { value: 'free', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.free' },
|
||||||
|
topCenter: { value: 'topCenter', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.topCenter' },
|
||||||
|
bottomCenter: { value: 'bottomCenter', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.bottomCenter' },
|
||||||
|
rightTop: { value: 'rightTop', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.rightTop' },
|
||||||
|
leftBottom: { value: 'leftBottom', label: 'DAGGERHEART.SETTINGS.Appearance.fearPosition.leftBottom' }
|
||||||
|
};
|
||||||
|
|
||||||
export const basicOwnershiplevels = {
|
export const basicOwnershiplevels = {
|
||||||
0: { value: 0, label: 'OWNERSHIP.NONE' },
|
0: { value: 0, label: 'OWNERSHIP.NONE' },
|
||||||
2: { value: 2, label: 'OWNERSHIP.OBSERVER' },
|
2: { value: 2, label: 'OWNERSHIP.OBSERVER' },
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,11 @@ export default class DhAppearance extends foundry.abstract.DataModel {
|
||||||
choices: CONFIG.DH.GENERAL.fearDisplay,
|
choices: CONFIG.DH.GENERAL.fearDisplay,
|
||||||
initial: CONFIG.DH.GENERAL.fearDisplay.token.value
|
initial: CONFIG.DH.GENERAL.fearDisplay.token.value
|
||||||
}),
|
}),
|
||||||
|
fearPosition: new StringField({
|
||||||
|
required: true,
|
||||||
|
choices: CONFIG.DH.GENERAL.fearPosition,
|
||||||
|
initial: CONFIG.DH.GENERAL.fearPosition.free.value
|
||||||
|
}),
|
||||||
displayCountdownUI: new BooleanField({ initial: true }),
|
displayCountdownUI: new BooleanField({ initial: true }),
|
||||||
diceSoNice: new SchemaField({
|
diceSoNice: new SchemaField({
|
||||||
hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }),
|
hope: diceStyle({ fg: '#ffffff', bg: '#ffe760', outline: '#000000', edge: '#ffffff' }),
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
background: var(--background);
|
background: var(--background);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
opacity: var(--ui-fade-opacity);
|
opacity: var(--ui-fade-opacity);
|
||||||
transition: opacity var(--ui-fade-duration);
|
transition: opacity var(--ui-fade-delay) var(--ui-fade-duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.performance-low, .noblur) {
|
&:not(.performance-low, .noblur) {
|
||||||
|
|
@ -41,6 +41,7 @@
|
||||||
|
|
||||||
&:hover::before {
|
&:hover::before {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
transition: opacity var(--ui-fade-duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ui-right:has(#effects-display .effect-container) & {
|
#ui-right:has(#effects-display .effect-container) & {
|
||||||
|
|
|
||||||
|
|
@ -1,119 +1,221 @@
|
||||||
:root {
|
:root {
|
||||||
--shadow-text-stroke: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
--hotbar-size: 60px;
|
||||||
--fear-animation: background 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease, opacity 0.3s ease;
|
}
|
||||||
|
|
||||||
|
#interface.theme-dark,
|
||||||
|
body.theme-dark {
|
||||||
|
.daggerheart.dh-style.fear-tracker {
|
||||||
|
--background: url(../assets/parchments/dh-parchment-dark.png);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#interface.theme-light,
|
||||||
|
body.theme-light {
|
||||||
|
.daggerheart.dh-style.fear-tracker {
|
||||||
|
--background: url('../assets/parchments/dh-parchment-light.png') no-repeat center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ui-middle:has(#hotbar.sm),
|
||||||
|
#ui-middle:has(#hotbar.md.offset) {
|
||||||
|
#resources {
|
||||||
|
&.top-center,
|
||||||
|
&.bottom-center {
|
||||||
|
width: calc((var(--hotbar-size) * 5) + 32px) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#resources {
|
#resources {
|
||||||
|
position: static;
|
||||||
min-height: calc(var(--header-height) + 4rem);
|
min-height: calc(var(--header-height) + 4rem);
|
||||||
min-width: 4rem;
|
min-width: 4rem;
|
||||||
color: #d3d3d3;
|
color: #d3d3d3;
|
||||||
transition: var(--fear-animation);
|
pointer-events: all;
|
||||||
header,
|
padding: var(--spacer-8);
|
||||||
.controls,
|
max-width: 540px;
|
||||||
.window-resize-handle {
|
min-width: 100px;
|
||||||
transition: var(--fear-animation);
|
|
||||||
|
&::before {
|
||||||
|
content: ' ';
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
background: var(--background);
|
||||||
|
border-radius: 8px;
|
||||||
|
opacity: var(--ui-fade-opacity);
|
||||||
|
transition: opacity var(--ui-fade-delay) var(--ui-fade-duration);
|
||||||
|
|
||||||
}
|
}
|
||||||
.window-content {
|
|
||||||
padding: 0.5rem;
|
&:hover::before {
|
||||||
#resource-fear {
|
opacity: 1;
|
||||||
|
transition: opacity var(--ui-fade-duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.free {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.top-center,
|
||||||
|
&.bottom-center {
|
||||||
|
margin: 1rem 0;
|
||||||
|
width: 100% !important;
|
||||||
|
transform: translateX(var(--offset));
|
||||||
|
transition: all 250ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.right-top {
|
||||||
|
width: 300px;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.left-bottom {
|
||||||
|
width: 200px;
|
||||||
|
max-width: 200px;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.performance-low, .noblur) {
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ui-right:has(#effects-display .effect-container) & {
|
||||||
|
right: 62px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#resource-fear {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
.fear-header {
|
||||||
|
opacity: 1;
|
||||||
|
height: 18.75px;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.resize-handle {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fear-header {
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
pointer-events: all;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
opacity: 0;
|
||||||
|
height: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
.drag-handle {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fear-title {
|
||||||
|
font-size: var(--font-size-13);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.fear-tokens {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
gap: 0.5rem 0.25rem;
|
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
i {
|
justify-content: center;
|
||||||
font-size: var(--font-size-18);
|
gap: 0.5rem 0.25rem;
|
||||||
border: 1px solid rgba(0, 0, 0, 0.5);
|
|
||||||
|
.fear-token {
|
||||||
|
font-size: var(--font-size-16);
|
||||||
|
border: 1.5px double light-dark(@dark-15, @dark-golden-80);
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
aspect-ratio: 1;
|
aspect-ratio: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 3rem;
|
width: 2.5rem;
|
||||||
background-color: @primary-color-fear;
|
background-color: @primary-color-fear;
|
||||||
-webkit-box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.75);
|
color: @beige;
|
||||||
box-shadow: 0px 0px 5px 1px rgba(0, 0, 0, 0.75);
|
|
||||||
color: #d3d3d3;
|
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
|
text-shadow: none;
|
||||||
|
|
||||||
&.inactive {
|
&.inactive {
|
||||||
filter: grayscale(1) !important;
|
filter: grayscale(1) !important;
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.controls,
|
|
||||||
.resource-bar {
|
|
||||||
border: 2px solid rgb(153 122 79);
|
|
||||||
background-color: rgb(24 22 46);
|
|
||||||
}
|
|
||||||
.controls {
|
|
||||||
display: flex;
|
|
||||||
align-self: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 30px;
|
|
||||||
height: 30px;
|
|
||||||
font-size: var(--font-size-20);
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
&.disabled {
|
|
||||||
opacity: 0.5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.resource-bar {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 6px;
|
|
||||||
font-size: var(--font-size-20);
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
padding: 0.25rem 0.5rem;
|
|
||||||
flex: 1;
|
|
||||||
text-shadow: var(--shadow-text-stroke);
|
|
||||||
&:before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
width: var(--fear-percent);
|
|
||||||
max-width: 100%;
|
|
||||||
background: linear-gradient(90deg, rgba(2, 0, 38, 1) 0%, rgba(199, 1, 252, 1) 100%);
|
|
||||||
z-index: 0;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
span {
|
|
||||||
position: inherit;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
&.fear {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
&.isGM {
|
|
||||||
i {
|
|
||||||
cursor: pointer;
|
|
||||||
&:hover {
|
|
||||||
font-size: var(--font-size-20);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
button[data-action='close'] {
|
.resize-handle {
|
||||||
display: none;
|
position: absolute;
|
||||||
}
|
bottom: -12px;
|
||||||
&:not(:hover):not(.minimized) {
|
right: -9px;
|
||||||
background: transparent;
|
cursor: nwse-resize;
|
||||||
box-shadow: unset;
|
|
||||||
border-color: transparent;
|
|
||||||
header,
|
|
||||||
#resource-fear .controls,
|
|
||||||
.window-resize-handle {
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.resource-bar {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
height: 30px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.progress-bar {
|
||||||
|
position: absolute;
|
||||||
|
appearance: none;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid light-dark(@dark-15, @dark-golden-80);
|
||||||
|
border-radius: 999px;
|
||||||
|
z-index: 0;
|
||||||
|
background: @dark-blue;
|
||||||
|
|
||||||
|
&::-webkit-progress-bar {
|
||||||
|
border: none;
|
||||||
|
background: @dark-blue;
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
&::-webkit-progress-value {
|
||||||
|
background: linear-gradient(90deg, rgba(2, 0, 38, 1) 0%, rgba(199, 1, 252, 1) 100%);
|
||||||
|
border-radius: 999px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
margin: auto 0;
|
||||||
|
z-index: 2;
|
||||||
|
height: auto;
|
||||||
|
text-align: center;
|
||||||
|
font-size: var(--font-size-18);
|
||||||
|
color: @beige;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
color: light-dark(@dark, @beige);
|
||||||
|
|
||||||
|
.disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.isGM {
|
||||||
|
.fear-token {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: box-shadow 0.15s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 8px @primary-color-fear ;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
&:has(.fear-bar) {
|
|
||||||
min-width: 200px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@
|
||||||
value=setting.displayFear
|
value=setting.displayFear
|
||||||
localize=true}}
|
localize=true}}
|
||||||
{{formGroup
|
{{formGroup
|
||||||
|
fields.fearPosition
|
||||||
|
value=setting.fearPosition
|
||||||
|
localize=true}}
|
||||||
|
{{formGroup
|
||||||
fields.displayCountdownUI
|
fields.displayCountdownUI
|
||||||
value=setting.displayCountdownUI
|
value=setting.displayCountdownUI
|
||||||
localize=true}}
|
localize=true}}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,48 @@
|
||||||
<div>
|
<div>
|
||||||
<div id="resource-fear" class="{{#if isGM}}isGM{{/if}}">
|
<div id="resource-fear" class="fear-tracker {{#if isGM}}isGM{{/if}}">
|
||||||
|
{{#if isFree}}
|
||||||
|
<div class="fear-header">
|
||||||
|
<div class="drag-handle">
|
||||||
|
<i class="fa-solid fa-grip-vertical"></i>
|
||||||
|
</div>
|
||||||
|
<span class="fear-title">{{localize 'DAGGERHEART.GENERAL.fear'}}</span>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
{{#if (eq display 'token')}}
|
{{#if (eq display 'token')}}
|
||||||
{{#times max}}
|
<div class="fear-tokens">
|
||||||
<i class="fas fa-skull {{#if (gte @this ../current)}} inactive{{/if}}" style="filter: hue-rotate(calc(({{this}}/{{../max}})*75deg))" data-index="{{this}}" data-action="setFear"></i>
|
{{#times max}}
|
||||||
{{/times}}
|
<a
|
||||||
|
class="fear-token {{#if (gte @this ../current)}} inactive{{/if}}"
|
||||||
|
style="filter: hue-rotate(calc(({{this}}/{{../max}})*75deg))"
|
||||||
|
data-index="{{this}}" data-action="setFear"
|
||||||
|
>
|
||||||
|
<i class="fear-token fas fa-skull"></i>
|
||||||
|
</a>
|
||||||
|
{{/times}}
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (eq display 'bar')}}
|
{{#if (eq display 'bar')}}
|
||||||
{{#if isGM}}<div class="controls control-minus {{#if (lte current 0)}} disabled{{/if}}" data-increment="-1" data-action="increaseFear">-</div>{{/if}}
|
|
||||||
<div class="resource-bar fear-bar" style="--fear-percent: {{percent}}%">
|
<div class="resource-bar fear-bar" style="--fear-percent: {{percent}}%">
|
||||||
<span>{{current}}/{{max}}</span>
|
<progress
|
||||||
|
class='progress-bar stress-color'
|
||||||
|
value='{{current}}'
|
||||||
|
max='{{max}}'
|
||||||
|
></progress>
|
||||||
|
<h4 class="label">{{current}} / {{max}}</h4>
|
||||||
</div>
|
</div>
|
||||||
{{#if isGM}}<div class="controls control-plus {{#if (gte current max)}} disabled{{/if}}" data-increment="+1" data-action="increaseFear">+</div>{{/if}}
|
{{#if isGM}}
|
||||||
|
<div class="controls">
|
||||||
|
<a class="{{#if (lte current 0)}} disabled{{/if}}" data-increment="-1" data-action="increaseFear"><i class="fa-solid fa-minus"></i></a>
|
||||||
|
<a class="{{#if (gte current max)}} disabled{{/if}}" data-increment="+1" data-action="increaseFear"><i class="fa-solid fa-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isFree}}
|
||||||
|
<a class="resize-handle">
|
||||||
|
<i class="fa-solid fa-chevron-right" style="transform: rotate(45deg);"></i>
|
||||||
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue