mirror of
https://github.com/Foundryborne/daggerheart.git
synced 2026-07-24 03:19:55 +02:00
Merge branch 'main' into feature/combo-dice-modifier
This commit is contained in:
commit
c711fb7321
30 changed files with 772 additions and 145 deletions
35
lang/en.json
35
lang/en.json
|
|
@ -126,6 +126,15 @@
|
||||||
"damageOnSave": "Damage on Save",
|
"damageOnSave": "Damage on Save",
|
||||||
"useDefaultItemValues": "Use default Item values"
|
"useDefaultItemValues": "Use default Item values"
|
||||||
},
|
},
|
||||||
|
"Reload": {
|
||||||
|
"checkReload": "Check Reload",
|
||||||
|
"reloadRequired": "Reload Required!",
|
||||||
|
"notRolled": "Not Rolled",
|
||||||
|
"checkFailed": "Check Failed",
|
||||||
|
"checkPassed": "Check Passed",
|
||||||
|
"rerollConfirmationTitle": "Reroll Reload Check",
|
||||||
|
"rerollConfirmationText": "Are you sure you want to reload the reload check?"
|
||||||
|
},
|
||||||
"RollField": {
|
"RollField": {
|
||||||
"diceRolling": {
|
"diceRolling": {
|
||||||
"compare": "Should be",
|
"compare": "Should be",
|
||||||
|
|
@ -1322,6 +1331,11 @@
|
||||||
"short": "V. Far"
|
"short": "V. Far"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ReloadChoices": {
|
||||||
|
"off": { "label": "Don't Use" },
|
||||||
|
"manual": { "label": "Manual" },
|
||||||
|
"auto": { "label": "Automatic" }
|
||||||
|
},
|
||||||
"RollTypes": {
|
"RollTypes": {
|
||||||
"trait": {
|
"trait": {
|
||||||
"name": "Trait"
|
"name": "Trait"
|
||||||
|
|
@ -2221,7 +2235,9 @@
|
||||||
},
|
},
|
||||||
"Resource": {
|
"Resource": {
|
||||||
"single": "Resource",
|
"single": "Resource",
|
||||||
"plural": "Resources"
|
"plural": "Resources",
|
||||||
|
"unloaded": "The weapon is not loaded",
|
||||||
|
"loaded": "The weapon is loaded"
|
||||||
},
|
},
|
||||||
"Roll": {
|
"Roll": {
|
||||||
"attack": "Attack Roll",
|
"attack": "Attack Roll",
|
||||||
|
|
@ -2688,6 +2704,9 @@
|
||||||
"displayFear": {
|
"displayFear": {
|
||||||
"label": "Display Fear"
|
"label": "Display Fear"
|
||||||
},
|
},
|
||||||
|
"fearPosition": {
|
||||||
|
"label": "Fear Position"
|
||||||
|
},
|
||||||
"displayCountdownUI": {
|
"displayCountdownUI": {
|
||||||
"label": "Display Countdown UI"
|
"label": "Display Countdown UI"
|
||||||
},
|
},
|
||||||
|
|
@ -2739,6 +2758,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": {
|
||||||
|
|
@ -2797,6 +2823,10 @@
|
||||||
"hint": "Effects with defined range dependency will automatically turn on/off depending on range"
|
"hint": "Effects with defined range dependency will automatically turn on/off depending on range"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"reload": {
|
||||||
|
"label": "Reload Checking",
|
||||||
|
"hint": "If the system should automatically roll reload checks or wait for the manual press of a button in chat"
|
||||||
|
},
|
||||||
"resourceScrollTexts": {
|
"resourceScrollTexts": {
|
||||||
"label": "Show Resource Change Scrolltexts",
|
"label": "Show Resource Change Scrolltexts",
|
||||||
"hint": "When a character is damaged, uses armor etc, a scrolling text will briefly appear by the token to signify this."
|
"hint": "When a character is damaged, uses armor etc, a scrolling text will briefly appear by the token to signify this."
|
||||||
|
|
@ -3259,7 +3289,8 @@
|
||||||
"lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}",
|
"lackingItemTransferPermission": "User {user} lacks owner permission needed to transfer items to {target}",
|
||||||
"noTokenTargeted": "No token is targeted",
|
"noTokenTargeted": "No token is targeted",
|
||||||
"behaviorRegionRequiresGM": "Creating a Region with an attached Behavior requires an online GM",
|
"behaviorRegionRequiresGM": "Creating a Region with an attached Behavior requires an online GM",
|
||||||
"comboDiceOnlyTwoDiceError": "Combo dice functionality only works on a single pair of two dice"
|
"comboDiceOnlyTwoDiceError": "Combo dice functionality only works on a single pair of two dice",
|
||||||
|
"reloadRequired": "The {weapon} must be reloaded to be used!"
|
||||||
},
|
},
|
||||||
"Progress": {
|
"Progress": {
|
||||||
"migrationLabel": "Performing system migration. Please wait and do not close Foundry."
|
"migrationLabel": "Performing system migration. Please wait and do not close Foundry."
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import DhDeathMove from '../../dialogs/deathMove.mjs';
|
||||||
import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs';
|
import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs';
|
||||||
import DhCharacterCreation from '../../characterCreation/characterCreation.mjs';
|
import DhCharacterCreation from '../../characterCreation/characterCreation.mjs';
|
||||||
import FilterMenu from '../../ux/filter-menu.mjs';
|
import FilterMenu from '../../ux/filter-menu.mjs';
|
||||||
import { getArmorSources, getDocFromElement, getDocFromElementSync, sortBy } from '../../../helpers/utils.mjs';
|
import { getArmorSources, getDocFromElement, getDocFromElementSync, itemAbleRollParse, sortBy } from '../../../helpers/utils.mjs';
|
||||||
|
|
||||||
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
/**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */
|
||||||
|
|
||||||
|
|
@ -29,6 +29,7 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
toggleResourceDice: CharacterSheet.#toggleResourceDice,
|
toggleResourceDice: CharacterSheet.#toggleResourceDice,
|
||||||
handleResourceDice: CharacterSheet.#handleResourceDice,
|
handleResourceDice: CharacterSheet.#handleResourceDice,
|
||||||
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
advanceResourceDie: CharacterSheet.#advanceResourceDie,
|
||||||
|
toggleItemReload: CharacterSheet.#onToggleItemReload,
|
||||||
cancelBeastform: CharacterSheet.#cancelBeastform,
|
cancelBeastform: CharacterSheet.#cancelBeastform,
|
||||||
toggleResourceManagement: CharacterSheet.#toggleResourceManagement,
|
toggleResourceManagement: CharacterSheet.#toggleResourceManagement,
|
||||||
useDowntime: this.useDowntime,
|
useDowntime: this.useDowntime,
|
||||||
|
|
@ -954,11 +955,21 @@ export default class CharacterSheet extends DHBaseActorSheet {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** */
|
|
||||||
static #advanceResourceDie(_, target) {
|
static #advanceResourceDie(_, target) {
|
||||||
this.updateResourceDie(target, true);
|
this.updateResourceDie(target, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async #onToggleItemReload(_, target) {
|
||||||
|
const item = await getDocFromElement(target);
|
||||||
|
if (!item || !item.system.resource?.max)
|
||||||
|
return;
|
||||||
|
|
||||||
|
await item.update({
|
||||||
|
'system.resource.value': item.system.needsReload ?
|
||||||
|
itemAbleRollParse(item.system.resource.max, this.document, item) : 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
lowerResourceDie(event) {
|
lowerResourceDie(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
@ -152,6 +153,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
|
||||||
html.querySelectorAll('.risk-it-all-button').forEach(element =>
|
html.querySelectorAll('.risk-it-all-button').forEach(element =>
|
||||||
element.addEventListener('click', event => this.riskItAllClearStressAndHitPoints(event, data))
|
element.addEventListener('click', event => this.riskItAllClearStressAndHitPoints(event, data))
|
||||||
);
|
);
|
||||||
|
for (const element of html.querySelectorAll('.roll-reload-check')) {
|
||||||
|
element.addEventListener('click', event => this.onRollReloadCheck(event, message));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
setupHooks() {
|
setupHooks() {
|
||||||
|
|
@ -275,4 +279,27 @@ 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
async onRollReloadCheck(_event, messageData) {
|
||||||
|
const message = game.messages.get(messageData._id);
|
||||||
|
|
||||||
|
if (message.system.reloadCheckValue) {
|
||||||
|
const confirmed = await foundry.applications.api.DialogV2.confirm({
|
||||||
|
window: {
|
||||||
|
title: _loc('DAGGERHEART.ACTIONS.Reload.rerollConfirmationTitle')
|
||||||
|
},
|
||||||
|
content: _loc('DAGGERHEART.ACTIONS.Reload.rerollConfirmationText')
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!confirmed) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { rollValue } = await message.system.action.handleReload?.({ awaitRoll: true });
|
||||||
|
await message.update({ 'system.reloadCheckValue': rollValue });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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,48 @@ 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;
|
||||||
|
|
||||||
|
this.handleStyleElement(fearPosition);
|
||||||
|
|
||||||
|
switch (fearPosition) {
|
||||||
|
case 'topCenter':
|
||||||
|
document.getElementById('ui-top')?.appendChild(this.element);
|
||||||
|
break;
|
||||||
|
case 'bottomCenter':
|
||||||
|
document.getElementById('ui-bottom')?.prepend(this.element);
|
||||||
|
break;
|
||||||
|
case 'rightTop':
|
||||||
|
document.getElementById('ui-right-column-1')?.appendChild(this.element);
|
||||||
|
break;
|
||||||
|
case 'leftBottom':
|
||||||
|
document.getElementById('ui-left-column-1')?.insertBefore(this.element, document.getElementById('players'));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
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 +126,29 @@ 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);
|
for (const position of Object.values(CONFIG.DH.GENERAL.fearPosition)) {
|
||||||
|
this.element.classList.remove(position.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.classList.add(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 +172,119 @@ export default class FearTracker extends HandlebarsApplicationMixin(ApplicationV
|
||||||
value
|
value
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Remove methods later to use Foundry's dragger and resize methods
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* 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' },
|
||||||
|
|
|
||||||
|
|
@ -62,3 +62,18 @@ export const actionAutomationChoices = {
|
||||||
label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.always'
|
label: 'DAGGERHEART.CONFIG.ActionAutomationChoices.always'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const reloadChoices = {
|
||||||
|
off: {
|
||||||
|
id: 'off',
|
||||||
|
label: 'DAGGERHEART.CONFIG.ReloadChoices.off.label'
|
||||||
|
},
|
||||||
|
manual: {
|
||||||
|
id: 'manual',
|
||||||
|
label: 'DAGGERHEART.CONFIG.ReloadChoices.manual.label'
|
||||||
|
},
|
||||||
|
auto: {
|
||||||
|
id: 'auto',
|
||||||
|
label: 'DAGGERHEART.CONFIG.ReloadChoices.auto.label'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -52,6 +52,10 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
}
|
}
|
||||||
|
|
||||||
async use(event, options) {
|
async use(event, options) {
|
||||||
|
if (this.item?.system.needsReload) {
|
||||||
|
return ui.notifications.error(_loc('DAGGERHEART.UI.Notifications.reloadRequired', { weapon: this.item.name }));
|
||||||
|
}
|
||||||
|
|
||||||
const result = await super.use(event, options);
|
const result = await super.use(event, options);
|
||||||
|
|
||||||
if (result?.message?.system.action?.roll?.type === 'attack') {
|
if (result?.message?.system.action?.roll?.type === 'attack') {
|
||||||
|
|
@ -62,6 +66,23 @@ export default class DHAttackAction extends DHDamageAction {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async handleReload(options = { awaitRoll: false }) {
|
||||||
|
const roll = await new Roll('1d6').evaluate();
|
||||||
|
if (game.modules.get('dice-so-nice')?.active) {
|
||||||
|
if (options.awaitRoll)
|
||||||
|
await game.dice3d.showForRoll(roll, game.user, true);
|
||||||
|
else
|
||||||
|
game.dice3d.showForRoll(roll, game.user, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const needsReload = roll.total === 1;
|
||||||
|
if (needsReload) {
|
||||||
|
this.item.update({ 'system.resource.value': 0 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return { needsReload, rollValue: roll.total };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a localized label array for this item subtype.
|
* Generate a localized label array for this item subtype.
|
||||||
* @returns {(string | { value: string, icons: string[] })[]} An array of localized strings and damage label objects.
|
* @returns {(string | { value: string, icons: string[] })[]} An array of localized strings and damage label objects.
|
||||||
|
|
|
||||||
|
|
@ -429,11 +429,11 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasDamage() {
|
get hasDamage() {
|
||||||
return this.type !== 'healing' && (Boolean(this.damage.main) || !foundry.utils.isEmpty(this.damage.resources));
|
return this.type !== 'healing' && (Boolean(this.damage?.main) || !foundry.utils.isEmpty(this.damage?.resources));
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasHealing() {
|
get hasHealing() {
|
||||||
return this.type === 'healing' && !foundry.utils.isEmpty(this.damage.resources);
|
return this.type === 'healing' && !foundry.utils.isEmpty(this.damage?.resources);
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasSave() {
|
get hasSave() {
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
hasEffect: new fields.BooleanField({ initial: false }),
|
hasEffect: new fields.BooleanField({ initial: false }),
|
||||||
hasSave: new fields.BooleanField({ initial: false }),
|
hasSave: new fields.BooleanField({ initial: false }),
|
||||||
hasTarget: new fields.BooleanField({ initial: false }),
|
hasTarget: new fields.BooleanField({ initial: false }),
|
||||||
|
reloadCheckValue: new fields.NumberField({ integer: true, nullable: true, initial: null }),
|
||||||
isDirect: new fields.BooleanField({ initial: false }),
|
isDirect: new fields.BooleanField({ initial: false }),
|
||||||
onSave: new fields.StringField(),
|
onSave: new fields.StringField(),
|
||||||
source: new fields.SchemaField({
|
source: new fields.SchemaField({
|
||||||
|
|
@ -75,10 +76,14 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
return fromUuidSync(this.source.actor);
|
return fromUuidSync(this.source.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
get actionItem() {
|
get item() {
|
||||||
const actionActor = this.actionActor;
|
const actionActor = this.actionActor;
|
||||||
if (!actionActor || !this.source.item) return null;
|
if (!actionActor || !this.source.item) return null;
|
||||||
|
|
||||||
|
return actionActor.items.get(this.source.item);
|
||||||
|
}
|
||||||
|
|
||||||
|
get actionItem() {
|
||||||
switch (this.source.originItem.type) {
|
switch (this.source.originItem.type) {
|
||||||
case CONFIG.DH.ITEM.originItemType.restMove:
|
case CONFIG.DH.ITEM.originItemType.restMove:
|
||||||
const restMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves;
|
const restMoves = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).restMoves;
|
||||||
|
|
@ -86,11 +91,18 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
|
||||||
this.source.originItem.actionIndex
|
this.source.originItem.actionIndex
|
||||||
];
|
];
|
||||||
default:
|
default:
|
||||||
const item = actionActor.items.get(this.source.item);
|
return this.item?.system.actionsList?.find(a => a.id === this.source.action);
|
||||||
return item ? item.system.actionsList?.find(a => a.id === this.source.action) : null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasReload() {
|
||||||
|
return this.item?.system.hasReload;
|
||||||
|
}
|
||||||
|
|
||||||
|
get reloadCheckFailed() {
|
||||||
|
return this.reloadCheckValue === 1;
|
||||||
|
}
|
||||||
|
|
||||||
get action() {
|
get action() {
|
||||||
const { actionActor, actionItem: itemAction } = this;
|
const { actionActor, actionItem: itemAction } = this;
|
||||||
if (!this.source.action) return null;
|
if (!this.source.action) return null;
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,14 @@ export default class DHWeapon extends AttachableItem {
|
||||||
return this.weaponFeatures;
|
return this.weaponFeatures;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get hasReload() {
|
||||||
|
return Boolean(this.weaponFeatures.find(x => x.value === 'reloading'));
|
||||||
|
}
|
||||||
|
|
||||||
|
get needsReload() {
|
||||||
|
return this.hasReload && this.resource.value === 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**@inheritdoc */
|
/**@inheritdoc */
|
||||||
async getDescriptionData() {
|
async getDescriptionData() {
|
||||||
const baseDescription = this.description;
|
const baseDescription = this.description;
|
||||||
|
|
|
||||||
|
|
@ -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.topCenter.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' }),
|
||||||
|
|
|
||||||
|
|
@ -196,6 +196,13 @@ export default class DhAutomation extends foundry.abstract.DataModel {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
reload: new fields.StringField({
|
||||||
|
required: true,
|
||||||
|
choices: CONFIG.DH.SETTINGS.reloadChoices,
|
||||||
|
initial: CONFIG.DH.SETTINGS.reloadChoices.manual.id,
|
||||||
|
label: 'DAGGERHEART.SETTINGS.Automation.FIELDS.reload.label',
|
||||||
|
hint: 'DAGGERHEART.SETTINGS.Automation.FIELDS.reload.hint'
|
||||||
|
}),
|
||||||
autoExpireActiveEffects: new fields.BooleanField({
|
autoExpireActiveEffects: new fields.BooleanField({
|
||||||
required: true,
|
required: true,
|
||||||
initial: true,
|
initial: true,
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,11 @@ export default class DHRoll extends BaseRoll {
|
||||||
|
|
||||||
static async toMessage(roll, config) {
|
static async toMessage(roll, config) {
|
||||||
const item = config.data.parent?.items?.get?.(config.source.item) ?? null;
|
const item = config.data.parent?.items?.get?.(config.source.item) ?? null;
|
||||||
const action = item ? item.system.actions.get(config.source.action) : null;
|
const actions = item ? [
|
||||||
|
...item.system.actions,
|
||||||
|
...(item.system.attack?.id === config.source.action ? [item.system.attack] : [])
|
||||||
|
] : [];
|
||||||
|
const action = actions.find(x => x.id === config.source.action);
|
||||||
let actionDescription = null;
|
let actionDescription = null;
|
||||||
if (action?.chatDisplay) {
|
if (action?.chatDisplay) {
|
||||||
actionDescription = action
|
actionDescription = action
|
||||||
|
|
@ -129,6 +133,14 @@ export default class DHRoll extends BaseRoll {
|
||||||
config.actionChatMessageHandled = true;
|
config.actionChatMessageHandled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const reloadSetting =
|
||||||
|
game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).reload;
|
||||||
|
const useReload =
|
||||||
|
item?.system.hasReload &&
|
||||||
|
action?.type === 'attack' &&
|
||||||
|
reloadSetting === CONFIG.DH.SETTINGS.reloadChoices.auto.id;
|
||||||
|
const reloadResult = useReload ? await action?.handleReload?.() : {};
|
||||||
|
|
||||||
const cls = getDocumentClass('ChatMessage'),
|
const cls = getDocumentClass('ChatMessage'),
|
||||||
msgData = {
|
msgData = {
|
||||||
type: this.messageType,
|
type: this.messageType,
|
||||||
|
|
@ -136,7 +148,11 @@ export default class DHRoll extends BaseRoll {
|
||||||
title: roll.title,
|
title: roll.title,
|
||||||
speaker: cls.getSpeaker({ actor: roll.data?.parent }),
|
speaker: cls.getSpeaker({ actor: roll.data?.parent }),
|
||||||
sound: config.mute ? null : CONFIG.sounds.dice,
|
sound: config.mute ? null : CONFIG.sounds.dice,
|
||||||
system: { ...config, actionDescription },
|
system: {
|
||||||
|
...config,
|
||||||
|
actionDescription,
|
||||||
|
reloadCheckValue: reloadResult.rollValue
|
||||||
|
},
|
||||||
rolls: [roll]
|
rolls: [roll]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -158,14 +174,17 @@ export default class DHRoll extends BaseRoll {
|
||||||
if (!this._evaluated) return;
|
if (!this._evaluated) return;
|
||||||
|
|
||||||
const metagamingSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming);
|
const metagamingSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Metagaming);
|
||||||
|
const automationSettings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
|
||||||
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options });
|
||||||
return foundry.applications.handlebars.renderTemplate(template, {
|
return foundry.applications.handlebars.renderTemplate(template, {
|
||||||
roll: this,
|
roll: this,
|
||||||
...chatData,
|
...chatData,
|
||||||
|
action: chatData.action,
|
||||||
parent: chatData.parent,
|
parent: chatData.parent,
|
||||||
targetMode: chatData.targetMode,
|
targetMode: chatData.targetMode,
|
||||||
areas: chatData.action?.areas,
|
areas: chatData.action?.areas,
|
||||||
metagamingSettings
|
metagamingSettings,
|
||||||
|
automationSettings
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,15 @@
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
"page": 48,
|
"page": 48,
|
||||||
"artist": ""
|
"artist": ""
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"type": "simple",
|
||||||
|
"value": 1,
|
||||||
|
"max": "1",
|
||||||
|
"recovery": null,
|
||||||
|
"progression": "decreasing",
|
||||||
|
"dieFaces": "d4",
|
||||||
|
"icon": "fa-solid fa-gun"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"effects": [],
|
"effects": [],
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,15 @@
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
"page": 46,
|
"page": 46,
|
||||||
"artist": ""
|
"artist": ""
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"type": "simple",
|
||||||
|
"value": 1,
|
||||||
|
"max": "1",
|
||||||
|
"recovery": null,
|
||||||
|
"progression": "decreasing",
|
||||||
|
"dieFaces": "d4",
|
||||||
|
"icon": "fa-solid fa-gun"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"effects": [],
|
"effects": [],
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,15 @@
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
"page": 50,
|
"page": 50,
|
||||||
"artist": ""
|
"artist": ""
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"type": "simple",
|
||||||
|
"value": 1,
|
||||||
|
"max": "1",
|
||||||
|
"recovery": null,
|
||||||
|
"progression": "decreasing",
|
||||||
|
"dieFaces": "d4",
|
||||||
|
"icon": "fa-solid fa-gun"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"effects": [],
|
"effects": [],
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,15 @@
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
"page": 49,
|
"page": 49,
|
||||||
"artist": ""
|
"artist": ""
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"type": "simple",
|
||||||
|
"value": 1,
|
||||||
|
"max": "1",
|
||||||
|
"recovery": null,
|
||||||
|
"progression": "decreasing",
|
||||||
|
"dieFaces": "d4",
|
||||||
|
"icon": "fa-solid fa-gun"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"effects": [],
|
"effects": [],
|
||||||
|
|
|
||||||
|
|
@ -128,6 +128,15 @@
|
||||||
"source": "Daggerheart SRD",
|
"source": "Daggerheart SRD",
|
||||||
"page": 51,
|
"page": 51,
|
||||||
"artist": ""
|
"artist": ""
|
||||||
|
},
|
||||||
|
"resource": {
|
||||||
|
"type": "simple",
|
||||||
|
"value": 1,
|
||||||
|
"max": "1",
|
||||||
|
"recovery": null,
|
||||||
|
"progression": "decreasing",
|
||||||
|
"dieFaces": "d4",
|
||||||
|
"icon": "fa-solid fa-gun"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"effects": [],
|
"effects": [],
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,10 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 4px;
|
gap: 4px;
|
||||||
|
|
||||||
|
.unloaded {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,11 @@
|
||||||
height: 40px;
|
height: 40px;
|
||||||
flex: 1 1 calc(50% - 5px);
|
flex: 1 1 calc(50% - 5px);
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family: @font-body;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
&:nth-last-child(1):nth-child(odd) {
|
&:nth-last-child(1):nth-child(odd) {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,9 +46,14 @@
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
height: 40px;
|
height: 36px;
|
||||||
flex: 1 1 calc(50% - 5px);
|
flex: 1 1 calc(50% - 5px);
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-family: @font-body;
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
&:nth-last-child(1):nth-child(odd) {
|
&:nth-last-child(1):nth-child(odd) {
|
||||||
flex-basis: 100%;
|
flex-basis: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -621,16 +621,74 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.roll-buttons {
|
.roll-buttons {
|
||||||
display: flex;
|
|
||||||
gap: 5px;
|
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
button {
|
button {
|
||||||
height: 32px;
|
height: 32px;
|
||||||
flex: 1;
|
}
|
||||||
|
|
||||||
&.end-button {
|
.main-buttons {
|
||||||
flex: 0;
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
button {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
&.end-button {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.extra-button-row {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
gap: 5px;
|
||||||
|
|
||||||
|
.image-container {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
img {
|
||||||
|
height: 24px;
|
||||||
|
filter: @dark-filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-result {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 18px;
|
||||||
|
color: @beige;
|
||||||
|
filter: drop-shadow(0 0 1px @light-white);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.reload-data {
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 5px;
|
||||||
|
gap: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
color: @golden;
|
||||||
|
background: @golden-40;
|
||||||
|
|
||||||
|
&.failed-check {
|
||||||
|
background: @red-40;
|
||||||
|
color: @red;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.passed-check {
|
||||||
|
background: @green-40;
|
||||||
|
color: @green;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.topCenter,
|
||||||
|
&.bottomCenter {
|
||||||
|
margin: 1rem 0;
|
||||||
|
width: 100% !important;
|
||||||
|
transform: translateX(var(--offset));
|
||||||
|
transition: all 250ms ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.rightTop {
|
||||||
|
width: 300px !important;
|
||||||
|
max-width: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.leftBottom {
|
||||||
|
width: 200px !important;
|
||||||
|
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}}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
<p class="hint">{{localize (concat "DAGGERHEART.SETTINGS.Automation.FIELDS.roll." field.name ".hint")}}</p>
|
<p class="hint">{{localize (concat "DAGGERHEART.SETTINGS.Automation.FIELDS.roll." field.name ".hint")}}</p>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
{{formGroup settingFields.schema.fields.reload value=settingFields.reload localize=true}}
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset>
|
<fieldset>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,13 @@
|
||||||
{{#if (eq item.system.resource.type 'simple')}}
|
{{#if (eq item.system.resource.type 'simple')}}
|
||||||
<div class="item-resource">
|
<div class="item-resource">
|
||||||
<i class="{{#if item.system.resource.icon}}{{item.system.resource.icon}}{{else}}fa-solid fa-hashtag{{/if}}"></i>
|
{{#if item.system.hasReload}}
|
||||||
<input type="number" id="{{item.uuid}}-resource" class="inventory-item-resource" value="{{item.system.resource.value}}" min="0" max="{{rollParsed item.system.resource.max item.actor item true}}" />
|
<a data-action="toggleItemReload" title="{{localize (ifThen item.system.needsReload 'DAGGERHEART.GENERAL.Resource.unloaded' 'DAGGERHEART.GENERAL.Resource.loaded')}}">
|
||||||
|
<i class="fa-solid fa-gun {{#if item.system.needsReload}}unloaded{{/if}}"></i>
|
||||||
|
</a>
|
||||||
|
{{else}}
|
||||||
|
<i class="{{#if item.system.resource.icon}}{{item.system.resource.icon}}{{else}}fa-solid fa-hashtag{{/if}}"></i>
|
||||||
|
<input type="number" id="{{item.uuid}}-resource" class="inventory-item-resource" value="{{item.system.resource.value}}" min="0" max="{{rollParsed item.system.resource.max item.actor item true}}" />
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{else if (eq item.system.resource.type 'diceValue')}}
|
{{else if (eq item.system.resource.type 'diceValue')}}
|
||||||
<div class="item-resources">
|
<div class="item-resources">
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,40 @@
|
||||||
<div class="roll-buttons">
|
<div class="roll-buttons">
|
||||||
{{#if areas.length}}<button class="action-areas end-button"><i class="fa-solid fa-crosshairs"></i></button>{{/if}}
|
<div class="main-buttons">
|
||||||
{{#if hasDamage}}
|
{{#if areas.length}}<button class="action-areas end-button"><i class="fa-solid fa-crosshairs"></i></button>{{/if}}
|
||||||
{{#if damage.active}}
|
{{#if hasDamage}}
|
||||||
<button class="duality-action damage-button">{{localize "DAGGERHEART.UI.Chat.damageRoll.dealDamage"}}</button>
|
{{#if damage.active}}
|
||||||
{{else}}
|
<button class="duality-action damage-button">{{localize "DAGGERHEART.UI.Chat.damageRoll.dealDamage"}}</button>
|
||||||
<button class="duality-action duality-action-damage">{{localize "DAGGERHEART.UI.Chat.attackRoll.rollDamage"}}</button>
|
{{else}}
|
||||||
|
<button class="duality-action duality-action-damage">{{localize "DAGGERHEART.UI.Chat.attackRoll.rollDamage"}}</button>
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{#if hasHealing}}
|
||||||
{{#if hasHealing}}
|
{{#if damage.active}}
|
||||||
{{#if damage.active}}
|
<button class="duality-action damage-button">{{localize "DAGGERHEART.UI.Chat.healingRoll.applyHealing"}}</button>
|
||||||
<button class="duality-action damage-button">{{localize "DAGGERHEART.UI.Chat.healingRoll.applyHealing"}}</button>
|
{{else}}
|
||||||
{{else}}
|
<button class="duality-action duality-action-damage">{{localize "DAGGERHEART.UI.Chat.attackRoll.rollHealing"}}</button>
|
||||||
<button class="duality-action duality-action-damage">{{localize "DAGGERHEART.UI.Chat.attackRoll.rollHealing"}}</button>
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{#if (and hasEffect)}}<button class="duality-action-effect">{{localize "DAGGERHEART.UI.Chat.attackRoll.applyEffect"}}</button>{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if parent.system.hasReload}}
|
||||||
|
<div class="extra-button-row">
|
||||||
|
<button class="roll-reload-check">
|
||||||
|
<div class="image-container">
|
||||||
|
<img class="dice-icon normal" src="{{concat 'systems/daggerheart/assets/icons/dice/default/d20.svg'}}" alt="">
|
||||||
|
{{#if reloadCheckValue}}<div class="dice-result">{{reloadCheckValue}}</div>{{/if}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{localize "DAGGERHEART.ACTIONS.Reload.checkReload"}}
|
||||||
|
</button>
|
||||||
|
<div class="reload-data {{#if reloadCheckValue}}{{ifThen parent.system.reloadCheckFailed 'failed-check' 'passed-check'}}{{/if}}">
|
||||||
|
{{#unless reloadCheckValue}}
|
||||||
|
{{localize "DAGGERHEART.ACTIONS.Reload.notRolled"}}
|
||||||
|
{{else}}
|
||||||
|
{{ifThen parent.system.reloadCheckFailed (localize "DAGGERHEART.ACTIONS.Reload.checkFailed") (localize "DAGGERHEART.ACTIONS.Reload.checkPassed")}}
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if (and hasEffect)}}<button class="duality-action-effect">{{localize "DAGGERHEART.UI.Chat.attackRoll.applyEffect"}}</button>{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
<div class="chat-roll">
|
<div class="chat-roll">
|
||||||
<div class="roll-part-title"><span>{{title}}</span></div>
|
<div class="roll-part-title"><span>{{title}}</span></div>
|
||||||
|
|
||||||
{{#if actionDescription}}{{> 'systems/daggerheart/templates/ui/chat/parts/description-part.hbs'}}{{/if}}
|
{{#if actionDescription}}{{> 'systems/daggerheart/templates/ui/chat/parts/description-part.hbs'}}{{/if}}
|
||||||
{{#if hasRoll}}
|
{{#if hasRoll}}
|
||||||
<div class="roll-part-header"><span>{{localize "Result"}}</span></div>
|
<div class="roll-part-header"><span>{{localize "Result"}}</span></div>
|
||||||
|
|
|
||||||
|
|
@ -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