}
- */
- static async #onEditName() {
- const combat = this.viewed;
- if (!combat || !game.user.isGM) return null;
- const field = combat.schema.fields.name;
- const inputHTML = field.toFormGroup({}, { name: 'name', value: combat.name, autofocus: true }).outerHTML;
- const formData = await foundry.applications.api.DialogV2.input({
- window: { icon: 'fa-solid fa-tag', title: 'COMBAT.ACTIONS.EditNameTitle' },
- position: { width: 480 },
- content: inputHTML
- });
- await combat.update({ name: formData.name || '' });
- }
-
_getCombatContextOptions() {
return [
{
- label: 'COMBAT.ACTIONS.EditName',
- icon: 'fa-solid fa-tag',
+ label: 'COMBAT.ClearMovementHistories',
+ icon: ' ',
+ visible: () => game.user.isGM && this.viewed?.combatants.size > 0,
+ callback: () => this.viewed.clearMovementHistories()
+ },
+ {
+ label: 'COMBAT.Delete',
+ icon: ' ',
visible: () => game.user.isGM && !!this.viewed,
- onClick: () => DhCombatTracker.#onEditName.call(this)
- },
- {
- label: 'COMBAT.ACTIONS.LinkToScene',
- icon: ' ',
- visible: () => game.user.isGM && !this.scene,
- onClick: () => this.viewed.toggleSceneLink()
- },
- {
- label: 'COMBAT.ACTIONS.UnlinkFromScene',
- icon: ' ',
- visible: () => game.user.isGM && !!this.scene,
- onClick: () => this.viewed.toggleSceneLink()
- },
- {
- label: 'COMBAT.End',
- icon: 'fa-solid fa-xmark',
- visible: () => game.user.isGM && !!this.viewed,
- onClick: () => this.viewed.endCombat()
+ callback: () => this.viewed.endCombat()
}
];
}
@@ -163,7 +133,7 @@ export default class DhCombatTracker extends foundry.applications.sidebar.tabs.C
canPing: combatant.sceneId === canvas.scene?.id && game.user.hasPermission('PING_CANVAS'),
type: combatant.actor?.system?.type,
img: await this._getCombatantThumbnail(combatant),
- disposition: combatant.token?.disposition
+ disposition: combatant.token.disposition
};
turn.css = [turn.active ? 'active' : null, hidden ? 'hide' : null, isDefeated ? 'defeated' : null].filterJoin(
diff --git a/module/applications/ui/countdownEdit.mjs b/module/applications/ui/countdownEdit.mjs
index 5974e1f2..b418107c 100644
--- a/module/applications/ui/countdownEdit.mjs
+++ b/module/applications/ui/countdownEdit.mjs
@@ -56,8 +56,8 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
- ? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
- : 'DAGGERHEART.UI.Countdowns.loop'
+ ? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
+ : 'DAGGERHEART.UI.Countdowns.loop'
: null;
const randomizeValid = !new Roll(countdown.progress.startFormula ?? '').isDeterministic;
acc[key] = {
@@ -148,11 +148,11 @@ export default class CountdownEdit extends HandlebarsApplicationMixin(Applicatio
}
async gmSetSetting(data) {
- await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
- game.socket.emit(`system.${CONFIG.DH.id}`, {
- action: socketEvent.Refresh,
- data: { refreshType: RefreshType.Countdown }
- });
+ await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data),
+ game.socket.emit(`system.${CONFIG.DH.id}`, {
+ action: socketEvent.Refresh,
+ data: { refreshType: RefreshType.Countdown }
+ });
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
}
diff --git a/module/applications/ui/countdowns.mjs b/module/applications/ui/countdowns.mjs
index 2a2a113e..76e2b399 100644
--- a/module/applications/ui/countdowns.mjs
+++ b/module/applications/ui/countdowns.mjs
@@ -31,9 +31,9 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
minimizable: false
},
actions: {
- toggleViewMode: DhCountdowns.#onToggleViewMode,
- editCountdowns: DhCountdowns.#onEditCountdowns,
- loopCountdown: DhCountdowns.#onLoopCountdown,
+ toggleViewMode: DhCountdowns.#toggleViewMode,
+ editCountdowns: DhCountdowns.#editCountdowns,
+ loopCountdown: DhCountdowns.#loopCountdown,
decreaseCountdown: (_, target) => this.editCountdown(false, target),
increaseCountdown: (_, target) => this.editCountdown(true, target)
},
@@ -101,8 +101,8 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
? countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
? 'DAGGERHEART.UI.Countdowns.increasingLoop'
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
- ? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
- : 'DAGGERHEART.UI.Countdowns.loop'
+ ? 'DAGGERHEART.UI.Countdowns.decreasingLoop'
+ : 'DAGGERHEART.UI.Countdowns.loop'
: null;
const loopDisabled =
!countdownEditable ||
@@ -147,7 +147,7 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
return true;
}
- static async #onToggleViewMode() {
+ static async #toggleViewMode() {
const currentMode = game.user.getFlag(CONFIG.DH.id, CONFIG.DH.FLAGS.userFlags.countdownMode);
const appMode = CONFIG.DH.GENERAL.countdownAppMode;
const newMode = currentMode === appMode.textIcon ? appMode.iconOnly : appMode.textIcon;
@@ -158,16 +158,15 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
this.render();
}
- static async #onEditCountdowns() {
+ static async #editCountdowns() {
new game.system.api.applications.ui.CountdownEdit().render(true);
}
- static async #onLoopCountdown(_, target) {
+ static async #loopCountdown(_, target) {
if (!DhCountdowns.canPerformEdit()) return;
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
- const countdownId = target.closest('[data-countdown]').dataset.countdown;
- const countdown = settings.countdowns[countdownId];
+ const countdown = settings.countdowns[target.id];
let progressMax = countdown.progress.start;
let message = null;
@@ -181,12 +180,12 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.increasing.id
? Number(progressMax) + 1
: countdown.progress.looping === CONFIG.DH.GENERAL.countdownLoopingTypes.decreasing.id
- ? Math.max(Number(progressMax) - 1, 0)
- : progressMax;
+ ? Math.max(Number(progressMax) - 1, 0)
+ : progressMax;
await waitForDiceSoNice(message);
await settings.updateSource({
- [`countdowns.${countdownId}.progress`]: {
+ [`countdowns.${target.id}.progress`]: {
current: newMax,
start: newMax
}
@@ -200,23 +199,22 @@ export default class DhCountdowns extends HandlebarsApplicationMixin(Application
if (!DhCountdowns.canPerformEdit()) return;
const settings = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns);
- const countdownId = target.closest('[data-countdown]').dataset.countdown;
- const countdown = settings.countdowns[countdownId];
+ const countdown = settings.countdowns[target.id];
const newCurrent = increase
? Math.min(countdown.progress.current + 1, countdown.progress.start)
: Math.max(countdown.progress.current - 1, 0);
- await settings.updateSource({ [`countdowns.${countdownId}.progress.current`]: newCurrent });
+ await settings.updateSource({ [`countdowns.${target.id}.progress.current`]: newCurrent });
await emitGMUpdate(GMUpdateEvent.UpdateCountdowns, DhCountdowns.gmSetSetting.bind(settings), settings, null, {
refreshType: RefreshType.Countdown
});
}
static async gmSetSetting(data) {
- await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data);
- game.socket.emit(`system.${CONFIG.DH.id}`, {
- action: socketEvent.Refresh,
- data: { refreshType: RefreshType.Countdown }
- });
+ await game.settings.set(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Countdowns, data),
+ game.socket.emit(`system.${CONFIG.DH.id}`, {
+ action: socketEvent.Refresh,
+ data: { refreshType: RefreshType.Countdown }
+ });
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
}
diff --git a/module/applications/ui/effectsDisplay.mjs b/module/applications/ui/effectsDisplay.mjs
index a64b1b22..035041e1 100644
--- a/module/applications/ui/effectsDisplay.mjs
+++ b/module/applications/ui/effectsDisplay.mjs
@@ -67,10 +67,10 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica
const actor = token
? token.actor
: canvas.tokens.controlled.length === 0
- ? !game.user.isGM
- ? game.user.character
- : null
- : canvas.tokens.controlled[0].actor;
+ ? !game.user.isGM
+ ? game.user.character
+ : null
+ : canvas.tokens.controlled[0].actor;
return getIconVisibleActiveEffects(actor?.getActiveEffects() ?? []);
};
diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs
index 02eed7db..68e325c2 100644
--- a/module/canvas/placeables/token.mjs
+++ b/module/canvas/placeables/token.mjs
@@ -155,15 +155,15 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token {
const targetEdge = this.#getEdgeBoundary(targetBounds, originPoint, targetPoint);
const adjustedOriginPoint = originEdge
? canvas.grid.getTopLeftPoint({
- x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
- y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
- })
+ x: originEdge.x + Math.sign(originPoint.x - originEdge.x),
+ y: originEdge.y + Math.sign(originPoint.y - originEdge.y)
+ })
: originPoint;
const adjustDestinationPoint = targetEdge
? canvas.grid.getTopLeftPoint({
- x: targetEdge.x + Math.sign(targetPoint.x - targetEdge.x),
- y: targetEdge.y + Math.sign(targetPoint.y - targetEdge.y)
- })
+ x: targetEdge.x + Math.sign(targetPoint.x - targetEdge.x),
+ y: targetEdge.y + Math.sign(targetPoint.y - targetEdge.y)
+ })
: targetPoint;
const distance = canvas.grid.measurePath([
{ ...adjustedOriginPoint, elevation: 0 },
diff --git a/module/config/itemBrowserConfig.mjs b/module/config/itemBrowserConfig.mjs
index 83572dc0..ae5fa71b 100644
--- a/module/config/itemBrowserConfig.mjs
+++ b/module/config/itemBrowserConfig.mjs
@@ -127,8 +127,8 @@ export const typeConfig = {
isSecondary
? 'DAGGERHEART.ITEMS.Weapon.secondaryWeapon.short'
: isSecondary === false
- ? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short'
- : '-'
+ ? 'DAGGERHEART.ITEMS.Weapon.primaryWeapon.short'
+ : '-'
},
{
key: 'system.tier',
diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs
index 1988b1d8..c4d07c25 100644
--- a/module/data/action/attackAction.mjs
+++ b/module/data/action/attackAction.mjs
@@ -75,12 +75,7 @@ export default class DHAttackAction extends DHDamageAction {
const useAltDamage = this.actor?.effects?.find(x => x.type === 'horde')?.active;
for (const { value, valueAlt, type } of damage.parts) {
const usedValue = useAltDamage ? valueAlt : value;
- const damageString = Roll.replaceFormulaData(usedValue.getFormula(), this.actor?.getRollData() ?? {});
- const str = damageString
- ? damageString
- : game.i18n.format('DAGGERHEART.GENERAL.missingX', {
- x: game.i18n.localize('DAGGERHEART.GENERAL.damage')
- });
+ const str = Roll.replaceFormulaData(usedValue.getFormula(), this.actor?.getRollData() ?? {});
const icons = Array.from(type)
.map(t => CONFIG.DH.GENERAL.damageTypes[t]?.icon)
diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs
index c71f5ef9..acd104a7 100644
--- a/module/data/action/baseAction.mjs
+++ b/module/data/action/baseAction.mjs
@@ -144,8 +144,8 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
return this.item instanceof DhpActor
? this.item
: this.item?.parent instanceof DhpActor
- ? this.item.parent
- : null;
+ ? this.item.parent
+ : null;
}
/**
@@ -223,7 +223,7 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
* @returns {object}
*/
async use(event, configOptions = {}) {
- if (!this.actor) throw new Error('An Action can\'t be used outside of an Actor context.');
+ if (!this.actor) throw new Error("An Action can't be used outside of an Actor context.");
let config = this.prepareConfig(event, configOptions);
if (!config) return;
@@ -300,17 +300,17 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel
const groupAttackTokens = this.damage.groupAttack
? game.system.api.fields.ActionFields.DamageField.getGroupAttackTokens(
- this.actor.id,
- this.damage.groupAttack
- )
+ this.actor.id,
+ this.damage.groupAttack
+ )
: null;
config.damageOptions = {
groupAttack: this.damage.groupAttack
? {
- numAttackers: Math.max(groupAttackTokens.length, 1),
- range: this.damage.groupAttack
- }
+ numAttackers: Math.max(groupAttackTokens.length, 1),
+ range: this.damage.groupAttack
+ }
: null
};
}
diff --git a/module/data/action/countdownAction.mjs b/module/data/action/countdownAction.mjs
index cb141637..abcc6b40 100644
--- a/module/data/action/countdownAction.mjs
+++ b/module/data/action/countdownAction.mjs
@@ -36,7 +36,7 @@ export default class DhCountdownAction extends DHBaseAction {
/** @inheritDoc */
static migrateData(source) {
- for (const countdown of Object.values(source.countdown)) {
+ for (const countdown of source.countdown) {
if (countdown.progress.max) {
countdown.progress.startFormula = countdown.progress.max;
countdown.progress.start = 1;
diff --git a/module/data/activeEffect/beastformEffect.mjs b/module/data/activeEffect/beastformEffect.mjs
index 7e037f5b..0fbea122 100644
--- a/module/data/activeEffect/beastformEffect.mjs
+++ b/module/data/activeEffect/beastformEffect.mjs
@@ -90,13 +90,13 @@ export default class BeastformEffect extends BaseEffect {
...baseUpdate,
x,
y,
- texture: {
+ 'texture': {
enabled: this.characterTokenData.usesDynamicToken,
src: token.flags.daggerheart?.beastformTokenImg ?? this.characterTokenData.tokenImg,
scaleX: this.characterTokenData.tokenSize.scale,
scaleY: this.characterTokenData.tokenSize.scale
},
- ring: {
+ 'ring': {
subject: {
texture:
token.flags.daggerheart?.beastformSubjectTexture ?? this.characterTokenData.tokenRingImg
diff --git a/module/data/activeEffect/changeTypes/armor.mjs b/module/data/activeEffect/changeTypes/armor.mjs
index 0c226513..217ff9dd 100644
--- a/module/data/activeEffect/changeTypes/armor.mjs
+++ b/module/data/activeEffect/changeTypes/armor.mjs
@@ -166,10 +166,10 @@ export default class ArmorChange extends foundry.abstract.DataModel {
value:
change.type === 'armor'
? {
- ...change.value,
- current: Math.min(change.value.current, newMax),
- max: newMax
- }
+ ...change.value,
+ current: Math.min(change.value.current, newMax),
+ max: newMax
+ }
: change.value
}))
];
diff --git a/module/data/actor/_module.mjs b/module/data/actor/_module.mjs
index 1fe1ef3f..99577620 100644
--- a/module/data/actor/_module.mjs
+++ b/module/data/actor/_module.mjs
@@ -1,17 +1,15 @@
import DhCharacter from './character.mjs';
import DhCompanion from './companion.mjs';
import DhAdversary from './adversary.mjs';
-import DhNPC from './npc.mjs';
import DhEnvironment from './environment.mjs';
import DhParty from './party.mjs';
-export { DhCharacter, DhCompanion, DhAdversary, DhNPC, DhEnvironment, DhParty };
+export { DhCharacter, DhCompanion, DhAdversary, DhEnvironment, DhParty };
export const config = {
character: DhCharacter,
companion: DhCompanion,
adversary: DhAdversary,
- npc: DhNPC,
environment: DhEnvironment,
party: DhParty
};
diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs
index d6d0dcdf..d69e17ad 100644
--- a/module/data/actor/adversary.mjs
+++ b/module/data/actor/adversary.mjs
@@ -3,7 +3,8 @@ import { ActionField } from '../fields/actionField.mjs';
import { commonActorRules } from './base.mjs';
import DhCreature from './creature.mjs';
import { bonusField } from '../fields/actorField.mjs';
-import { getTierAdjustedAdversary } from './tierAdjustment.mjs';
+import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
+import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
export default class DhpAdversary extends DhCreature {
static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.Adversary'];
@@ -205,6 +206,205 @@ export default class DhpAdversary extends DhCreature {
/** Returns source data for this actor adjusted to a new tier, which can be used to create a new actor. */
adjustForTier(tier) {
const source = this.parent.toObject(true);
- return getTierAdjustedAdversary(source, tier);
+
+ /** @type {(2 | 3 | 4)[]} */
+ const tiers = new Array(Math.abs(tier - this.tier))
+ .fill(0)
+ .map((_, idx) => idx + Math.min(tier, this.tier) + 1);
+ if (tier < this.tier) tiers.reverse();
+ const typeData = adversaryScalingData[source.system.type] ?? adversaryScalingData[source.system.standard];
+ const tierEntries = tiers.map(t => ({ tier: t, ...typeData[t] }));
+
+ // Apply simple tier changes
+ const scale = tier > this.tier ? 1 : -1;
+ for (const entry of tierEntries) {
+ source.system.difficulty += scale * entry.difficulty;
+ source.system.damageThresholds.major += scale * entry.majorThreshold;
+ source.system.damageThresholds.severe += scale * entry.severeThreshold;
+ source.system.resources.hitPoints.max += scale * entry.hp;
+ source.system.resources.stress.max += scale * entry.stress;
+ source.system.attack.roll.bonus += scale * entry.attack;
+ }
+
+ // Get the mean and standard deviation of expected damage in the previous and new tier
+ // The data we have is for attack scaling, but we reuse this for action scaling later
+ const expectedDamageData = adversaryExpectedDamage[source.system.type] ?? adversaryExpectedDamage.basic;
+ const damageMeta = {
+ currentDamageRange: { tier: source.system.tier, ...expectedDamageData[source.system.tier] },
+ newDamageRange: { tier, ...expectedDamageData[tier] },
+ type: 'attack'
+ };
+
+ // Update damage of base attack
+ try {
+ this.#adjustActionDamage(source.system.attack, damageMeta);
+ } catch (err) {
+ ui.notifications.warn('Failed to convert attack damage of adversary');
+ console.error(err);
+ }
+
+ // Update damage of each item action, making sure to also update the description if possible
+ const damageRegex = /@Damage\[([^\[\]]*)\]({[^}]*})?/g;
+ for (const item of source.items) {
+ // Replace damage inlines with new formulas
+ for (const withDescription of [item.system, ...Object.values(item.system.actions)]) {
+ withDescription.description = withDescription.description.replace(damageRegex, (match, inner) => {
+ const { value: formula } = parseInlineParams(inner);
+ if (!formula || !type) return match;
+
+ try {
+ const adjusted = this.#calculateAdjustedDamage(formula, { ...damageMeta, type: 'action' });
+ const newFormula = [
+ adjusted.diceQuantity ? `${adjusted.diceQuantity}d${adjusted.faces}` : null,
+ adjusted.bonus
+ ]
+ .filter(p => !!p)
+ .join('+');
+ return match.replace(formula, newFormula);
+ } catch {
+ return match;
+ }
+ });
+ }
+
+ // Update damage in item actions
+ // Parse damage, and convert all formula matches in the descriptions to the new damage
+ for (const action of Object.values(item.system.actions)) {
+ try {
+ const result = this.#adjustActionDamage(action, { ...damageMeta, type: 'action' });
+ if (!result) continue;
+
+ for (const { previousFormula, formula } of Object.values(result)) {
+ const oldFormulaRegexp = new RegExp(
+ previousFormula.replace(' ', '').replace('+', '(?:\\s)?\\+(?:\\s)?')
+ );
+ item.system.description = item.system.description.replace(oldFormulaRegexp, formula);
+ action.description = action.description.replace(oldFormulaRegexp, formula);
+ }
+ } catch (err) {
+ ui.notifications.warn(`Failed to convert action damage for item ${item.name}`);
+ console.error(err);
+ }
+ }
+ }
+
+ // Finally set the tier of the source data, now that everything is complete
+ source.system.tier = tier;
+ return source;
+ }
+
+ /**
+ * Converts a damage object to a new damage range
+ * @returns {{ diceQuantity: number; faces: number; bonus: number }} the adjusted result as a combined term
+ * @throws error if the formula is the wrong type
+ */
+ #calculateAdjustedDamage(formula, { currentDamageRange, newDamageRange, type }) {
+ const terms = parseTermsFromSimpleFormula(formula);
+ const flatTerms = terms.filter(t => t.diceQuantity === 0);
+ const diceTerms = terms.filter(t => t.diceQuantity > 0);
+ if (flatTerms.length > 1 || diceTerms.length > 1) {
+ throw new Error('invalid formula for conversion');
+ }
+ const value = {
+ ...(diceTerms[0] ?? { diceQuantity: 0, faces: 1 }),
+ bonus: flatTerms[0]?.bonus ?? 0
+ };
+ const previousExpected = calculateExpectedValue(value);
+ if (previousExpected === 0) return value; // nothing to do
+
+ const dieSizes = [4, 6, 8, 10, 12, 20];
+ const steps = newDamageRange.tier - currentDamageRange.tier;
+ const increasing = steps > 0;
+ const deviation = (previousExpected - currentDamageRange.mean) / currentDamageRange.deviation;
+ const expected = Math.max(1, newDamageRange.mean + newDamageRange.deviation * deviation);
+
+ // If this was just a flat number, convert to the expected damage and exit
+ if (value.diceQuantity === 0) {
+ value.bonus = Math.round(expected);
+ return value;
+ }
+
+ const getExpectedDie = () => calculateExpectedValue({ diceQuantity: 1, faces: value.faces }) || 1;
+ const getBaseAverage = () => calculateExpectedValue({ ...value, bonus: 0 });
+
+ // Check the number of base overages over the expected die. In the end, if the bonus inflates too much, we add a die
+ const baseOverages = Math.floor(value.bonus / getExpectedDie());
+
+ // Prestep. Change number of dice for attacks, bump up/down for actions
+ // We never bump up to d20, though we might bump down from it
+ if (type === 'attack') {
+ const minimum = increasing ? value.diceQuantity : 0;
+ value.diceQuantity = Math.max(minimum, newDamageRange.tier);
+ } else {
+ const currentIdx = dieSizes.indexOf(value.faces);
+ value.faces = dieSizes[Math.clamp(currentIdx + steps, 0, 4)];
+ }
+
+ value.bonus = Math.round(expected - getBaseAverage());
+
+ // Attempt to handle negative values.
+ // If we can do it with only step downs, do so. Otherwise remove tier dice, and try again
+ if (value.bonus < 0) {
+ let stepsRequired = Math.ceil(Math.abs(value.bonus) / value.diceQuantity);
+ const currentIdx = dieSizes.indexOf(value.faces);
+
+ // If step downs alone don't suffice, change the flat modifier, then calculate steps required again
+ // If this isn't sufficient, the result will be slightly off. This is unlikely to happen
+ if (type !== 'attack' && stepsRequired > currentIdx && value.diceQuantity > 0) {
+ value.diceQuantity -= increasing ? 1 : Math.abs(steps);
+ value.bonus = Math.round(expected - getBaseAverage());
+ if (value.bonus >= 0) return value; // complete
+ }
+
+ stepsRequired = Math.ceil(Math.abs(value.bonus) / value.diceQuantity);
+ value.faces = dieSizes[Math.max(0, currentIdx - stepsRequired)];
+ value.bonus = Math.max(0, Math.round(expected - getBaseAverage()));
+ }
+
+ // If value is really high, we add a number of dice based on the number of overages
+ // This attempts to preserve a similar amount of variance when increasing an action
+ const overagesToRemove = Math.floor(value.bonus / getExpectedDie()) - baseOverages;
+ if (type !== 'attack' && increasing && overagesToRemove > 0) {
+ value.diceQuantity += overagesToRemove;
+ value.bonus = Math.round(expected - getBaseAverage());
+ }
+
+ return value;
+ }
+
+ /**
+ * Updates damage to reflect a specific value.
+ * @throws if damage structure is invalid for conversion
+ * @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage
+ */
+ #adjustActionDamage(action, damageMeta) {
+ if (!action.damage?.parts.hitPoints) return null;
+
+ const result = {};
+ for (const property of ['value', 'valueAlt']) {
+ const data = action.damage.parts.hitPoints[property];
+ const previousFormula = data.custom.enabled
+ ? data.custom.formula
+ : [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0]
+ .filter(p => !!p)
+ .join('+');
+ const value = this.#calculateAdjustedDamage(previousFormula, damageMeta);
+ const formula = [value.diceQuantity ? `${value.diceQuantity}d${value.faces}` : null, value.bonus]
+ .filter(p => !!p)
+ .join('+');
+ if (value.diceQuantity) {
+ data.custom.enabled = false;
+ data.bonus = value.bonus;
+ data.dice = `d${value.faces}`;
+ data.flatMultiplier = value.diceQuantity;
+ } else if (!value.diceQuantity) {
+ data.custom.enabled = true;
+ data.custom.formula = formula;
+ }
+
+ result[property] = { previousFormula, formula, value };
+ }
+
+ return result;
}
}
diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs
index aed27650..10d53c13 100644
--- a/module/data/actor/character.mjs
+++ b/module/data/actor/character.mjs
@@ -315,8 +315,8 @@ export default class DhCharacter extends DhCreature {
return currentLevel === 1
? 1
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
- tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
- ).tier;
+ tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
+ ).tier;
}
get ancestry() {
@@ -520,20 +520,20 @@ export default class DhCharacter extends DhCreature {
if (armorSource.type === 'armor') {
armorUpdates[armorSource.parent.id].updates.push({
- _id: armorSource.id,
+ '_id': armorSource.id,
'system.armor.current': armorSource.system.armor.current + usedArmorChange
});
} else {
effectUpdates[armorSource.parent.id].updates.push({
- _id: armorSource.id,
+ '_id': armorSource.id,
'system.changes': armorSource.system.changes.map(change => ({
...change,
value:
change.type === 'armor'
? {
- ...change.value,
- current: armorSource.system.armorChange.value.current + usedArmorChange
- }
+ ...change.value,
+ current: armorSource.system.armorChange.value.current + usedArmorChange
+ }
: change.value
}))
});
@@ -621,21 +621,21 @@ export default class DhCharacter extends DhCreature {
},
...(multiclassFeatures.length
? {
- multiclassFeatures: {
- title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} - ${this.multiclass.value?.name}`,
- type: 'multiclass',
- values: multiclassFeatures
- }
- }
+ multiclassFeatures: {
+ title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} - ${this.multiclass.value?.name}`,
+ type: 'multiclass',
+ values: multiclassFeatures
+ }
+ }
: {}),
...(multiclassSubclassFeatures.length
? {
- multiclassSubclassFeatures: {
- title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} ${game.i18n.localize('TYPES.Item.subclass')} - ${this.multiclass.subclass?.name}`,
- type: 'multiclassSubclass',
- values: multiclassSubclassFeatures
- }
- }
+ multiclassSubclassFeatures: {
+ title: `${game.i18n.localize('DAGGERHEART.GENERAL.multiclass')} ${game.i18n.localize('TYPES.Item.subclass')} - ${this.multiclass.subclass?.name}`,
+ type: 'multiclassSubclass',
+ values: multiclassSubclassFeatures
+ }
+ }
: {}),
companionFeatures: {
title: game.i18n.localize('DAGGERHEART.ACTORS.Character.companionFeatures'),
@@ -659,8 +659,8 @@ export default class DhCharacter extends DhCreature {
(this.primaryWeapon && this.secondaryWeapon)
? burden.twoHanded.value
: this.primaryWeapon || this.secondaryWeapon
- ? burden.oneHanded.value
- : null;
+ ? burden.oneHanded.value
+ : null;
}
get deathMoveViable() {
@@ -726,8 +726,8 @@ export default class DhCharacter extends DhCreature {
currentLevel === 1
? null
: Object.values(game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers).find(
- tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
- ).tier;
+ tier => currentLevel >= tier.levels.start && currentLevel <= tier.levels.end
+ ).tier;
if (game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).levelupAuto) {
for (let levelKey in this.levelData.levelups) {
const level = this.levelData.levelups[levelKey];
diff --git a/module/data/actor/npc.mjs b/module/data/actor/npc.mjs
deleted file mode 100644
index 2ccaf926..00000000
--- a/module/data/actor/npc.mjs
+++ /dev/null
@@ -1,43 +0,0 @@
-import DHNPCSettings from '../../applications/sheets-configs/npc-settings.mjs';
-import BaseDataActor from './base.mjs';
-
-export default class DhpNPC extends BaseDataActor {
- static LOCALIZATION_PREFIXES = ['DAGGERHEART.ACTORS.NPC'];
-
- static get metadata() {
- return foundry.utils.mergeObject(super.metadata, {
- label: 'TYPES.Actor.npc',
- type: 'npc',
- settingSheet: DHNPCSettings,
- hasResistances: false,
- hasAttribution: true
- });
- }
-
- static defineSchema() {
- const fields = foundry.data.fields;
- return {
- ...super.defineSchema(),
- difficulty: new fields.NumberField({
- nullable: true,
- initial: null,
- integer: true,
- label: 'DAGGERHEART.GENERAL.difficulty'
- }),
- description: new fields.HTMLField({ label: 'DAGGERHEART.GENERAL.description' }),
- motives: new fields.StringField(),
- notes: new fields.HTMLField()
- };
- }
-
- /**@inheritdoc */
- static DEFAULT_ICON = 'systems/daggerheart/assets/icons/documents/actors/drama-masks.svg';
-
- get features() {
- return this.parent.items.filter(x => x.type === 'feature');
- }
-
- isItemValid(source) {
- return super.isItemValid(source) || source.type === 'feature';
- }
-}
diff --git a/module/data/actor/tierAdjustment.mjs b/module/data/actor/tierAdjustment.mjs
deleted file mode 100644
index bc6ad176..00000000
--- a/module/data/actor/tierAdjustment.mjs
+++ /dev/null
@@ -1,219 +0,0 @@
-import { calculateExpectedValue, parseTermsFromSimpleFormula } from '../../helpers/utils.mjs';
-import { adversaryExpectedDamage, adversaryScalingData } from '../../config/actorConfig.mjs';
-import { parseInlineParams } from '../../enrichers/parser.mjs';
-
-export function getTierAdjustedAdversary(source, tier) {
- const currentTier = source.tier ?? 1;
-
- /** @type {(2 | 3 | 4)[]} */
- const tiers = new Array(Math.abs(tier - currentTier))
- .fill(0)
- .map((_, idx) => idx + Math.min(tier, currentTier) + 1);
- if (tier < currentTier) tiers.reverse();
- const typeData = adversaryScalingData[source.system.type] ?? adversaryScalingData[source.system.standard];
- const tierEntries = tiers.map(t => ({ tier: t, ...typeData[t] }));
-
- // Apply simple tier changes
- const scale = tier > currentTier ? 1 : -1;
- for (const entry of tierEntries) {
- source.system.difficulty += scale * entry.difficulty;
- source.system.damageThresholds.major += scale * entry.majorThreshold;
- source.system.damageThresholds.severe += scale * entry.severeThreshold;
- source.system.resources.hitPoints.max += scale * entry.hp;
- source.system.resources.stress.max += scale * entry.stress;
- source.system.attack.roll.bonus += scale * entry.attack;
- }
-
- // Get the mean and standard deviation of expected damage in the previous and new tier
- // The data we have is for attack scaling, but we reuse this for action scaling later
- const expectedDamageData = adversaryExpectedDamage[source.system.type] ?? adversaryExpectedDamage.basic;
- const damageMeta = {
- currentDamageRange: { tier: source.system.tier, ...expectedDamageData[source.system.tier] },
- newDamageRange: { tier, ...expectedDamageData[tier] }
- };
-
- // Store initial attack damage for abilities that have you deal a "standard attack"
- const initialAttack = {
- type: source.system.attack.damage?.parts.hitPoints?.type?.toSorted(),
- value: getDamagePartsFormula(source.system.attack.damage?.parts.hitPoints?.value)
- };
-
- // Update damage of base attack.
- try {
- const damage = source.system.attack.damage;
- if (!damage?.parts.hitPoints) throw new Error('Unexpected missing attack in adversary');
-
- for (const property of ['value', 'valueAlt']) {
- const data = damage.parts.hitPoints[property];
- const previousFormula = getDamagePartsFormula(data);
- const { value, formula } = calculateAdjustedDamage(previousFormula, 'attack', damageMeta);
- applyAdjustedDamage(data, value, formula);
- }
- } catch (err) {
- ui.notifications.warn('Failed to convert attack damage of adversary');
- console.error(err);
- }
-
- // Update damage of each item action, making sure to also update the description if possible
- const damageRegex = /@Damage\[([^\[\]]*)\]({[^}]*})?/g;
- for (const item of source.items) {
- // Replace damage inlines with new formulas. Keep a record for a specific check later
- const descriptionFormulas = [];
- for (const withDescription of [item.system, ...Object.values(item.system.actions)]) {
- withDescription.description = withDescription.description.replace(damageRegex, (match, inner) => {
- const { value: formula } = parseInlineParams(inner, { first: 'value' });
- if (!formula) return match;
-
- try {
- const newFormula = calculateAdjustedDamage(formula, 'action', damageMeta)?.formula;
- descriptionFormulas.push(formula);
- return match.replace(formula, newFormula);
- } catch {
- return match;
- }
- });
- }
-
- // Update damage in item actions and convert all formula matches in the descriptions to the new damage
- for (const action of Object.values(item.system.actions)) {
- if (!action.damage?.parts.hitPoints) continue;
- try {
- // Apply conversions and save a record. If it matches attack damage *and* Its not in the description, use attack conversion instead
- const result = [];
- for (const property of ['value', 'valueAlt']) {
- const { [property]: data, type: damageType } = action.damage.parts.hitPoints;
- const previousFormula = getDamagePartsFormula(data);
- const isActuallyAttack =
- previousFormula === initialAttack.value &&
- foundry.utils.equals(damageType.toSorted(), initialAttack.type) &&
- !descriptionFormulas.includes(previousFormula);
- const type = isActuallyAttack ? 'attack' : 'action';
- const { value, formula } = calculateAdjustedDamage(previousFormula, type, damageMeta);
- applyAdjustedDamage(data, value, formula);
- result.push({ previousFormula, formula });
- }
-
- // Override text in the description with those values
- for (const { previousFormula, formula } of Object.values(result)) {
- const oldFormulaRegexp = new RegExp(
- previousFormula.replace(' ', '').replace('+', '(?:\\s)?\\+(?:\\s)?')
- );
- item.system.description = item.system.description.replace(oldFormulaRegexp, formula);
- action.description = action.description.replace(oldFormulaRegexp, formula);
- }
- } catch (err) {
- ui.notifications.warn(`Failed to convert action damage for item ${item.name}`);
- console.error(err);
- }
- }
- }
-
- // Finally set the tier of the source data, now that everything is complete
- source.system.tier = tier;
- return source;
-}
-
-/**
- * Converts a damage object to a new damage range
- * @returns {{ diceQuantity: number; faces: number; bonus: number }} the adjusted result as a combined term
- * @throws error if the formula is the wrong type
- */
-function calculateAdjustedDamage(formula, type, { currentDamageRange, newDamageRange }) {
- const terms = parseTermsFromSimpleFormula(formula);
- const flatTerms = terms.filter(t => t.diceQuantity === 0);
- const diceTerms = terms.filter(t => t.diceQuantity > 0);
- if (flatTerms.length > 1 || diceTerms.length > 1) {
- throw new Error('invalid formula for conversion');
- }
- const value = {
- ...(diceTerms[0] ?? { diceQuantity: 0, faces: 1 }),
- bonus: flatTerms[0]?.bonus ?? 0
- };
- const previousExpected = calculateExpectedValue(value);
- if (previousExpected === 0) return value; // nothing to do
-
- const dieSizes = [4, 6, 8, 10, 12, 20];
- const steps = newDamageRange.tier - currentDamageRange.tier;
- const increasing = steps > 0;
- const deviation = (previousExpected - currentDamageRange.mean) / currentDamageRange.deviation;
- const expected = Math.max(1, newDamageRange.mean + newDamageRange.deviation * deviation);
-
- // If this was just a flat number, convert to the expected damage and exit
- if (value.diceQuantity === 0) {
- value.bonus = Math.round(expected);
- return value;
- }
-
- const getExpectedDie = () => calculateExpectedValue({ diceQuantity: 1, faces: value.faces }) || 1;
- const getBaseAverage = () => calculateExpectedValue({ ...value, bonus: 0 });
-
- // Check the number of base overages over the expected die. In the end, if the bonus inflates too much, we add a die
- const baseOverages = Math.floor(value.bonus / getExpectedDie());
-
- // Prestep. Change number of dice for attacks, bump up/down for actions
- // We never bump up to d20, though we might bump down from it
- if (type === 'attack') {
- const minimum = increasing ? value.diceQuantity : 0;
- value.diceQuantity = Math.max(minimum, newDamageRange.tier);
- } else {
- const currentIdx = dieSizes.indexOf(value.faces);
- value.faces = dieSizes[Math.clamp(currentIdx + steps, 0, 4)];
- }
-
- value.bonus = Math.round(expected - getBaseAverage());
-
- // Attempt to handle negative values.
- // If we can do it with only step downs, do so. Otherwise remove tier dice, and try again
- if (value.bonus < 0) {
- let stepsRequired = Math.ceil(Math.abs(value.bonus) / value.diceQuantity);
- const currentIdx = dieSizes.indexOf(value.faces);
-
- // If step downs alone don't suffice, change the flat modifier, then calculate steps required again
- // If this isn't sufficient, the result will be slightly off. This is unlikely to happen
- if (type !== 'attack' && stepsRequired > currentIdx && value.diceQuantity > 0) {
- value.diceQuantity -= increasing ? 1 : Math.abs(steps);
- value.bonus = Math.round(expected - getBaseAverage());
- if (value.bonus >= 0) return value; // complete
- }
-
- stepsRequired = Math.ceil(Math.abs(value.bonus) / value.diceQuantity);
- value.faces = dieSizes[Math.max(0, currentIdx - stepsRequired)];
- value.bonus = Math.max(0, Math.round(expected - getBaseAverage()));
- }
-
- // If value is really high, we add a number of dice based on the number of overages
- // This attempts to preserve a similar amount of variance when increasing an action
- const overagesToRemove = Math.floor(value.bonus / getExpectedDie()) - baseOverages;
- if (type !== 'attack' && increasing && overagesToRemove > 0) {
- value.diceQuantity += overagesToRemove;
- value.bonus = Math.round(expected - getBaseAverage());
- }
-
- const newFormula = [value.diceQuantity ? `${value.diceQuantity}d${value.faces}` : null, value.bonus]
- .filter(p => !!p)
- .join('+');
- return { value, formula: newFormula };
-}
-
-function getDamagePartsFormula(data) {
- return data.custom.enabled
- ? data.custom.formula
- : [data.flatMultiplier ? `${data.flatMultiplier}${data.dice}` : 0, data.bonus ?? 0].filter(p => !!p).join('+');
-}
-
-/**
- * Updates damage to reflect a specific value.
- * @throws if damage structure is invalid for conversion
- * @returns the converted formula and value as a simplified term, or null if it doesn't deal HP damage
- */
-function applyAdjustedDamage(diceData, value, formula) {
- if (value.diceQuantity) {
- diceData.custom.enabled = false;
- diceData.bonus = value.bonus;
- diceData.dice = `d${value.faces}`;
- diceData.flatMultiplier = value.diceQuantity;
- } else if (!value.diceQuantity) {
- diceData.custom.enabled = true;
- diceData.custom.formula = formula;
- }
-}
diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs
index ccfe25ea..eaa1cdc2 100644
--- a/module/data/chat-message/actorRoll.mjs
+++ b/module/data/chat-message/actorRoll.mjs
@@ -1,5 +1,3 @@
-import { triggerChatRollFx } from '../../helpers/utils.mjs';
-
const fields = foundry.data.fields;
const targetsField = () =>
@@ -132,35 +130,6 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel {
});
}
- /* TODO: Change how damage data is stored somehow to enable better rerolling */
- async getRerolledDamage() {
- if (!this.damage) return;
-
- const rerolls = [];
- const update = { system: { damage: {} } };
- for (const partKey in this.damage) {
- const part = this.damage[partKey];
- const testRoll = Roll.fromData(part.parts[0].roll);
- const rerolled = await testRoll.reroll();
- rerolls.push(rerolled);
-
- if (!update.system.damage[partKey]) update.system.damage[partKey] = { parts: [part.parts[0]] };
- const partData = update.system.damage[partKey].parts[0];
- update.system.damage[partKey].total = rerolled.total;
- partData.modifierTotal = rerolled.terms.reduce((acc, x) => {
- if (x.isDeterministic && !x.operator) acc += x.total;
- return acc;
- }, 0);
- partData.dice = rerolled.dice.map(d => ({ ...d.toJSON(), dice: d.denomination }));
- partData.total = rerolled.total;
- partData.roll = rerolled.toJSON();
- }
-
- await triggerChatRollFx(rerolls);
-
- return update;
- }
-
registerTargetHook() {
if (!this.parent.isAuthor || !this.hasTarget) return;
if (this.targetMode && this.parent.targetHook !== null) {
diff --git a/module/data/companionLevelup.mjs b/module/data/companionLevelup.mjs
index e24820de..7ab61210 100644
--- a/module/data/companionLevelup.mjs
+++ b/module/data/companionLevelup.mjs
@@ -22,12 +22,12 @@ export class DhCompanionLevelup extends foundry.abstract.DataModel {
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
const experiences = initialAchievements.experience
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
- acc[foundry.utils.randomID()] = {
- name: '',
- modifier: initialAchievements.experience.modifier
- };
- return acc;
- }, {})
+ acc[foundry.utils.randomID()] = {
+ name: '',
+ modifier: initialAchievements.experience.modifier
+ };
+ return acc;
+ }, {})
: {};
const currentChoices = pcLevelData.levelups[i]?.selections?.length;
@@ -302,9 +302,9 @@ export class DhLevelupLevel extends foundry.abstract.DataModel {
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
domainCards: levelData.achievements?.domainCards
? levelData.achievements.domainCards.reduce((acc, card, index) => {
- acc[index] = { ...card };
- return acc;
- }, {})
+ acc[index] = { ...card };
+ return acc;
+ }, {})
: (achievements.domainCards ?? {}),
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
},
diff --git a/module/data/countdowns.mjs b/module/data/countdowns.mjs
index 54971d34..7d27197d 100644
--- a/module/data/countdowns.mjs
+++ b/module/data/countdowns.mjs
@@ -77,11 +77,11 @@ export class DhCountdown extends foundry.abstract.DataModel {
static defaultCountdown(type, playerHidden) {
const ownership = playerHidden
? game.users.reduce((acc, user) => {
- if (!user.isGM) {
- acc[user.id] = CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE;
- }
- return acc;
- }, {})
+ if (!user.isGM) {
+ acc[user.id] = CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE;
+ }
+ return acc;
+ }, {})
: undefined;
return {
@@ -102,8 +102,8 @@ export class DhCountdown extends foundry.abstract.DataModel {
value: user.isGM
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
: this.ownership.players[user.id] && this.ownership.players[user.id].type !== -1
- ? this.ownership.players[user.id].type
- : this.ownership.default,
+ ? this.ownership.players[user.id].type
+ : this.ownership.default,
isGM: user.isGM
};
diff --git a/module/data/fields/action/beastformField.mjs b/module/data/fields/action/beastformField.mjs
index 0eeb95c2..e3be9937 100644
--- a/module/data/fields/action/beastformField.mjs
+++ b/module/data/fields/action/beastformField.mjs
@@ -105,8 +105,8 @@ export default class BeastformField extends fields.SchemaField {
baseSize === 'custom'
? 'custom'
: (Object.keys(CONFIG.DH.ACTOR.tokenSize).find(
- x => CONFIG.DH.ACTOR.tokenSize[x].value === CONFIG.DH.ACTOR.tokenSize[baseSize].value + 1
- ) ?? baseSize);
+ x => CONFIG.DH.ACTOR.tokenSize[x].value === CONFIG.DH.ACTOR.tokenSize[baseSize].value + 1
+ ) ?? baseSize);
formData.system.tokenSize = {
...evolvedData.form.system.tokenSize,
size: evolvedSize
diff --git a/module/data/fields/action/costField.mjs b/module/data/fields/action/costField.mjs
index 82cfcd23..1928af41 100644
--- a/module/data/fields/action/costField.mjs
+++ b/module/data/fields/action/costField.mjs
@@ -116,8 +116,8 @@ export default class CostField extends fields.ArrayField {
c.key === 'fear'
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Resources.Fear)
: resources[c.key].isReversed
- ? resources[c.key].max - resources[c.key].value
- : resources[c.key].value;
+ ? resources[c.key].max - resources[c.key].value
+ : resources[c.key].value;
if (c.scalable) c.maxStep = Math.floor((c.max - c.value) / c.step);
return c;
});
@@ -149,8 +149,8 @@ export default class CostField extends fields.ArrayField {
!resources[c.key]
? a
: a && resources[c.key].isReversed
- ? resources[c.key].value + (c.total ?? c.value) <= resources[c.key].max
- : resources[c.key]?.value >= (c.total ?? c.value),
+ ? resources[c.key].value + (c.total ?? c.value) <= resources[c.key].max
+ : resources[c.key]?.value >= (c.total ?? c.value),
true
);
}
diff --git a/module/data/fields/action/countdownField.mjs b/module/data/fields/action/countdownField.mjs
index 96d9dd91..990f8ef1 100644
--- a/module/data/fields/action/countdownField.mjs
+++ b/module/data/fields/action/countdownField.mjs
@@ -87,11 +87,11 @@ export default class CountdownField extends fields.ArrayField {
CONFIG.DH.id,
CONFIG.DH.SETTINGS.gameSettings.Countdowns,
countdownSetting.toObject()
- );
- game.socket.emit(`system.${CONFIG.DH.id}`, {
- action: socketEvent.Refresh,
- data: { refreshType: RefreshType.Countdown }
- });
+ ),
+ game.socket.emit(`system.${CONFIG.DH.id}`, {
+ action: socketEvent.Refresh,
+ data: { refreshType: RefreshType.Countdown }
+ });
Hooks.callAll(socketEvent.Refresh, { refreshType: RefreshType.Countdown });
},
data,
diff --git a/module/data/fields/action/damageField.mjs b/module/data/fields/action/damageField.mjs
index 9b21d3ba..30a5ad7c 100644
--- a/module/data/fields/action/damageField.mjs
+++ b/module/data/fields/action/damageField.mjs
@@ -72,6 +72,9 @@ export default class DamageField extends fields.SchemaField {
damageConfig.source.message = messageId;
damageConfig.directDamage = !!damageConfig.source?.message;
+ // if(damageConfig.source?.message && game.modules.get('dice-so-nice')?.active)
+ // await game.dice3d.waitFor3DAnimationByMessageID(damageConfig.source.message);
+
const damageResult = await CONFIG.Dice.daggerheart.DamageRoll.build(damageConfig);
if (!damageResult) return false;
if (damageResult.actionChatMessageHandled) config.actionChatMessageHandled = true;
diff --git a/module/data/fields/action/effectsField.mjs b/module/data/fields/action/effectsField.mjs
index e943d63d..1053e51d 100644
--- a/module/data/fields/action/effectsField.mjs
+++ b/module/data/fields/action/effectsField.mjs
@@ -1,3 +1,5 @@
+import { emitGMUpdate, GMUpdateEvent } from '../../../systemRegistration/socket.mjs';
+
const fields = foundry.data.fields;
export default class EffectsField extends fields.ArrayField {
@@ -32,7 +34,8 @@ export default class EffectsField extends fields.ArrayField {
}
if (EffectsField.getAutomation() || force) {
targets ??= (message.system?.targets ?? config.targets).filter(t => !config.hasRoll || t.hit);
- EffectsField.applyEffects.call(this, targets);
+ await emitGMUpdate(GMUpdateEvent.UpdateEffect, EffectsField.applyEffects.bind(this), targets, this.uuid);
+ // EffectsField.applyEffects.call(this, config.targets.filter(t => !config.hasRoll || t.hit));
}
}
@@ -56,16 +59,16 @@ export default class EffectsField extends fields.ArrayField {
if (!token) return;
const messageToken = token.document ?? token;
- const conditionImmunities = messageToken.actor.system.rules?.conditionImmunities ?? {};
+ const conditionImmunities = messageToken.actor.system.rules.conditionImmunities ?? {};
messageTargets.push({
token: messageToken,
conditionImmunities: Object.values(conditionImmunities).some(x => x)
? game.i18n.format('DAGGERHEART.UI.Chat.effectSummary.immunityTo', {
- immunities: Object.keys(conditionImmunities)
- .filter(x => conditionImmunities[x])
- .map(x => game.i18n.localize(conditions[x].name))
- .join(', ')
- })
+ immunities: Object.keys(conditionImmunities)
+ .filter(x => conditionImmunities[x])
+ .map(x => game.i18n.localize(conditions[x].name))
+ .join(', ')
+ })
: null
});
diff --git a/module/data/fields/action/saveField.mjs b/module/data/fields/action/saveField.mjs
index 7343ab85..0629353e 100644
--- a/module/data/fields/action/saveField.mjs
+++ b/module/data/fields/action/saveField.mjs
@@ -69,11 +69,11 @@ export default class SaveField extends fields.SchemaField {
game.user === actor.owner
? SaveField.rollSave.call(this, actor, event)
: actor.owner.query('reactionRoll', {
- actionId: this.uuid,
- actorId: actor.uuid,
- event,
- message
- });
+ actionId: this.uuid,
+ actorId: actor.uuid,
+ event,
+ message
+ });
const result = await rollSave;
await SaveField.updateSaveMessage.call(this, result, message, target.id);
subResolve();
@@ -97,8 +97,8 @@ export default class SaveField extends fields.SchemaField {
const title = actor.isNPC
? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
- ability: game.i18n.localize(abilities[this.save.trait]?.label)
- }),
+ ability: game.i18n.localize(abilities[this.save.trait]?.label)
+ }),
rollConfig = {
event,
title,
diff --git a/module/data/fields/action/summonField.mjs b/module/data/fields/action/summonField.mjs
index a2275fa5..ec7881f7 100644
--- a/module/data/fields/action/summonField.mjs
+++ b/module/data/fields/action/summonField.mjs
@@ -1,4 +1,4 @@
-import { itemAbleRollParse, triggerChatRollFx } from '../../../helpers/utils.mjs';
+import { itemAbleRollParse } from '../../../helpers/utils.mjs';
import FormulaField from '../formulaField.mjs';
const fields = foundry.data.fields;
@@ -40,7 +40,7 @@ export default class DHSummonField extends fields.ArrayField {
const roll = new Roll(itemAbleRollParse(summon.count, this.actor, this.item));
await roll.evaluate();
const count = roll.total;
- if (!roll.isDeterministic) rolls.push(roll);
+ if (!roll.isDeterministic && game.modules.get('dice-so-nice')?.active) rolls.push(roll);
const actor = await DHSummonField.getWorldActor(await foundry.utils.fromUuid(summon.actorUUID));
/* Extending summon data in memory so it's available in actionField.toChat. Think it's harmless, but ugly. Could maybe find a better way. */
@@ -56,7 +56,7 @@ export default class DHSummonField extends fields.ArrayField {
}
}
- if (rolls.length) await triggerChatRollFx(rolls);
+ if (rolls.length) await Promise.all(rolls.map(roll => game.dice3d.showForRoll(roll, game.user, true)));
this.actor.sheet?.minimize();
DHSummonField.handleSummon(summonData, this.actor);
diff --git a/module/data/item/ancestry.mjs b/module/data/item/ancestry.mjs
index eae1136c..b9253a3c 100644
--- a/module/data/item/ancestry.mjs
+++ b/module/data/item/ancestry.mjs
@@ -1,6 +1,6 @@
import BaseDataItem from './base.mjs';
import ItemLinkFields from '../../data/fields/itemLinkFields.mjs';
-import { fromUuids, getFeaturesHTMLData } from '../../helpers/utils.mjs';
+import { getFeaturesHTMLData } from '../../helpers/utils.mjs';
export default class DHAncestry extends BaseDataItem {
/** @inheritDoc */
@@ -45,10 +45,6 @@ export default class DHAncestry extends BaseDataItem {
/**@inheritdoc */
async getDescriptionData() {
- // Preload all ancestry features for acquisition from the cache
- // todo: make feature acquisition async and replace feature helpers for methods
- await fromUuids(this._source.features.map(f => f.item));
-
const baseDescription = this.description;
const features = await getFeaturesHTMLData(this.features);
diff --git a/module/data/item/beastform.mjs b/module/data/item/beastform.mjs
index ba274cc7..ee9d9839 100644
--- a/module/data/item/beastform.mjs
+++ b/module/data/item/beastform.mjs
@@ -208,8 +208,8 @@ export default class DHBeastform extends BaseDataItem {
const autoTokenSize =
this.tokenSize.size !== 'custom'
? game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Homebrew).tokenSizes[
- this.tokenSize.size
- ]
+ this.tokenSize.size
+ ]
: null;
const width = autoTokenSize ?? this.tokenSize.width;
const height = autoTokenSize ?? this.tokenSize.height;
diff --git a/module/data/item/class.mjs b/module/data/item/class.mjs
index 470a1e3c..7014e011 100644
--- a/module/data/item/class.mjs
+++ b/module/data/item/class.mjs
@@ -2,7 +2,7 @@ import BaseDataItem from './base.mjs';
import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
import ItemLinkFields from '../fields/itemLinkFields.mjs';
-import { addLinkedItemsDiff, fromUuids, getFeaturesHTMLData, updateLinkedItemApps } from '../../helpers/utils.mjs';
+import { addLinkedItemsDiff, getFeaturesHTMLData, updateLinkedItemApps } from '../../helpers/utils.mjs';
export default class DHClass extends BaseDataItem {
/** @inheritDoc */
@@ -73,16 +73,15 @@ export default class DHClass extends BaseDataItem {
const uuids = [this.parent.uuid, this.parent._stats?.compendiumSource].filter(u => !!u);
const subclasses = game.items.filter(x => x.type === 'subclass' && uuids.includes(x.system.linkedClass));
for (const pack of game.packs) {
- const packIds = [];
const indexes = await pack.getIndex({ fields: ['system.linkedClass'] });
for (const index of indexes) {
if (index.type !== 'subclass') continue;
if (!uuids.includes(index.system?.linkedClass)) continue;
if (subclasses.find(x => x.uuid === index.uuid)) continue;
- packIds.push(index._id);
- }
- if (packIds.length > 0) subclasses.push(...(await pack.getDocuments({ _id__in: packIds })));
+ const subclass = await foundry.utils.fromUuid(index.uuid);
+ subclasses.push(subclass);
+ }
}
return subclasses;
@@ -217,10 +216,6 @@ export default class DHClass extends BaseDataItem {
classItems.push(contentLink.outerHTML);
}
- // Preload all class features for acquisition from the cache
- // todo: make feature acquisition async and replace feature helpers for methods
- await fromUuids(this._source.features.map(f => f.item));
-
const hopeFeatures = await getFeaturesHTMLData(this.hopeFeatures);
const classFeatures = await getFeaturesHTMLData(this.classFeatures);
diff --git a/module/data/item/community.mjs b/module/data/item/community.mjs
index 6f4470b8..6d054976 100644
--- a/module/data/item/community.mjs
+++ b/module/data/item/community.mjs
@@ -1,4 +1,4 @@
-import { fromUuids, getFeaturesHTMLData } from '../../helpers/utils.mjs';
+import { getFeaturesHTMLData } from '../../helpers/utils.mjs';
import ForeignDocumentUUIDArrayField from '../fields/foreignDocumentUUIDArrayField.mjs';
import BaseDataItem from './base.mjs';
@@ -27,10 +27,6 @@ export default class DHCommunity extends BaseDataItem {
/**@inheritdoc */
async getDescriptionData() {
- // Preload all community features for acquisition from the cache
- // todo: make feature acquisition async and replace feature helpers for methods
- await fromUuids(this._source.features);
-
const baseDescription = this.description;
const features = await getFeaturesHTMLData(this.features);
diff --git a/module/data/item/subclass.mjs b/module/data/item/subclass.mjs
index 934b55d3..ecf72de3 100644
--- a/module/data/item/subclass.mjs
+++ b/module/data/item/subclass.mjs
@@ -1,4 +1,5 @@
-import { fromUuids, getFeaturesHTMLData } from '../../helpers/utils.mjs';
+import { getFeaturesHTMLData } from '../../helpers/utils.mjs';
+import ForeignDocumentUUIDField from '../fields/foreignDocumentUUIDField.mjs';
import ItemLinkFields from '../fields/itemLinkFields.mjs';
import BaseDataItem from './base.mjs';
@@ -90,11 +91,6 @@ export default class DHSubclass extends BaseDataItem {
const spellcastTrait = this.spellcastingTrait
? game.i18n.localize(CONFIG.DH.ACTOR.abilities[this.spellcastingTrait].label)
: null;
-
- // Preload all subclass features for acquisition from the cache
- // todo: make feature acquisition async and replace feature helpers for methods
- await fromUuids(this._source.features.map(f => f.item));
-
const foundationFeatures = await getFeaturesHTMLData(this.foundationFeatures);
const specializationFeatures = await getFeaturesHTMLData(this.specializationFeatures);
const masteryFeatures = await getFeaturesHTMLData(this.masteryFeatures);
diff --git a/module/data/levelup.mjs b/module/data/levelup.mjs
index e30bf52d..4dc1c058 100644
--- a/module/data/levelup.mjs
+++ b/module/data/levelup.mjs
@@ -19,12 +19,12 @@ export class DhLevelup extends foundry.abstract.DataModel {
const initialAchievements = i === tier.levels.start ? tier.initialAchievements : {};
const experiences = initialAchievements.experience
? [...Array(initialAchievements.experience.nr).keys()].reduce((acc, _) => {
- acc[foundry.utils.randomID()] = {
- name: '',
- modifier: initialAchievements.experience.modifier
- };
- return acc;
- }, {})
+ acc[foundry.utils.randomID()] = {
+ name: '',
+ modifier: initialAchievements.experience.modifier
+ };
+ return acc;
+ }, {})
: {};
const domainCards = [...Array(tier.domainCardByLevel).keys()].reduce((acc, _) => {
@@ -298,9 +298,9 @@ export class DhLevelupLevel extends foundry.abstract.DataModel {
experiences: levelData.achievements?.experiences ?? achievements.experiences ?? {},
domainCards: levelData.achievements?.domainCards
? levelData.achievements.domainCards.reduce((acc, card, index) => {
- acc[index] = { ...card };
- return acc;
- }, {})
+ acc[index] = { ...card };
+ return acc;
+ }, {})
: (achievements.domainCards ?? {}),
proficiency: levelData.achievements?.proficiency ?? achievements.proficiency ?? null
},
diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs
index b1d3bd0b..509f5d69 100644
--- a/module/dice/d20Roll.mjs
+++ b/module/dice/d20Roll.mjs
@@ -1,5 +1,4 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
-import { triggerChatRollFx } from '../helpers/utils.mjs';
import DHRoll from './dhRoll.mjs';
export default class D20Roll extends DHRoll {
@@ -225,15 +224,4 @@ export default class D20Roll extends DHRoll {
resetFormula() {
return (this._formula = this.constructor.getFormula(this.terms));
}
-
- async reroll(options) {
- const result = await super.reroll(options);
- if (this instanceof game.system.api.dice.DualityRoll) return result;
-
- if (options?.liveRoll) {
- await triggerChatRollFx([result]);
- }
-
- return result;
- }
}
diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs
index ef810ed7..98fd8401 100644
--- a/module/dice/damageRoll.mjs
+++ b/module/dice/damageRoll.mjs
@@ -1,5 +1,5 @@
import DamageDialog from '../applications/dialogs/damageDialog.mjs';
-import { parseRallyDice, triggerChatRollFx } from '../helpers/utils.mjs';
+import { parseRallyDice } from '../helpers/utils.mjs';
import DHRoll from './dhRoll.mjs';
export default class DamageRoll extends DHRoll {
@@ -18,12 +18,7 @@ export default class DamageRoll extends DHRoll {
if (config.evaluate !== false) for (const roll of config.roll) await roll.roll.evaluate();
roll._evaluated = true;
-
- const parts = [];
- for (const roll of config.roll) {
- parts.push(this.postEvaluate(roll));
- roll.roll = JSON.stringify(roll.roll.toJSON());
- }
+ const parts = config.roll.map(r => this.postEvaluate(r));
config.damage = this.unifyDamageRoll(parts);
}
@@ -43,24 +38,25 @@ export default class DamageRoll extends DHRoll {
const chatMessage = config.source?.message
? ui.chat.collection.get(config.source.message)
: getDocumentClass('ChatMessage').applyMode({}, config.rollMode ?? 'public');
-
- const diceRolls = [];
if (game.modules.get('dice-so-nice')?.active) {
- config.mute = true;
const pool = foundry.dice.terms.PoolTerm.fromRolls(
- Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll))
+ Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll))
+ ),
+ diceRoll = Roll.fromTerms([pool]);
+ await game.dice3d.showForRoll(
+ diceRoll,
+ game.user,
+ true,
+ chatMessage.whisper?.length > 0 ? chatMessage.whisper : null,
+ chatMessage.blind
);
- diceRolls.push(Roll.fromTerms([pool]));
+ config.mute = true;
}
-
- await triggerChatRollFx(diceRolls, {
- whisper: chatMessage.whisper?.length > 0 ? chatMessage.whisper : null,
- blind: chatMessage.blind
- });
await super.buildPost(roll, config, message);
-
if (config.source?.message) {
chatMessage.update({ 'system.damage': config.damage });
+
+ if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
}
}
@@ -323,10 +319,9 @@ export default class DamageRoll extends DHRoll {
const newIndex = parsedDiceTerms[dice].results.length;
await term.reroll(`/r1=${termResult.result}`);
- const diceRolls = [];
if (game.modules.get('dice-so-nice')?.active) {
const newResult = parsedDiceTerms[dice].results[newIndex];
- diceRolls.push({
+ const diceSoNiceRoll = {
_evaluated: true,
dice: [
new foundry.dice.terms.Die({
@@ -337,10 +332,11 @@ export default class DamageRoll extends DHRoll {
})
],
options: { appearance: {} }
- });
+ };
+
+ await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true);
}
- await triggerChatRollFx(diceRolls);
await parsedRoll.evaluate();
const results = parsedRoll.dice[dice].results.map(result => ({
diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs
index c28db98f..d6975f71 100644
--- a/module/dice/dhRoll.mjs
+++ b/module/dice/dhRoll.mjs
@@ -1,5 +1,4 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
-import { triggerChatRollFx } from '../helpers/utils.mjs';
export default class DHRoll extends Roll {
baseTerms = [];
@@ -37,7 +36,6 @@ export default class DHRoll extends Roll {
static async buildConfigure(config = {}, message = {}) {
config.hooks = [...this.getHooks(), ''];
config.dialog ??= {};
- config.damageOptions ??= {};
for (const hook of config.hooks) {
if (Hooks.call(`${CONFIG.DH.id}.preRoll${hook.capitalize()}`, config, message) === false) return null;
@@ -77,7 +75,9 @@ export default class DHRoll extends Roll {
}
if (config.skips?.createMessage) {
- await triggerChatRollFx([roll]);
+ if (game.modules.get('dice-so-nice')?.active) {
+ await game.dice3d.showForRoll(roll, game.user, true);
+ }
} else if (!config.source?.message) {
config.message = await this.toMessage(roll, config);
}
@@ -85,7 +85,6 @@ export default class DHRoll extends Roll {
static postEvaluate(roll, config = {}) {
return {
- ...roll.options.roll,
total: roll.total,
formula: roll.formula,
dice: roll.dice.map(d => ({
@@ -104,9 +103,9 @@ export default class DHRoll extends Roll {
if (action?.chatDisplay) {
actionDescription = action
? await foundry.applications.ux.TextEditor.implementation.enrichHTML(action.description, {
- relativeTo: config.data,
- rollData: config.data.getRollData?.() ?? {}
- })
+ relativeTo: config.data,
+ rollData: config.data.getRollData?.() ?? {}
+ })
: null;
config.actionChatMessageHandled = true;
}
diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs
index cc7ee75e..83229425 100644
--- a/module/dice/die/dualityDie.mjs
+++ b/module/dice/die/dualityDie.mjs
@@ -1,4 +1,4 @@
-import { updateResourcesForDualityReroll } from '../helpers.mjs';
+import { ResourceUpdateMap } from '../../data/action/baseAction.mjs';
export default class DualityDie extends foundry.dice.terms.Die {
constructor(options) {
@@ -12,6 +12,24 @@ export default class DualityDie extends foundry.dice.terms.Die {
return roll.withHope ? 1 : roll.withFear ? -1 : 0;
}
+ #updateResources(oldDuality, newDuality, actor) {
+ const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
+ if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return;
+
+ const updates = [];
+ const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0);
+ const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
+ const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
+
+ if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
+ if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
+ if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
+
+ const resourceUpdates = new ResourceUpdateMap(actor);
+ resourceUpdates.addResources(updates);
+ resourceUpdates.updateResources();
+ }
+
async reroll(modifier, options) {
const oldDuality = this.#getDualityState(options.liveRoll.roll);
await super.reroll(modifier, options);
@@ -39,7 +57,7 @@ export default class DualityDie extends foundry.dice.terms.Die {
if (options.liveRoll.isReaction) return;
const newDuality = this.#getDualityState(options.liveRoll.roll);
- updateResourcesForDualityReroll(oldDuality, newDuality, options.liveRoll.actor);
+ this.#updateResources(oldDuality, newDuality, options.liveRoll.actor);
}
}
diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs
index 1cfed094..d58811fe 100644
--- a/module/dice/dualityRoll.mjs
+++ b/module/dice/dualityRoll.mjs
@@ -1,8 +1,6 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
import D20Roll from './d20Roll.mjs';
import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
-import { getDiceSoNicePresets } from '../config/generalConfig.mjs';
-import { updateResourcesForDualityReroll } from './helpers.mjs';
export default class DualityRoll extends D20Roll {
_advantageNumber = 1;
@@ -109,10 +107,10 @@ export default class DualityRoll extends D20Roll {
const label = this.guaranteedCritical
? 'DAGGERHEART.GENERAL.guaranteedCriticalSuccess'
: this.isCritical
- ? 'DAGGERHEART.GENERAL.criticalSuccess'
- : this.withHope
- ? 'DAGGERHEART.GENERAL.hope'
- : 'DAGGERHEART.GENERAL.fear';
+ ? 'DAGGERHEART.GENERAL.criticalSuccess'
+ : this.withHope
+ ? 'DAGGERHEART.GENERAL.hope'
+ : 'DAGGERHEART.GENERAL.fear';
return game.i18n.localize(label);
}
@@ -132,14 +130,20 @@ export default class DualityRoll extends D20Roll {
}
createBaseDice() {
- this.terms = [this.terms[0], this.terms[1], this.terms[2]];
+ if (
+ this.dice[0] instanceof game.system.api.dice.diceTypes.HopeDie &&
+ this.dice[1] instanceof game.system.api.dice.diceTypes.FearDie
+ ) {
+ this.terms = [this.terms[0], this.terms[1], this.terms[2]];
+ return;
+ }
this.terms[0] = new game.system.api.dice.diceTypes.HopeDie({
- faces: this.terms[0]?.faces ?? this.data.rules.dualityRoll?.defaultHopeDice ?? 12
+ faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12
});
this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' });
this.terms[2] = new game.system.api.dice.diceTypes.FearDie({
- faces: this.terms[2]?.faces ?? this.data.rules.dualityRoll?.defaultFearDice ?? 12
+ faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12
});
}
@@ -147,8 +151,8 @@ export default class DualityRoll extends D20Roll {
const advDieClass = this.hasAdvantage
? game.system.api.dice.diceTypes.AdvantageDie
: this.hasDisadvantage
- ? game.system.api.dice.diceTypes.DisadvantageDie
- : null;
+ ? game.system.api.dice.diceTypes.DisadvantageDie
+ : null;
if (advDieClass) {
const advDie = new advDieClass({ faces: this.advantageFaces, number: this.advantageNumber });
if (this.terms.length < 4) {
@@ -384,40 +388,4 @@ export default class DualityRoll extends D20Roll {
if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id);
}
}
-
- async reroll(options) {
- const oldDuality = this.withHope ? 1 : this.withFear ? -1 : 0;
- const rerolled = DualityRoll.fromData((await super.reroll(options)).toJSON());
-
- if (options?.liveRoll) {
- if (game.modules.get('dice-so-nice')?.active) {
- const diceAppearance = await getDiceSoNicePresets(
- rerolled,
- rerolled.dHope.denomination,
- rerolled.dFear.denomination
- );
- rerolled.dHope.options.appearance = diceAppearance.hope.appearance;
- rerolled.dFear.options.appearance = diceAppearance.fear.appearance;
- if (rerolled.dAdvantage) rerolled.dAdvantage.options.appearance = diceAppearance.advantage.appearance;
- if (rerolled.dDisadvantage)
- rerolled.dDisadvantage.options.appearance = diceAppearance.disadvantage.appearance;
-
- await game.dice3d.showForRoll(rerolled, game.user, true);
- } else {
- foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
- }
-
- if (this.options.actionType === 'reaction') return;
-
- const newDuality = rerolled.withHope ? 1 : rerolled.withFear ? -1 : 0;
- const actor = await foundry.utils.fromUuid(this.options.source.actor);
- updateResourcesForDualityReroll(oldDuality, newDuality, actor);
- }
-
- return rerolled;
- }
-
- fromJSON(json) {
- return super.fromJSON(json);
- }
}
diff --git a/module/dice/helpers.mjs b/module/dice/helpers.mjs
deleted file mode 100644
index 35adb8b7..00000000
--- a/module/dice/helpers.mjs
+++ /dev/null
@@ -1,19 +0,0 @@
-import { ResourceUpdateMap } from '../data/action/baseAction.mjs';
-
-export function updateResourcesForDualityReroll(oldDuality, newDuality, actor) {
- const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation);
- if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return;
-
- const updates = [];
- const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0);
- const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0);
- const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0);
-
- if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true });
- if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true });
- if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true });
-
- const resourceUpdates = new ResourceUpdateMap(actor);
- resourceUpdates.addResources(updates);
- resourceUpdates.updateResources();
-}
diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs
index 3518210b..f9239a90 100644
--- a/module/documents/activeEffect.mjs
+++ b/module/documents/activeEffect.mjs
@@ -175,8 +175,8 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect {
return model instanceof documentClass
? model
: model.parent
- ? this.#resolveParentDocument(model.parent, documentClass)
- : null;
+ ? this.#resolveParentDocument(model.parent, documentClass)
+ : null;
}
static getChangeValue(model, change, effect) {
diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs
index fb10435f..e4c11a5c 100644
--- a/module/documents/actor.mjs
+++ b/module/documents/actor.mjs
@@ -65,11 +65,6 @@ export default class DhpActor extends Actor {
};
}
- static createDialog(data, createOptions, options, renderOptions) {
- options.classes = [options.classes ?? [], 'actor-create'].flat(); // handled in hook
- return super.createDialog(data, createOptions, options, renderOptions);
- }
-
/* -------------------------------------------- */
/** @inheritDoc */
@@ -114,14 +109,6 @@ export default class DhpActor extends Actor {
});
}
- if (this.type === 'npc') {
- Object.assign(update, {
- prototypeToken: {
- disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY
- }
- });
- }
-
this.updateSource(update);
}
diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs
index 480f8c69..78bab016 100644
--- a/module/documents/chatMessage.mjs
+++ b/module/documents/chatMessage.mjs
@@ -9,9 +9,9 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
actor && this.isContentVisible
? actor
: {
- img: this.author.avatar ? this.author.avatar : 'icons/svg/mystery-man.svg',
- name: ''
- };
+ img: this.author.avatar ? this.author.avatar : 'icons/svg/mystery-man.svg',
+ name: ''
+ };
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
const html = await super.renderHTML({ actor: actorData, author: this.author });
@@ -183,11 +183,7 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
if (pendingingSaves.length) {
const confirm = await foundry.applications.api.DialogV2.confirm({
window: { title: game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.title') },
- content: `
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.unfinishedRolls')}
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.warning')}
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.confirmation')}
- `
+ content: `${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.unfinishedRolls')}
${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.confirmation')}
${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.warning')}
`
});
if (!confirm) return;
}
@@ -251,24 +247,8 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
const targets = this.filterPermTargets(this.system.hitTargets),
config = foundry.utils.deepClone(this.system);
config.event = event;
-
if (targets.length === 0)
- return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelectedOrPerm'));
- else if (config.hasSave) {
- const pendingingSaves = targets.filter(t => t.saved.success === null);
- if (pendingingSaves.length) {
- const confirm = await foundry.applications.api.DialogV2.confirm({
- window: { title: game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.title') },
- content: `
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.unfinishedRolls')}
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.warning')}
- ${game.i18n.localize('DAGGERHEART.APPLICATIONS.PendingReactionsDialog.confirmation')}
- `
- });
- if (!confirm) return;
- }
- }
-
+ ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelectedOrPerm'));
this.consumeOnSuccess();
this.system.action?.workflow.get('effects')?.execute(config, targets, true);
}
@@ -290,14 +270,14 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage {
behaviors:
effects.length > 0
? [
- {
- name: game.i18n.localize('TYPES.RegionBehavior.applyActiveEffect'),
- type: 'applyActiveEffect',
- system: {
- effects: effects
- }
- }
- ]
+ {
+ name: game.i18n.localize('TYPES.RegionBehavior.applyActiveEffect'),
+ type: 'applyActiveEffect',
+ system: {
+ effects: effects
+ }
+ }
+ ]
: [],
displayMeasurements: true,
locked: false,
diff --git a/module/documents/item.mjs b/module/documents/item.mjs
index 4716068d..603ca594 100644
--- a/module/documents/item.mjs
+++ b/module/documents/item.mjs
@@ -82,7 +82,6 @@ export default class DHItem extends foundry.documents.Item {
/** @inheritdoc */
static async createDialog(data = {}, createOptions = {}, options = {}) {
const { folders, types, template, context = {}, ...dialogOptions } = options;
- dialogOptions.classes = [options.classes ?? [], 'item-create'].flat(); // handled in hook
if (types?.length === 0) {
throw new Error('The array of sub-types to restrict to must not be empty.');
@@ -98,8 +97,8 @@ export default class DHItem extends foundry.documents.Item {
isInventoryItem === true
? 'Inventory Items' //TODO localize
: isInventoryItem === false
- ? 'Character Items' //TODO localize
- : 'Other'; //TODO localize
+ ? 'Character Items' //TODO localize
+ : 'Other'; //TODO localize
return { value: type, label, group };
}
diff --git a/module/documents/token.mjs b/module/documents/token.mjs
index 8e91d4f0..30862724 100644
--- a/module/documents/token.mjs
+++ b/module/documents/token.mjs
@@ -324,7 +324,7 @@ export default class DHToken extends CONFIG.Token.documentClass {
}
let x = 0.5 * bottom;
let y = 0.25;
- for (let k = width - bottom; k--;) {
+ for (let k = width - bottom; k--; ) {
points.push(x, y);
x += 0.5;
y -= 0.25;
@@ -333,7 +333,7 @@ export default class DHToken extends CONFIG.Token.documentClass {
y += 0.25;
}
points.push(x, y);
- for (let k = bottom; k--;) {
+ for (let k = bottom; k--; ) {
y += 0.5;
points.push(x, y);
x += 0.5;
@@ -341,14 +341,14 @@ export default class DHToken extends CONFIG.Token.documentClass {
points.push(x, y);
}
y += 0.5;
- for (let k = top; k--;) {
+ for (let k = top; k--; ) {
points.push(x, y);
x -= 0.5;
y += 0.25;
points.push(x, y);
y += 0.5;
}
- for (let k = width - top; k--;) {
+ for (let k = width - top; k--; ) {
points.push(x, y);
x -= 0.5;
y += 0.25;
@@ -357,7 +357,7 @@ export default class DHToken extends CONFIG.Token.documentClass {
y -= 0.25;
}
points.push(x, y);
- for (let k = top; k--;) {
+ for (let k = top; k--; ) {
y -= 0.5;
points.push(x, y);
x -= 0.5;
@@ -365,7 +365,7 @@ export default class DHToken extends CONFIG.Token.documentClass {
points.push(x, y);
}
y -= 0.5;
- for (let k = bottom; k--;) {
+ for (let k = bottom; k--; ) {
points.push(x, y);
x += 0.5;
y -= 0.25;
diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs
index 3e3f4a16..18c03169 100644
--- a/module/documents/tooltipManager.mjs
+++ b/module/documents/tooltipManager.mjs
@@ -3,6 +3,7 @@ import { AdversaryBPPerEncounter, BaseBPPerEncounter } from '../config/encounter
export default class DhTooltipManager extends foundry.helpers.interaction.TooltipManager {
#wide = false;
#bordered = false;
+ #active = false;
async activate(element, options = {}) {
const { TextEditor } = foundry.applications.ux;
diff --git a/module/enrichers/DamageEnricher.mjs b/module/enrichers/DamageEnricher.mjs
index db0e8729..e3f9c42a 100644
--- a/module/enrichers/DamageEnricher.mjs
+++ b/module/enrichers/DamageEnricher.mjs
@@ -1,7 +1,7 @@
import { parseInlineParams } from './parser.mjs';
export default function DhDamageEnricher(match, _options) {
- const { value, type, inline } = parseInlineParams(match[1], { first: 'value' });
+ const { value, type, inline } = parseInlineParams(match[1]);
if (!value || !type) return match[0];
return getDamageMessage(value, type, inline, match[0]);
}
@@ -59,7 +59,7 @@ export const renderDamageButton = async event => {
{
formula: value,
applyTo: CONFIG.DH.GENERAL.healingTypes.hitPoints.id,
- damageTypes: type
+ type: type
}
]
};
diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs
index a7db01a4..5b66179f 100644
--- a/module/enrichers/DualityRollEnricher.mjs
+++ b/module/enrichers/DualityRollEnricher.mjs
@@ -15,8 +15,8 @@ function getDualityMessage(roll, flavor) {
(roll?.trait
? game.i18n.format('DAGGERHEART.GENERAL.rollWith', { roll: trait })
: roll?.reaction
- ? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
- : game.i18n.localize('DAGGERHEART.GENERAL.duality'));
+ ? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll')
+ : game.i18n.localize('DAGGERHEART.GENERAL.duality'));
const dataLabel = trait
? game.i18n.localize(abilities[roll.trait].label)
@@ -25,14 +25,14 @@ function getDualityMessage(roll, flavor) {
const advantage = roll?.advantage
? CONFIG.DH.ACTIONS.advantageState.advantage.value
: roll?.disadvantage
- ? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
- : undefined;
+ ? CONFIG.DH.ACTIONS.advantageState.disadvantage.value
+ : undefined;
const advantageLabel =
advantage === CONFIG.DH.ACTIONS.advantageState.advantage.value
? 'Advantage'
: advantage === CONFIG.DH.ACTIONS.advantageState.disadvantage.value
- ? 'Disadvantage'
- : undefined;
+ ? 'Disadvantage'
+ : undefined;
const dualityElement = document.createElement('span');
dualityElement.innerHTML = `
diff --git a/module/enrichers/TemplateEnricher.mjs b/module/enrichers/TemplateEnricher.mjs
index bbe93b17..8db3ec14 100644
--- a/module/enrichers/TemplateEnricher.mjs
+++ b/module/enrichers/TemplateEnricher.mjs
@@ -8,8 +8,8 @@ export default function DhTemplateEnricher(match, _options) {
const range =
params.range && Number.isNaN(Number(params.range))
? Object.values(CONFIG.DH.GENERAL.templateRanges).find(
- x => x.id.toLowerCase() === params.range || x.short === params.range
- )?.id
+ x => x.id.toLowerCase() === params.range || x.short === params.range
+ )?.id
: params.range;
if (!CONFIG.DH.GENERAL.templateTypes[type] || !range) return match[0];
diff --git a/module/enrichers/parser.mjs b/module/enrichers/parser.mjs
index 76ea0b73..365caec9 100644
--- a/module/enrichers/parser.mjs
+++ b/module/enrichers/parser.mjs
@@ -8,7 +8,7 @@ export function parseInlineParams(paramString, { first } = {}) {
const parts = paramString.split('|').map(x => x.trim());
const params = {};
for (const [idx, param] of parts.entries()) {
- if (first && idx === 0 && !param.includes(':')) {
+ if (first && idx === 0) {
params[first] = param;
} else {
const parts = param.split(':');
diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs
index af6c2777..7bc5fa25 100644
--- a/module/helpers/utils.mjs
+++ b/module/helpers/utils.mjs
@@ -108,9 +108,9 @@ export const tagifyElement = (element, baseOptions, onChange, tagifyOptions = {}
const options = Array.isArray(baseOptions)
? baseOptions
: Object.keys(baseOptions).map(optionKey => ({
- ...baseOptions[optionKey],
- id: optionKey
- }));
+ ...baseOptions[optionKey],
+ id: optionKey
+ }));
const tagifyElement = new Tagify(element, {
tagTextProp: 'name',
@@ -605,8 +605,8 @@ export function calculateExpectedValue(formulaOrTerms) {
const terms = Array.isArray(formulaOrTerms)
? formulaOrTerms
: typeof formulaOrTerms === 'string'
- ? parseTermsFromSimpleFormula(formulaOrTerms)
- : [formulaOrTerms];
+ ? parseTermsFromSimpleFormula(formulaOrTerms)
+ : [formulaOrTerms];
return terms.reduce((r, t) => r + (t.bonus ?? 0) + (t.diceQuantity ? (t.diceQuantity * (t.faces + 1)) / 2 : 0), 0);
}
@@ -656,8 +656,8 @@ export async function RefreshFeatures(
'resource.value': increasing
? 0
: game.system.api.documents.DhActiveEffect.effectSafeEval(
- Roll.replaceFormulaData(item.system.resource.max, actor.getRollData())
- )
+ Roll.replaceFormulaData(item.system.resource.max, actor.getRollData())
+ )
};
}
if (item.system.metadata?.hasActions) {
@@ -864,58 +864,3 @@ export function camelize(str) {
})
.replace(/\s+/g, '');
}
-
-/** Bulk load a list of documents using uuids. Returns the documents in the same order */
-export async function fromUuids(uuids) {
- // Set up base entries. Each step works on a sublist of these objects
- const entries = uuids.map(uuid => ({
- uuid,
- parsed: foundry.utils.parseUuid(uuid),
- value: foundry.utils.fromUuidSync(uuid)
- }));
-
- // Handle missing uuids for embedded documents first
- // A value may be index data, so we check if its a document
- const packEmbeddedEntries = entries.filter(
- e =>
- !(e.value instanceof Document) &&
- e.parsed &&
- e.parsed.collection instanceof foundry.documents.collections.CompendiumCollection &&
- e.parsed.embedded.length > 0
- );
- await Promise.all(
- packEmbeddedEntries.map(async e => {
- e.value = await fromUuid(e.uuid);
- return true;
- })
- );
-
- // Handle missing top level pack stuff, by batching per pack
- const missingTopLevel = entries.filter(e => !(e.value instanceof Document) && e.value?.pack);
- for (const packGroup of Object.values(Object.groupBy(missingTopLevel, e => e.value.pack))) {
- const pack = game.packs.get(packGroup[0].value.pack);
- if (!pack) continue;
-
- const ids = packGroup.map(p => p.parsed?.id).filter(id => !!id);
- const documents = await pack.getDocuments({ _id__in: ids });
- for (const p of packGroup) {
- p.value = documents.find(d => d.id === p.parsed.id) ?? p.value;
- }
- }
-
- return entries.map(e => e.value);
-}
-/**
- * Triggers DiceSoNice rolls or dice roll audio for rolls. Not used for duality rolls.
- * @param { Roll[] } rolls
- * @return { void }
- */
-export async function triggerChatRollFx(rolls, options = { whisper: false, blind: false }) {
- const { whisper, blind } = options;
- if (game.modules.get('dice-so-nice')?.active) {
- const rerollPromises = rolls.map(roll => game.dice3d.showForRoll(roll, game.user, true, whisper, blind));
- await Promise.allSettled(rerollPromises);
- } else {
- foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice });
- }
-}
diff --git a/module/systemRegistration/migrations.mjs b/module/systemRegistration/migrations.mjs
index b718a127..b4c446b2 100644
--- a/module/systemRegistration/migrations.mjs
+++ b/module/systemRegistration/migrations.mjs
@@ -24,8 +24,8 @@ export async function runMigrations() {
const { originItemType, isMulticlass, identifier } = item.system;
const base = originItemType
? actor.items.find(
- x => x.type === originItemType && Boolean(isMulticlass) === Boolean(x.system.isMulticlass)
- )
+ x => x.type === originItemType && Boolean(isMulticlass) === Boolean(x.system.isMulticlass)
+ )
: null;
if (base) {
const feature = base.system.features.find(x => x.item && x.item.uuid === item.uuid);
diff --git a/package-lock.json b/package-lock.json
index dee096eb..28223032 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,20 +13,18 @@
"rollup": "^4.40.0"
},
"devDependencies": {
- "@eslint/js": "^10.0.1",
"@foundryvtt/foundryvtt-cli": "^1.0.2",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
- "@stylistic/eslint-plugin": "^5.10.0",
"concurrently": "^8.2.2",
"eslint": "^10.2.1",
+ "eslint-plugin-prettier": "^5.5.5",
"globals": "^17.5.0",
"husky": "^9.1.7",
"lint-staged": "^16.4.0",
"postcss": "^8.4.32",
- "rollup-plugin-postcss": "^4.0.2",
- "typescript": "^6.0.3",
- "typescript-eslint": "^8.60.1"
+ "prettier": "^3.5.3",
+ "rollup-plugin-postcss": "^4.0.2"
}
},
"node_modules/@babel/runtime": {
@@ -160,27 +158,6 @@
"node": "^20.19.0 || ^22.13.0 || >=24"
}
},
- "node_modules/@eslint/js": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz",
- "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^20.19.0 || ^22.13.0 || >=24"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "eslint": "^10.0.0"
- },
- "peerDependenciesMeta": {
- "eslint": {
- "optional": true
- }
- }
- },
"node_modules/@eslint/object-schema": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz",
@@ -443,6 +420,19 @@
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true
},
+ "node_modules/@pkgr/core": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
+ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
"node_modules/@rollup/plugin-commonjs": {
"version": "25.0.8",
"resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-25.0.8.tgz",
@@ -771,58 +761,6 @@
"util": "^0.12.4"
}
},
- "node_modules/@stylistic/eslint-plugin": {
- "version": "5.10.0",
- "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.10.0.tgz",
- "integrity": "sha512-nPK52ZHvot8Ju/0A4ucSX1dcPV2/1clx0kLcH5wDmrE4naKso7TUC/voUyU1O9OTKTrR6MYip6LP0ogEMQ9jPQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/types": "^8.56.0",
- "eslint-visitor-keys": "^4.2.1",
- "espree": "^10.4.0",
- "estraverse": "^5.3.0",
- "picomatch": "^4.0.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "peerDependencies": {
- "eslint": "^9.0.0 || ^10.0.0"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@stylistic/eslint-plugin/node_modules/espree": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
- "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.15.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
"node_modules/@trysound/sax": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
@@ -857,288 +795,6 @@
"integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==",
"dev": true
},
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.60.1.tgz",
- "integrity": "sha512-JQ4S5GB0tfjO8BuJ4fcX+HodkzJjYBV+7OJ+wLygaX7OGQ7FudyHL4NSCA6ob+w3Yn+5MkKIozOwQhXeM7opVg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.12.2",
- "@typescript-eslint/scope-manager": "8.60.1",
- "@typescript-eslint/type-utils": "8.60.1",
- "@typescript-eslint/utils": "8.60.1",
- "@typescript-eslint/visitor-keys": "8.60.1",
- "ignore": "^7.0.5",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.60.1",
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.60.1.tgz",
- "integrity": "sha512-A0M6ua6H252bVjPvvtSgl2QA4+ET9S5Mtkb2GDyTxIhH/C4qDItT7RQNO5PhMC6NXGYXOR9dIalcDDgBKT7oFA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.60.1",
- "@typescript-eslint/types": "8.60.1",
- "@typescript-eslint/typescript-estree": "8.60.1",
- "@typescript-eslint/visitor-keys": "8.60.1",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.60.1.tgz",
- "integrity": "sha512-eXkTH2bxmXlqD1RnOPmLZ9ZM9D3VwSx04JOwBnP9RQ+yUA5a2Mu7SfW8uaV2Aon53NJzZlZYuX7tn91Izf+xaw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.60.1",
- "@typescript-eslint/types": "^8.60.1",
- "debug": "^4.4.3"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.60.1.tgz",
- "integrity": "sha512-gvI5OQoptnxQnchOirukCuQ55svJSTuD/4k5+pC267xyBtYry748R9/c3tYUzb/iE6RZfllRz2lVulLCHkTm4w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.60.1",
- "@typescript-eslint/visitor-keys": "8.60.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.60.1.tgz",
- "integrity": "sha512-nh8w4qAteiKuZu3pSSzG/yGKpw0OlkrKnzFmbVRenKaD4qc+7i1GrmZaLVkr8rk4uipiPGMOW4YsM6WmKZ5CvA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.60.1.tgz",
- "integrity": "sha512-sdwTrpjosW7ANQYJ39ZBF1ZyEMEGVB2UsikrserVM/30a/F1dTLnu9bGxEdosugyu5caigjLrR2qiD11asjI1A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.60.1",
- "@typescript-eslint/typescript-estree": "8.60.1",
- "@typescript-eslint/utils": "8.60.1",
- "debug": "^4.4.3",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.60.1.tgz",
- "integrity": "sha512-4h0tY8ppCkdCzcrl2YM5M3my0xsE1Tf8om3owEu5oPWmXwkKRmk0j0LGDzYBGUcAlesEbxBhazqu/K4cu3Ug7w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.60.1.tgz",
- "integrity": "sha512-alpRkfG8hlVE5kdJW2GkfgDgXxold3e8e4l6EnmhRmRLbekgAPCCGDVD++sABy9FcgPFroq+uFcCSM1vR57Cew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.60.1",
- "@typescript-eslint/tsconfig-utils": "8.60.1",
- "@typescript-eslint/types": "8.60.1",
- "@typescript-eslint/visitor-keys": "8.60.1",
- "debug": "^4.4.3",
- "minimatch": "^10.2.2",
- "semver": "^7.7.3",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.5.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
- "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz",
- "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^4.0.2"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
- "version": "10.2.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
- "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==",
- "dev": true,
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "brace-expansion": "^5.0.5"
- },
- "engines": {
- "node": "18 || 20 || >=22"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
- "version": "7.8.2",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.2.tgz",
- "integrity": "sha512-c8jsqUZm3omBOI66G90z1Dyw5z622G8oLG+omfsHBJf3CWQTlOcwOjvOG6wtiNfW6anKm/eA39LMwMtMez2TiQ==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.60.1.tgz",
- "integrity": "sha512-h2MPBLoNtjc3qZWfY3Tl51yPorQ2McHn8pJfcMNTcIvrrZrr90Ykffit0yjrPFWQcRcUxzH20+6OcVdW4yHtUg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.9.1",
- "@typescript-eslint/scope-manager": "8.60.1",
- "@typescript-eslint/types": "8.60.1",
- "@typescript-eslint/typescript-estree": "8.60.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.60.1.tgz",
- "integrity": "sha512-EbGRQg4FhrmwLodl+t3JNAnXHWVr9Vp+Zl1QBZVPY4ByfkzIT8cX3K6QWODHtkIZqqJVEWvhHSx3v5PDHsaQag==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.60.1",
- "eslint-visitor-keys": "^5.0.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
"node_modules/@yaireo/tagify": {
"version": "4.35.1",
"resolved": "https://registry.npmjs.org/@yaireo/tagify/-/tagify-4.35.1.tgz",
@@ -2197,11 +1853,10 @@
}
},
"node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
- "license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
@@ -2586,6 +2241,37 @@
}
}
},
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.5.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz",
+ "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.1",
+ "synckit": "^0.11.12"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
"node_modules/eslint-scope": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
@@ -2825,6 +2511,13 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
@@ -2861,24 +2554,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -5542,6 +5217,34 @@
"node": ">= 0.8.0"
}
},
+ "node_modules/prettier": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
+ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
+ "dev": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz",
+ "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -6350,6 +6053,22 @@
"node": ">= 10"
}
},
+ "node_modules/synckit": {
+ "version": "0.11.12",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
+ "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.2.9"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/synckit"
+ }
+ },
"node_modules/teex": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/teex/-/teex-1.0.1.tgz",
@@ -6397,23 +6116,6 @@
"node": ">=18"
}
},
- "node_modules/tinyglobby": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz",
- "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.4"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -6445,19 +6147,6 @@
"tree-kill": "cli.js"
}
},
- "node_modules/ts-api-utils": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
- "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.12"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4"
- }
- },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
@@ -6482,44 +6171,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/typescript": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
- "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/typescript-eslint": {
- "version": "8.60.1",
- "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.60.1.tgz",
- "integrity": "sha512-6m5hkkRAp8lKvhVpcprAIn5KkehQEh+47oHH2VGnExEh7dhNxXlg6GPAOIu6TxbVQxhebrJDvjl3020ooiWCMA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/eslint-plugin": "8.60.1",
- "@typescript-eslint/parser": "8.60.1",
- "@typescript-eslint/typescript-estree": "8.60.1",
- "@typescript-eslint/utils": "8.60.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
- "typescript": ">=4.8.4 <6.1.0"
- }
- },
"node_modules/unc-path-regex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
diff --git a/package.json b/package.json
index ede90401..73a7fe99 100644
--- a/package.json
+++ b/package.json
@@ -24,20 +24,18 @@
"prepare": "husky"
},
"devDependencies": {
- "@eslint/js": "^10.0.1",
"@foundryvtt/foundryvtt-cli": "^1.0.2",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-node-resolve": "^15.2.3",
- "@stylistic/eslint-plugin": "^5.10.0",
"concurrently": "^8.2.2",
"eslint": "^10.2.1",
+ "eslint-plugin-prettier": "^5.5.5",
"globals": "^17.5.0",
"husky": "^9.1.7",
"lint-staged": "^16.4.0",
"postcss": "^8.4.32",
- "rollup-plugin-postcss": "^4.0.2",
- "typescript": "^6.0.3",
- "typescript-eslint": "^8.60.1"
+ "prettier": "^3.5.3",
+ "rollup-plugin-postcss": "^4.0.2"
},
"lint-staged": {
"**/*": "eslint --fix"
diff --git a/styles/daggerheart.less b/styles/daggerheart.less
index 4da2e043..187402fb 100755
--- a/styles/daggerheart.less
+++ b/styles/daggerheart.less
@@ -1,11 +1,19 @@
@import './less/sheets/index.less';
@import './less/sheets-settings/index.less';
+
@import './less/dialog/index.less';
-@import './less/hud/index.less';
-@import './less/utils/index.less';
+
+@import './less//hud/index.less';
+
+@import './less/utils/colors.less';
+@import './less/utils/fonts.less';
+
@import './less/global/index.less';
+
@import './less/ui/index.less';
+
@import './less/ux/index.less';
@import '../build/tagify.css';
+@import './less/utils/mixin.less';
diff --git a/styles/less/dialog/actions/index.less b/styles/less/dialog/actions/index.less
deleted file mode 100644
index e9cc0401..00000000
--- a/styles/less/dialog/actions/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import "./action-list.less";
\ No newline at end of file
diff --git a/styles/less/dialog/attribution/index.less b/styles/less/dialog/attribution/index.less
deleted file mode 100644
index 2f8eaf45..00000000
--- a/styles/less/dialog/attribution/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import "./sheet.less";
\ No newline at end of file
diff --git a/styles/less/dialog/beastform/index.less b/styles/less/dialog/beastform/index.less
deleted file mode 100644
index 2f8eaf45..00000000
--- a/styles/less/dialog/beastform/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import "./sheet.less";
\ No newline at end of file
diff --git a/styles/less/dialog/character-creation/index.less b/styles/less/dialog/character-creation/index.less
deleted file mode 100644
index adf8d57a..00000000
--- a/styles/less/dialog/character-creation/index.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import "./sheet.less";
-@import "./creation-action-footer.less";
-@import "./selections-container.less";
-@import "./tab-navigation.less";
\ No newline at end of file
diff --git a/styles/less/dialog/character-reset/index.less b/styles/less/dialog/character-reset/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/character-reset/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/compendiumBrowserPackDialog/index.less b/styles/less/dialog/compendiumBrowserPackDialog/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/compendiumBrowserPackDialog/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/damage-reduction/index.less b/styles/less/dialog/damage-reduction/index.less
deleted file mode 100644
index 0b8e94a8..00000000
--- a/styles/less/dialog/damage-reduction/index.less
+++ /dev/null
@@ -1,2 +0,0 @@
-@import './sheets.less';
-@import './damage-reduction-container.less';
\ No newline at end of file
diff --git a/styles/less/dialog/damage-selection/index.less b/styles/less/dialog/damage-selection/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/damage-selection/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/death-move/index.less b/styles/less/dialog/death-move/index.less
deleted file mode 100644
index 8a8a16c4..00000000
--- a/styles/less/dialog/death-move/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './death-move-container.less';
\ No newline at end of file
diff --git a/styles/less/dialog/dice-roll/index.less b/styles/less/dialog/dice-roll/index.less
deleted file mode 100644
index 8e0af6e0..00000000
--- a/styles/less/dialog/dice-roll/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './roll-selection.less';
\ No newline at end of file
diff --git a/styles/less/dialog/downtime/index.less b/styles/less/dialog/downtime/index.less
deleted file mode 100644
index 09cc2dfe..00000000
--- a/styles/less/dialog/downtime/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './downtime-container.less';
\ No newline at end of file
diff --git a/styles/less/dialog/group-roll-dialog/_common.less b/styles/less/dialog/group-roll-dialog/_common.less
new file mode 100644
index 00000000..f74ab8a0
--- /dev/null
+++ b/styles/less/dialog/group-roll-dialog/_common.less
@@ -0,0 +1,44 @@
+h1 {
+ color: @color-text-emphatic;
+ font: 700 var(--font-size-24) var(--dh-font-subtitle);
+ text-align: center;
+}
+
+header {
+ --bar-color: light-dark(@dark-blue, @golden);
+ color: light-dark(@dark, @beige);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+
+ &:not(:first-child) {
+ margin-top: var(--spacer-8);
+ }
+
+ span {
+ padding: 0 10px;
+ }
+
+ &:before {
+ content: ' ';
+ flex: 1;
+ height: 1px;
+ background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--bar-color) 100%);
+ }
+
+ &:after {
+ content: ' ';
+ flex: 1;
+ height: 1px;
+ background: linear-gradient(90deg, var(--bar-color) 0%, rgba(0, 0, 0, 0) 100%);
+ }
+}
+
+img.portrait {
+ border-radius: 50%;
+ border: none;
+ object-fit: cover;
+ object-position: center top;
+ width: 2.5rem;
+ height: 2.5rem;
+}
diff --git a/styles/less/dialog/group-roll-dialog/index.less b/styles/less/dialog/group-roll-dialog/index.less
index f90b57dc..27925fa2 100644
--- a/styles/less/dialog/group-roll-dialog/index.less
+++ b/styles/less/dialog/group-roll-dialog/index.less
@@ -1,3 +1,8 @@
-@import './sheet.less';
-@import './initialization.less';
-@import './main.less';
+.daggerheart.dialog.dh-style.views.group-roll-dialog {
+ .window-content {
+ @import "./_common.less";
+ }
+}
+
+@import "./initialization.less";
+@import "./main.less";
diff --git a/styles/less/dialog/group-roll-dialog/sheet.less b/styles/less/dialog/group-roll-dialog/sheet.less
deleted file mode 100644
index 938710c9..00000000
--- a/styles/less/dialog/group-roll-dialog/sheet.less
+++ /dev/null
@@ -1,48 +0,0 @@
-.daggerheart.dialog.dh-style.views.group-roll-dialog {
- .window-content {
- h1 {
- color: @color-text-emphatic;
- font: 700 var(--font-size-24) var(--dh-font-subtitle);
- text-align: center;
- }
-
- header {
- --bar-color: light-dark(@dark-blue, @golden);
- color: light-dark(@dark, @beige);
- display: flex;
- justify-content: center;
- align-items: center;
-
- &:not(:first-child) {
- margin-top: var(--spacer-8);
- }
-
- span {
- padding: 0 10px;
- }
-
- &:before {
- content: ' ';
- flex: 1;
- height: 1px;
- background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--bar-color) 100%);
- }
-
- &:after {
- content: ' ';
- flex: 1;
- height: 1px;
- background: linear-gradient(90deg, var(--bar-color) 0%, rgba(0, 0, 0, 0) 100%);
- }
- }
-
- img.portrait {
- border-radius: 50%;
- border: none;
- object-fit: cover;
- object-position: center top;
- width: 2.5rem;
- height: 2.5rem;
- }
- }
-}
\ No newline at end of file
diff --git a/styles/less/dialog/image-select/index.less b/styles/less/dialog/image-select/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/image-select/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less
index 4ce4834e..11d9635e 100644
--- a/styles/less/dialog/index.less
+++ b/styles/less/dialog/index.less
@@ -1,20 +1,44 @@
-@import './actions/index.less';
-@import './attribution/index.less';
-@import './beastform/index.less';
-@import './character-creation/index.less';
-@import './character-reset/index.less';
-@import './compendiumBrowserPackDialog/index.less';
-@import './damage-reduction/index.less';
-@import './damage-selection/index.less';
-@import './death-move/index.less';
-@import './dice-roll/index.less';
-@import './downtime/index.less';
-@import './group-roll-dialog/index.less';
+@import './attribution/sheet.less';
@import './level-up/index.less';
-@import './resource-dice/index.less';
-@import './multiclass-choice/index.less';
-@import './tag-team-dialog/index.less';
-@import './image-select/index.less';
-@import './item-transfer/index.less';
-@import './settings/index.less';
-@import './risk-it-all/index.less';
\ No newline at end of file
+
+@import './resource-dice/sheet.less';
+
+@import './actions/action-list.less';
+
+@import './damage-selection/sheet.less';
+
+@import './downtime/downtime-container.less';
+
+@import './death-move/death-move-container.less';
+
+@import './beastform/sheet.less';
+
+@import './character-creation/creation-action-footer.less';
+@import './character-creation/selections-container.less';
+@import './character-creation/sheet.less';
+@import './character-creation/tab-navigation.less';
+
+@import './dice-roll/roll-selection.less';
+@import './damage-reduction/damage-reduction-container.less';
+@import './damage-reduction/sheets.less';
+
+@import './multiclass-choice/sheet.less';
+
+@import './reroll-dialog/sheet.less';
+
+@import './tag-team-dialog/initialization.less';
+@import './tag-team-dialog/sheet.less';
+
+@import './group-roll-dialog/index.less';
+
+@import './image-select/sheet.less';
+
+@import './item-transfer/sheet.less';
+
+@import './settings/change-currency-icon.less';
+
+@import './risk-it-all/sheet.less';
+
+@import './character-reset/sheet.less';
+
+@import './compendiumBrowserPackDialog/sheet.less';
diff --git a/styles/less/dialog/item-transfer/index.less b/styles/less/dialog/item-transfer/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/item-transfer/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/level-up/sheet.less b/styles/less/dialog/level-up/sheet.less
index 9ebd9331..c663f304 100644
--- a/styles/less/dialog/level-up/sheet.less
+++ b/styles/less/dialog/level-up/sheet.less
@@ -14,7 +14,8 @@
.tab.active {
flex: 1;
overflow: auto;
- .with-scroll-shadows();
+ scrollbar-width: thin;
+ scrollbar-color: light-dark(@dark-blue, @golden) transparent;
}
div[data-application-part='form'] {
diff --git a/styles/less/dialog/level-up/summary-container.less b/styles/less/dialog/level-up/summary-container.less
index de7c9f4a..97353ba7 100644
--- a/styles/less/dialog/level-up/summary-container.less
+++ b/styles/less/dialog/level-up/summary-container.less
@@ -18,7 +18,7 @@
overflow: auto;
padding: 10px 0;
max-height: 700px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
.level-achievements-container,
.level-advancements-container {
diff --git a/styles/less/dialog/multiclass-choice/index.less b/styles/less/dialog/multiclass-choice/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/multiclass-choice/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/reroll-dialog/sheet.less b/styles/less/dialog/reroll-dialog/sheet.less
new file mode 100644
index 00000000..71c94d80
--- /dev/null
+++ b/styles/less/dialog/reroll-dialog/sheet.less
@@ -0,0 +1,125 @@
+.daggerheart.dialog.dh-style.views.reroll-dialog {
+ .window-content {
+ max-width: 648px;
+ }
+
+ .reroll-outer-container {
+ h2 {
+ margin: 0;
+ }
+
+ .dices-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 8px;
+ }
+
+ .dice-outer-container {
+ width: 300px;
+
+ legend {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+
+ i {
+ margin-right: 4px;
+ }
+ }
+
+ .dice-container {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
+
+ .result-container {
+ position: relative;
+ aspect-ratio: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 1.375rem;
+ opacity: 0.8;
+
+ &.selected {
+ opacity: 1;
+ border: 1px solid;
+ border-radius: 6px;
+ border-color: light-dark(@dark-blue, @golden);
+ filter: drop-shadow(0 0 3px @golden);
+ }
+
+ &:before {
+ content: ' ';
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+ mask: var(--svg-die) no-repeat center;
+ mask-size: contain;
+ background: linear-gradient(139.01deg, #efe6d8 3.51%, #372e1f 96.49%);
+ }
+
+ &.d4:before {
+ --svg-die: url(../assets/icons/dice/default/d4.svg);
+ }
+ &.d6:before {
+ --svg-die: url(../assets/icons/dice/default/d6.svg);
+ }
+ &.d8:before {
+ --svg-die: url(../assets/icons/dice/default/d8.svg);
+ }
+ &.d10:before {
+ --svg-die: url(../assets/icons/dice/default/d10.svg);
+ }
+ &.d12:before {
+ --svg-die: url('../assets/icons/dice/default/d12.svg');
+ }
+ &.d20:before {
+ --svg-die: url(../assets/icons/dice/default/d20.svg);
+ }
+
+ .to-reroll-result {
+ position: absolute;
+ bottom: -7px;
+ gap: 2px;
+ border: 1px solid;
+ border-radius: 6px;
+ background-image: url(../assets/parchments/dh-parchment-dark.png);
+ display: flex;
+ align-items: center;
+ padding: 2px 6px;
+
+ input {
+ margin: 0;
+ height: 12px;
+ line-height: 0px;
+ position: relative;
+ top: 1px;
+
+ &:before,
+ &:after {
+ line-height: 12px;
+ font-size: var(--font-size-12);
+ }
+ }
+
+ i {
+ font-size: var(--font-size-10);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ footer {
+ margin-top: 8px;
+ display: flex;
+ justify-content: space-between;
+
+ .controls {
+ display: flex;
+ gap: 8px;
+ }
+ }
+}
diff --git a/styles/less/dialog/resource-dice/index.less b/styles/less/dialog/resource-dice/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/resource-dice/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/risk-it-all/index.less b/styles/less/dialog/risk-it-all/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/dialog/risk-it-all/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/dialog/settings/index.less b/styles/less/dialog/settings/index.less
deleted file mode 100644
index 235f3b9c..00000000
--- a/styles/less/dialog/settings/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './change-currency-icon.less';
\ No newline at end of file
diff --git a/styles/less/dialog/tag-team-dialog/index.less b/styles/less/dialog/tag-team-dialog/index.less
deleted file mode 100644
index 8bf56824..00000000
--- a/styles/less/dialog/tag-team-dialog/index.less
+++ /dev/null
@@ -1,2 +0,0 @@
-@import './sheet.less';
-@import './initialization.less';
\ No newline at end of file
diff --git a/styles/less/dialog/tag-team-dialog/sheet.less b/styles/less/dialog/tag-team-dialog/sheet.less
index 82bc0270..3a112146 100644
--- a/styles/less/dialog/tag-team-dialog/sheet.less
+++ b/styles/less/dialog/tag-team-dialog/sheet.less
@@ -194,7 +194,6 @@
.roll-selection-container {
display: flex;
- gap: 16px;
.select-roll-button {
margin-top: 8px;
diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less
index e57ba50d..7af8becd 100755
--- a/styles/less/global/elements.less
+++ b/styles/less/global/elements.less
@@ -283,7 +283,7 @@
}
&.fit-height {
- flex: 1;
+ height: 95%;
}
&.flex {
diff --git a/styles/less/global/prose-mirror.less b/styles/less/global/prose-mirror.less
index e4b1249f..8412235d 100644
--- a/styles/less/global/prose-mirror.less
+++ b/styles/less/global/prose-mirror.less
@@ -40,11 +40,6 @@
ul {
list-style: disc;
}
- }
- // Fixes centering and makes it not render over scrollbar
- &:hover button.toggle:enabled {
- display: flex;
- right: 12px;
}
}
}
diff --git a/styles/less/global/tab-navigation.less b/styles/less/global/tab-navigation.less
index 3d143b4c..038a9749 100755
--- a/styles/less/global/tab-navigation.less
+++ b/styles/less/global/tab-navigation.less
@@ -3,7 +3,8 @@
.daggerheart.dh-style {
.tab-navigation {
- margin: 5px 0 10px 0;
+ margin: 5px 0;
+ height: 40px;
width: 100%;
.navigation-container {
@@ -20,10 +21,6 @@
a {
color: @color-text-emphatic;
-
- &.empty:not(.active) {
- opacity: 0.4;
- }
}
}
}
diff --git a/styles/less/hud/index.less b/styles/less/hud/index.less
index f1f4602e..459f8fd7 100644
--- a/styles/less/hud/index.less
+++ b/styles/less/hud/index.less
@@ -1 +1 @@
-@import './token-hud/index.less';
+@import './token-hud/token-hud.less';
diff --git a/styles/less/hud/token-hud/index.less b/styles/less/hud/token-hud/index.less
deleted file mode 100644
index c86d0939..00000000
--- a/styles/less/hud/token-hud/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './token-hud.less';
\ No newline at end of file
diff --git a/styles/less/hud/token-hud/token-hud.less b/styles/less/hud/token-hud/token-hud.less
index 3b998f4e..3cb94e1e 100644
--- a/styles/less/hud/token-hud/token-hud.less
+++ b/styles/less/hud/token-hud/token-hud.less
@@ -38,9 +38,6 @@
}
.status-effects {
- // TODO: Remove when the issue https://github.com/foundryvtt/foundryvtt/issues/14410 is resolved and Foundry handles it cleanly themselves.
- grid-template-rows: min-content;
-
.effect-control-container {
position: relative;
diff --git a/styles/less/sheets-settings/adversary-settings/index.less b/styles/less/sheets-settings/adversary-settings/index.less
deleted file mode 100644
index 5968577d..00000000
--- a/styles/less/sheets-settings/adversary-settings/index.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import './sheet.less';
-@import './experiences.less';
-@import './features.less';
\ No newline at end of file
diff --git a/styles/less/sheets-settings/adversary-settings/sheet.less b/styles/less/sheets-settings/adversary-settings/sheet.less
index e6eb8d0b..b4b0683b 100644
--- a/styles/less/sheets-settings/adversary-settings/sheet.less
+++ b/styles/less/sheets-settings/adversary-settings/sheet.less
@@ -7,7 +7,7 @@
&.attack.active {
display: flex;
flex-direction: column;
- gap: 12px;
+ gap: 16px;
}
.fieldsets-section {
diff --git a/styles/less/sheets-settings/character-settings/index.less b/styles/less/sheets-settings/character-settings/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/sheets-settings/character-settings/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/sheets-settings/environment-settings/index.less b/styles/less/sheets-settings/environment-settings/index.less
deleted file mode 100644
index 1e6ee34d..00000000
--- a/styles/less/sheets-settings/environment-settings/index.less
+++ /dev/null
@@ -1,2 +0,0 @@
-@import './adversaries.less';
-@import './features.less';
\ No newline at end of file
diff --git a/styles/less/sheets-settings/index.less b/styles/less/sheets-settings/index.less
index 53a03868..f575f848 100644
--- a/styles/less/sheets-settings/index.less
+++ b/styles/less/sheets-settings/index.less
@@ -1,4 +1,8 @@
@import './header.less';
-@import './adversary-settings/index.less';
-@import './character-settings/index.less';
-@import './environment-settings/index.less';
+@import './adversary-settings/sheet.less';
+@import './adversary-settings/experiences.less';
+@import './adversary-settings/features.less';
+@import './character-settings/sheet.less';
+
+@import './environment-settings/features.less';
+@import './environment-settings/adversaries.less';
diff --git a/styles/less/sheets/actions/index.less b/styles/less/sheets/actions/index.less
deleted file mode 100644
index 29ef8645..00000000
--- a/styles/less/sheets/actions/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './actions.less';
\ No newline at end of file
diff --git a/styles/less/sheets/activeEffects/index.less b/styles/less/sheets/activeEffects/index.less
deleted file mode 100644
index 19f8a3a7..00000000
--- a/styles/less/sheets/activeEffects/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './activeEffects.less';
\ No newline at end of file
diff --git a/styles/less/sheets/actors/actor-sheet-shared.less b/styles/less/sheets/actors/actor-sheet-shared.less
index b3eb0469..470067ca 100644
--- a/styles/less/sheets/actors/actor-sheet-shared.less
+++ b/styles/less/sheets/actors/actor-sheet-shared.less
@@ -38,23 +38,11 @@
}
.tab.inventory {
- .gold-section {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr 1fr;
+ .search-section {
+ display: flex;
gap: 10px;
- padding: 10px 10px 0;
-
- .input {
- color: light-dark(@dark, @beige);
- }
+ align-items: center;
}
- }
-
- .search-section {
- display: flex;
- gap: 10px;
- align-items: center;
- justify-content: space-between;
.search-bar {
position: relative;
color: light-dark(@dark-blue-50, @beige-50);
@@ -84,11 +72,22 @@
height: 32px;
position: absolute;
right: 20px;
- font-size: var(--font-size-16);
+ font-size: 16px;
z-index: 1;
color: light-dark(@dark-blue-50, @beige-50);
}
}
+
+ .gold-section {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr 1fr;
+ gap: 10px;
+ padding: 10px 10px 0;
+
+ .input {
+ color: light-dark(@dark, @beige);
+ }
+ }
}
&.limited {
diff --git a/styles/less/sheets/actors/adversary/features.less b/styles/less/sheets/actors/adversary/actions.less
similarity index 82%
rename from styles/less/sheets/actors/adversary/features.less
rename to styles/less/sheets/actors/adversary/actions.less
index 447d050e..af870d9b 100644
--- a/styles/less/sheets/actors/adversary/features.less
+++ b/styles/less/sheets/actors/adversary/actions.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.adversary {
.tab.features {
@@ -9,8 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
padding-bottom: 20px;
- .with-scroll-shadows();
}
}
}
diff --git a/styles/less/sheets/actors/adversary/effects.less b/styles/less/sheets/actors/adversary/effects.less
index 4aa44e51..fbf74249 100644
--- a/styles/less/sheets/actors/adversary/effects.less
+++ b/styles/less/sheets/actors/adversary/effects.less
@@ -1,5 +1,4 @@
@import '../../../utils/colors.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.adversary {
.tab.effects {
@@ -8,8 +7,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
padding-bottom: 20px;
- .with-scroll-shadows();
}
}
}
diff --git a/styles/less/sheets/actors/adversary/header.less b/styles/less/sheets/actors/adversary/header.less
index 1e5e4fa5..8bd3fcee 100644
--- a/styles/less/sheets/actors/adversary/header.less
+++ b/styles/less/sheets/actors/adversary/header.less
@@ -35,7 +35,7 @@
.tags {
display: flex;
gap: 10px;
- padding-bottom: 8px;
+ padding-bottom: 16px;
.tag {
display: flex;
@@ -67,5 +67,11 @@
gap: 12px;
padding: 16px 0;
}
+
+ .adversary-navigation {
+ display: flex;
+ gap: 8px;
+ align-items: center;
+ }
}
}
diff --git a/styles/less/sheets/actors/adversary/index.less b/styles/less/sheets/actors/adversary/index.less
deleted file mode 100644
index 28ff9d22..00000000
--- a/styles/less/sheets/actors/adversary/index.less
+++ /dev/null
@@ -1,7 +0,0 @@
-@import './features.less';
-@import './header.less';
-@import './sheet.less';
-@import './sidebar.less';
-@import './effects.less';
-@import './notes.less';
-
diff --git a/styles/less/sheets/actors/adversary/notes.less b/styles/less/sheets/actors/adversary/notes.less
deleted file mode 100644
index a95d070e..00000000
--- a/styles/less/sheets/actors/adversary/notes.less
+++ /dev/null
@@ -1,3 +0,0 @@
-.application.sheet.daggerheart.actor.dh-style.adversary .tab.notes.active {
- padding-bottom: 20px;
-}
diff --git a/styles/less/sheets/actors/adversary/sidebar.less b/styles/less/sheets/actors/adversary/sidebar.less
index 5db9f5e9..b1bb51db 100644
--- a/styles/less/sheets/actors/adversary/sidebar.less
+++ b/styles/less/sheets/actors/adversary/sidebar.less
@@ -286,8 +286,9 @@
overflow-y: hidden;
padding-top: 10px;
padding-bottom: 20px;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
+
scrollbar-gutter: stable;
- .with-scroll-shadows();
&:hover {
overflow-y: auto;
diff --git a/styles/less/sheets/actors/character/biography.less b/styles/less/sheets/actors/character/biography.less
index 8548a2fb..f8d56735 100644
--- a/styles/less/sheets/actors/character/biography.less
+++ b/styles/less/sheets/actors/character/biography.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.character {
.tab.biography {
@@ -10,10 +9,10 @@
gap: 10px;
height: 100%;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 98%, transparent 100%);
padding-top: 8px;
padding-bottom: 20px;
height: 100%;
- .with-scroll-shadows();
}
.characteristics-section {
diff --git a/styles/less/sheets/actors/character/effects.less b/styles/less/sheets/actors/character/effects.less
index 0ab1007d..ae49fa2d 100644
--- a/styles/less/sheets/actors/character/effects.less
+++ b/styles/less/sheets/actors/character/effects.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.character {
.tab.effects {
@@ -9,8 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
padding-bottom: 20px;
- .with-scroll-shadows();
}
}
}
diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less
index 52b41826..017254a3 100644
--- a/styles/less/sheets/actors/character/features.less
+++ b/styles/less/sheets/actors/character/features.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.character {
.tab.features {
@@ -9,8 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
padding-bottom: 20px;
- .with-scroll-shadows();
}
}
}
diff --git a/styles/less/sheets/actors/character/index.less b/styles/less/sheets/actors/character/index.less
deleted file mode 100644
index edefe0a1..00000000
--- a/styles/less/sheets/actors/character/index.less
+++ /dev/null
@@ -1,8 +0,0 @@
-@import './biography.less';
-@import './effects.less';
-@import './features.less';
-@import './header.less';
-@import './inventory.less';
-@import './loadout.less';
-@import './sheet.less';
-@import './sidebar.less';
diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less
index fcfbbee9..c8d2b584 100644
--- a/styles/less/sheets/actors/character/inventory.less
+++ b/styles/less/sheets/actors/character/inventory.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.character {
.tab.inventory {
@@ -9,9 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
- margin-top: 20px;
- padding-bottom: 20px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
+ padding: 20px 0;
}
}
}
diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less
index fa3e0176..a896b92e 100644
--- a/styles/less/sheets/actors/character/loadout.less
+++ b/styles/less/sheets/actors/character/loadout.less
@@ -1,10 +1,48 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.character {
.tab.loadout {
.search-section {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .search-bar {
+ position: relative;
+ color: light-dark(@dark-blue-50, @beige-50);
+ width: 80%;
+ padding-top: 5px;
+
+ input {
+ border-radius: 50px;
+ background: light-dark(@dark-blue-10, @golden-10);
+ border: none;
+ outline: 2px solid transparent;
+ transition: all 0.3s ease;
+ padding: 0 20px;
+
+ &:hover {
+ outline: 2px solid light-dark(@dark, @golden);
+ }
+
+ &::-webkit-search-cancel-button {
+ -webkit-appearance: none;
+ display: none;
+ }
+ }
+
+ .icon {
+ align-content: center;
+ height: 32px;
+ position: absolute;
+ right: 20px;
+ font-size: var(--font-size-16);
+ z-index: 1;
+ color: light-dark(@dark-blue-50, @beige-50);
+ }
+ }
+
.btn-toggle-view {
background: light-dark(@dark-blue-10, @dark-blue);
border: 1px solid @color-border;
@@ -52,9 +90,8 @@
gap: 10px;
height: 100%;
overflow-y: auto;
- margin-top: 20px;
- padding-bottom: 20px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 98%, transparent 100%);
+ padding: 20px 0;
}
}
}
diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less
index c76ee9ff..3c358d8f 100644
--- a/styles/less/sheets/actors/character/sidebar.less
+++ b/styles/less/sheets/actors/character/sidebar.less
@@ -549,8 +549,8 @@
overflow-y: hidden;
padding-top: 10px;
padding-bottom: 20px;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
scrollbar-gutter: stable;
- .with-scroll-shadows();
&:hover {
overflow-y: auto;
diff --git a/styles/less/sheets/actors/companion/effects.less b/styles/less/sheets/actors/companion/effects.less
index c0cac669..6d7fe061 100644
--- a/styles/less/sheets/actors/companion/effects.less
+++ b/styles/less/sheets/actors/companion/effects.less
@@ -7,8 +7,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
padding-bottom: 20px;
- .with-scroll-shadows();
}
}
}
diff --git a/styles/less/sheets/actors/companion/header.less b/styles/less/sheets/actors/companion/header.less
index aca789a6..b4df96bf 100644
--- a/styles/less/sheets/actors/companion/header.less
+++ b/styles/less/sheets/actors/companion/header.less
@@ -148,8 +148,10 @@
}
.companion-navigation {
+ display: flex;
+ gap: 8px;
+ align-items: baseline;
width: 100%;
- padding: 0 10px;
}
}
}
diff --git a/styles/less/sheets/actors/companion/index.less b/styles/less/sheets/actors/companion/index.less
deleted file mode 100644
index c4931814..00000000
--- a/styles/less/sheets/actors/companion/index.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import './details.less';
-@import './header.less';
-@import './sheet.less';
-@import './effects.less';
diff --git a/styles/less/sheets/actors/companion/sheet.less b/styles/less/sheets/actors/companion/sheet.less
index 8bf8a0b9..f31679ba 100644
--- a/styles/less/sheets/actors/companion/sheet.less
+++ b/styles/less/sheets/actors/companion/sheet.less
@@ -10,16 +10,3 @@
background: url('../assets/parchments/dh-parchment-light.png');
}
});
-
-.application.sheet.daggerheart.actor.dh-style.companion {
- .window-content {
- display: flex;
- }
-
- .tab.active {
- flex: 1;
- overflow: hidden;
- display: flex;
- flex-direction: column;
- }
-}
diff --git a/styles/less/sheets/actors/environment/features.less b/styles/less/sheets/actors/environment/actions.less
similarity index 74%
rename from styles/less/sheets/actors/environment/features.less
rename to styles/less/sheets/actors/environment/actions.less
index 84cf26f8..cc8a345a 100644
--- a/styles/less/sheets/actors/environment/features.less
+++ b/styles/less/sheets/actors/environment/actions.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.environment {
.tab.features {
@@ -9,8 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
- padding-bottom: 4px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
+ padding-bottom: 20px;
}
}
}
diff --git a/styles/less/sheets/actors/environment/header.less b/styles/less/sheets/actors/environment/header.less
index da6954e0..85471af4 100644
--- a/styles/less/sheets/actors/environment/header.less
+++ b/styles/less/sheets/actors/environment/header.less
@@ -138,8 +138,10 @@
}
.environment-navigation {
+ display: flex;
+ gap: 20px;
+ align-items: baseline;
padding: 0 20px;
-
.tab-navigation {
margin-top: 0;
}
diff --git a/styles/less/sheets/actors/environment/index.less b/styles/less/sheets/actors/environment/index.less
deleted file mode 100644
index 211c8e60..00000000
--- a/styles/less/sheets/actors/environment/index.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import './features.less';
-@import './header.less';
-@import './potentialAdversaries.less';
-@import './sheet.less';
diff --git a/styles/less/sheets/actors/environment/potentialAdversaries.less b/styles/less/sheets/actors/environment/potentialAdversaries.less
index f112c0d2..f3c5776a 100644
--- a/styles/less/sheets/actors/environment/potentialAdversaries.less
+++ b/styles/less/sheets/actors/environment/potentialAdversaries.less
@@ -7,8 +7,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
- padding-bottom: 4px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%);
+ padding-bottom: 20px;
}
}
}
diff --git a/styles/less/sheets/actors/index.less b/styles/less/sheets/actors/index.less
deleted file mode 100644
index 959bc0f5..00000000
--- a/styles/less/sheets/actors/index.less
+++ /dev/null
@@ -1,7 +0,0 @@
-@import './actor-sheet-shared.less';
-@import './adversary/index.less';
-@import './character/index.less';
-@import './companion/index.less';
-@import './environment/index.less';
-@import './npc/index.less';
-@import './party/index.less';
\ No newline at end of file
diff --git a/styles/less/sheets/actors/npc/features.less b/styles/less/sheets/actors/npc/features.less
deleted file mode 100644
index a579d9f8..00000000
--- a/styles/less/sheets/actors/npc/features.less
+++ /dev/null
@@ -1,18 +0,0 @@
-.application.sheet.daggerheart.actor.dh-style.npc {
- .tab.features {
- &.active {
- overflow: hidden;
- display: flex;
- flex-direction: column;
- }
-
- .feature-section {
- display: flex;
- flex-direction: column;
- gap: 10px;
- overflow-y: auto;
- padding-bottom: 4px;
- .with-scroll-shadows();
- }
- }
-}
diff --git a/styles/less/sheets/actors/npc/header.less b/styles/less/sheets/actors/npc/header.less
deleted file mode 100644
index 086a254c..00000000
--- a/styles/less/sheets/actors/npc/header.less
+++ /dev/null
@@ -1,83 +0,0 @@
-.application.sheet.daggerheart.actor.dh-style.npc {
- .npc-header-sheet {
- width: 100%;
- display: flex;
-
- .portrait {
- cursor: pointer;
- max-width: 275px;
-
- img {
- height: 275px;
- }
- }
-
- .tags {
- display: flex;
- gap: 10px;
- padding-bottom: 8px;
-
- .tag {
- display: flex;
- flex-direction: row;
- gap: 4px;
- justify-content: center;
- align-items: center;
- padding: 3px 5px;
- font-size: var(--font-size-12);
- font: @font-body;
-
- background: light-dark(@dark-15, @beige-15);
- border: 1px solid light-dark(@dark, @beige);
- border-radius: 3px;
- }
-
- .label {
- display: flex;
- flex-direction: row;
- justify-content: center;
- align-items: center;
- font-size: var(--font-size-12);
- }
- }
-
- .info-section {
- flex: 1;
- padding: 0 15px;
- padding-top: var(--header-height);
- display: flex;
- flex-direction: column;
-
- .name-row {
- display: flex;
- gap: 5px;
- align-items: center;
- justify-content: space-between;
- padding: 8px 0;
-
- h1 {
- display: flex;
- flex: 1;
- padding: 6px 0 0 0;
- font-size: var(--font-size-32);
- text-align: start;
- border: 1px solid transparent;
- outline: 2px solid transparent;
- transition: all 0.3s ease;
- word-break: break-word;
-
- &:hover {
- outline: 2px solid light-dark(@dark, @golden);
- }
- }
- }
-
- .npc-info {
- display: flex;
- flex-direction: column;
- gap: 12px;
- padding: 16px 0;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/styles/less/sheets/actors/npc/index.less b/styles/less/sheets/actors/npc/index.less
deleted file mode 100644
index 2d7d54e3..00000000
--- a/styles/less/sheets/actors/npc/index.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import './sheet.less';
-@import './header.less';
-@import './features.less';
\ No newline at end of file
diff --git a/styles/less/sheets/actors/npc/sheet.less b/styles/less/sheets/actors/npc/sheet.less
deleted file mode 100644
index 8ba3b7a9..00000000
--- a/styles/less/sheets/actors/npc/sheet.less
+++ /dev/null
@@ -1,10 +0,0 @@
-.application.sheet.daggerheart.actor.dh-style.npc {
- .window-content {
- display: grid;
- grid-template-rows: auto auto 1fr;
- }
-
- .npc-navigation {
- padding: 0 15px;
- }
-}
\ No newline at end of file
diff --git a/styles/less/sheets/actors/party/index.less b/styles/less/sheets/actors/party/index.less
deleted file mode 100644
index 56f7a457..00000000
--- a/styles/less/sheets/actors/party/index.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import './header.less';
-@import './party-members.less';
-@import './sheet.less';
-@import './inventory.less';
diff --git a/styles/less/sheets/actors/party/inventory.less b/styles/less/sheets/actors/party/inventory.less
index 444c6a57..8af37a79 100644
--- a/styles/less/sheets/actors/party/inventory.less
+++ b/styles/less/sheets/actors/party/inventory.less
@@ -1,6 +1,5 @@
@import '../../../utils/colors.less';
@import '../../../utils/fonts.less';
-@import '../../../utils/mixin.less';
.application.sheet.daggerheart.actor.dh-style.party {
.tab.inventory {
@@ -9,9 +8,8 @@
flex-direction: column;
gap: 10px;
overflow-y: auto;
- margin-top: 20px;
- padding-bottom: 4px;
- .with-scroll-shadows();
+ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
+ padding: 20px 0;
}
}
}
diff --git a/styles/less/sheets/index.less b/styles/less/sheets/index.less
index 451ae03a..7d595614 100644
--- a/styles/less/sheets/index.less
+++ b/styles/less/sheets/index.less
@@ -1,5 +1,45 @@
-@import './activeEffects/index.less';
-@import './actions/index.less';
-@import './actors/index.less';
-@import './items/index.less';
-@import './rollTables/index.less';
\ No newline at end of file
+@import './actions/actions.less';
+
+@import './actors/actor-sheet-shared.less';
+
+@import './actors/adversary/actions.less';
+@import './actors/adversary/header.less';
+@import './actors/adversary/sheet.less';
+@import './actors/adversary/sidebar.less';
+@import './actors/adversary/effects.less';
+
+@import './actors/character/biography.less';
+@import './actors/character/effects.less';
+@import './actors/character/features.less';
+@import './actors/character/header.less';
+@import './actors/character/inventory.less';
+@import './actors/character/loadout.less';
+@import './actors/character/sheet.less';
+@import './actors/character/sidebar.less';
+
+@import './actors/companion/details.less';
+@import './actors/companion/header.less';
+@import './actors/companion/sheet.less';
+@import './actors/companion/effects.less';
+
+@import './actors/environment/actions.less';
+@import './actors/environment/header.less';
+@import './actors/environment/potentialAdversaries.less';
+@import './actors/environment/sheet.less';
+
+@import './actors/party/header.less';
+@import './actors/party/party-members.less';
+@import './actors/party/sheet.less';
+@import './actors/party/inventory.less';
+
+@import './items/beastform.less';
+@import './items/class.less';
+@import './items/domain-card.less';
+@import './items/feature.less';
+@import './items/heritage.less';
+@import './items/item-sheet-shared.less';
+
+@import './rollTables/sheet.less';
+@import './actions/actions.less';
+
+@import './activeEffects/activeEffects.less';
diff --git a/styles/less/sheets/items/index.less b/styles/less/sheets/items/index.less
deleted file mode 100644
index 7c40a2e3..00000000
--- a/styles/less/sheets/items/index.less
+++ /dev/null
@@ -1,6 +0,0 @@
-@import './beastform.less';
-@import './class.less';
-@import './domain-card.less';
-@import './feature.less';
-@import './heritage.less';
-@import './item-sheet-shared.less';
\ No newline at end of file
diff --git a/styles/less/sheets/rollTables/index.less b/styles/less/sheets/rollTables/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/sheets/rollTables/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/ui/chat/index.less b/styles/less/ui/chat/index.less
deleted file mode 100644
index 9cadbd04..00000000
--- a/styles/less/ui/chat/index.less
+++ /dev/null
@@ -1,10 +0,0 @@
-@import './sheet.less';
-@import './ability-use.less';
-@import './action.less';
-@import './chat.less';
-@import './damage-summary.less';
-@import './deathmoves.less';
-@import './downtime.less';
-@import './effect-summary.less';
-@import './group-roll.less';
-@import './refresh-message.less';
\ No newline at end of file
diff --git a/styles/less/ui/combat-sidebar/index.less b/styles/less/ui/combat-sidebar/index.less
deleted file mode 100644
index 786815ef..00000000
--- a/styles/less/ui/combat-sidebar/index.less
+++ /dev/null
@@ -1,5 +0,0 @@
-@import './combat-sidebar.less';
-@import './combatant-controls.less';
-@import './encounter-controls.less';
-@import './spotlight-control.less';
-@import './token-actions.less';
\ No newline at end of file
diff --git a/styles/less/ui/countdown/countdown.less b/styles/less/ui/countdown/countdown.less
index 63e539ba..66a6c88a 100644
--- a/styles/less/ui/countdown/countdown.less
+++ b/styles/less/ui/countdown/countdown.less
@@ -18,7 +18,7 @@
border: 0;
box-shadow: none;
color: @color-text-primary;
- width: 18.75rem;
+ width: 300px;
pointer-events: all;
align-self: flex-end;
transition: 0.3s right ease-in-out;
@@ -36,7 +36,7 @@
transition: opacity var(--ui-fade-duration);
}
- &:not(.performance-low, .noblur) {
+ :not(.performance-low, .noblur) {
backdrop-filter: blur(5px);
}
@@ -49,7 +49,8 @@
}
&.icon-only {
- width: 12rem;
+ width: 180px;
+ min-width: 180px;
}
.countdowns-header,
@@ -107,8 +108,8 @@
gap: 16px;
img {
- width: 2.75rem;
- height: 2.75rem;
+ width: 44px;
+ height: 44px;
border-radius: 6px;
}
@@ -126,7 +127,7 @@
.countdown-tool-controls {
display: flex;
align-items: center;
- gap: var(--spacer-12);
+ gap: 16px;
}
.progress-tag {
diff --git a/styles/less/ui/countdown/index.less b/styles/less/ui/countdown/index.less
deleted file mode 100644
index 45ecda26..00000000
--- a/styles/less/ui/countdown/index.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import './sheet.less';
-@import './countdown-edit.less';
-@import './countdown.less';
\ No newline at end of file
diff --git a/styles/less/ui/effects-display/index.less b/styles/less/ui/effects-display/index.less
deleted file mode 100644
index 1c574e81..00000000
--- a/styles/less/ui/effects-display/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './sheet.less';
\ No newline at end of file
diff --git a/styles/less/ui/index.less b/styles/less/ui/index.less
index 53a71b9b..31ea8955 100644
--- a/styles/less/ui/index.less
+++ b/styles/less/ui/index.less
@@ -1,11 +1,40 @@
-@import './chat/index.less';
-@import './combat-sidebar/index.less';
-@import './countdown/index.less';
-@import './effects-display/index.less';
-@import './item-browser/index.less';
-@import './ownership-selection/index.less';
-@import './resources/index.less';
-@import './scene-config/index.less';
-@import './scene-navigation/index.less';
-@import './settings/index.less';
-@import './sidebar/index.less';
\ No newline at end of file
+@import './chat/ability-use.less';
+@import './chat/action.less';
+@import './chat/chat.less';
+@import './chat/damage-summary.less';
+@import './chat/downtime.less';
+@import './chat/effect-summary.less';
+@import './chat/group-roll.less';
+@import './chat/refresh-message.less';
+@import './chat/deathmoves.less';
+@import './chat/sheet.less';
+
+@import './combat-sidebar/combat-sidebar.less';
+@import './combat-sidebar/combatant-controls.less';
+@import './combat-sidebar/encounter-controls.less';
+@import './combat-sidebar/spotlight-control.less';
+@import './combat-sidebar/token-actions.less';
+@import './item-browser/item-browser.less';
+
+@import './countdown/countdown.less';
+@import './countdown/countdown-edit.less';
+@import './countdown/sheet.less';
+
+@import './ownership-selection/ownership-selection.less';
+
+@import './resources/resources.less';
+
+@import './settings/settings.less';
+@import './settings/homebrew-settings/domains.less';
+@import './settings/homebrew-settings/types.less';
+@import './settings/homebrew-settings/resources.less';
+@import './settings/appearance-settings/diceSoNice.less';
+
+@import './sidebar/tabs.less';
+@import './sidebar/daggerheartMenu.less';
+
+@import './scene-config/scene-config.less';
+
+@import './effects-display/sheet.less';
+
+@import './scene-navigation/scene-navigation.less';
diff --git a/styles/less/ui/item-browser/index.less b/styles/less/ui/item-browser/index.less
deleted file mode 100644
index 842f716b..00000000
--- a/styles/less/ui/item-browser/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './item-browser.less';
\ No newline at end of file
diff --git a/styles/less/ui/item-browser/item-browser.less b/styles/less/ui/item-browser/item-browser.less
index aac63d7a..1387f444 100644
--- a/styles/less/ui/item-browser/item-browser.less
+++ b/styles/less/ui/item-browser/item-browser.less
@@ -1,6 +1,5 @@
@import '../../utils/colors.less';
@import '../../utils/fonts.less';
-@import '../../utils/mixin.less';
.application.daggerheart.dh-style.compendium-browser {
border: initial;
@@ -243,7 +242,6 @@
.compendium-sidebar > .folder-list {
overflow-y: auto;
scrollbar-gutter: stable;
- .with-scroll-shadows();
}
.item-list-header,
diff --git a/styles/less/ui/ownership-selection/index.less b/styles/less/ui/ownership-selection/index.less
deleted file mode 100644
index 9646670a..00000000
--- a/styles/less/ui/ownership-selection/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './ownership-selection.less';
\ No newline at end of file
diff --git a/styles/less/ui/resources/index.less b/styles/less/ui/resources/index.less
deleted file mode 100644
index a7d08785..00000000
--- a/styles/less/ui/resources/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './resources.less';
\ No newline at end of file
diff --git a/styles/less/ui/scene-config/index.less b/styles/less/ui/scene-config/index.less
deleted file mode 100644
index 4e3af363..00000000
--- a/styles/less/ui/scene-config/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './scene-config.less';
\ No newline at end of file
diff --git a/styles/less/ui/scene-navigation/index.less b/styles/less/ui/scene-navigation/index.less
deleted file mode 100644
index c0765ae7..00000000
--- a/styles/less/ui/scene-navigation/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './scene-navigation.less';
\ No newline at end of file
diff --git a/styles/less/ui/settings/appearance-settings/index.less b/styles/less/ui/settings/appearance-settings/index.less
deleted file mode 100644
index 8b1c109a..00000000
--- a/styles/less/ui/settings/appearance-settings/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './diceSoNice.less';
\ No newline at end of file
diff --git a/styles/less/ui/settings/homebrew-settings/index.less b/styles/less/ui/settings/homebrew-settings/index.less
deleted file mode 100644
index f0a8bfc1..00000000
--- a/styles/less/ui/settings/homebrew-settings/index.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import './domains.less';
-@import './resources.less';
-@import './types.less';
\ No newline at end of file
diff --git a/styles/less/ui/settings/index.less b/styles/less/ui/settings/index.less
deleted file mode 100644
index 4e1aa798..00000000
--- a/styles/less/ui/settings/index.less
+++ /dev/null
@@ -1,3 +0,0 @@
-@import './settings.less';
-@import './appearance-settings/index.less';
-@import './homebrew-settings/index.less';
\ No newline at end of file
diff --git a/styles/less/ui/sidebar/index.less b/styles/less/ui/sidebar/index.less
deleted file mode 100644
index b4961b41..00000000
--- a/styles/less/ui/sidebar/index.less
+++ /dev/null
@@ -1,2 +0,0 @@
-@import './daggerheartMenu.less';
-@import './tabs.less';
\ No newline at end of file
diff --git a/styles/less/utils/index.less b/styles/less/utils/index.less
deleted file mode 100644
index 37b096d3..00000000
--- a/styles/less/utils/index.less
+++ /dev/null
@@ -1,4 +0,0 @@
-@import './colors.less';
-@import './fonts.less';
-@import './mixin.less';
-@import './spacing.less';
\ No newline at end of file
diff --git a/styles/less/utils/mixin.less b/styles/less/utils/mixin.less
index 18b1f9a6..237a5acb 100644
--- a/styles/less/utils/mixin.less
+++ b/styles/less/utils/mixin.less
@@ -160,47 +160,3 @@
@destination @length
);
}
-
-// Scroll shadows, but only if the browser supports. At the time of writing, this doesn't work on firefox
-@supports ((animation-timeline: scroll()) and (animation-range: 0% 100%)) {
- @property --fade-start {
- syntax: "";
- inherits: false;
- initial-value: 0;
- }
-
- @property --fade-end {
- syntax: "";
- inherits: false;
- initial-value: 0;
- }
-
- @keyframes scrollfade {
- 0% {
- --fade-start: 0;
- }
- 10%, 100% {
- --fade-start: 12px;
- }
- 0%, 90% {
- --fade-end: 12px;
- }
- 100% {
- --fade-end: 0;
- }
- }
-}
-
-.with-scroll-shadows() {
- animation: scrollfade;
- animation-timeline: --scrollfade;
- animation-range: entry 0% exit 100%;
- scroll-timeline: --scrollfade y;
- mask-image: linear-gradient(
- 0deg,
- transparent 0%,
- black var(--fade-end),
- black calc(100% - var(--fade-start)),
- transparent 100%
- );
-}
diff --git a/styles/less/ux/autocomplete/index.less b/styles/less/ux/autocomplete/index.less
deleted file mode 100644
index 91007146..00000000
--- a/styles/less/ux/autocomplete/index.less
+++ /dev/null
@@ -1 +0,0 @@
-@import './autocomplete.less';
\ No newline at end of file
diff --git a/styles/less/ux/index.less b/styles/less/ux/index.less
index b6c9a2e7..a73f2d1c 100644
--- a/styles/less/ux/index.less
+++ b/styles/less/ux/index.less
@@ -1,2 +1,10 @@
-@import './autocomplete/index.less';
-@import './tooltip/index.less';
\ No newline at end of file
+@import './tooltip/sheet.less';
+@import './tooltip/tooltip.less';
+@import './tooltip/armorManagement.less';
+@import './tooltip/battlepoints.less';
+@import './tooltip/bordered-tooltip.less';
+@import './tooltip/domain-cards.less';
+
+@import './autocomplete/autocomplete.less';
+
+@import './tooltip/resource-management.less';
diff --git a/styles/less/ux/tooltip/index.less b/styles/less/ux/tooltip/index.less
deleted file mode 100644
index eeec9354..00000000
--- a/styles/less/ux/tooltip/index.less
+++ /dev/null
@@ -1,7 +0,0 @@
-@import './sheet.less';
-@import './armorManagement.less';
-@import './battlepoints.less';
-@import './bordered-tooltip.less';
-@import './domain-cards.less';
-@import './resource-management.less';
-@import './tooltip.less';
\ No newline at end of file
diff --git a/system.json b/system.json
index ed14a17b..2acd7570 100644
--- a/system.json
+++ b/system.json
@@ -2,7 +2,7 @@
"id": "daggerheart",
"title": "Daggerheart",
"description": "An unofficial implementation of the Daggerheart system",
- "version": "2.3.2",
+ "version": "2.2.7",
"compatibility": {
"minimum": "14.361",
"verified": "14.363",
@@ -10,7 +10,7 @@
},
"url": "https://github.com/Foundryborne/daggerheart",
"manifest": "https://raw.githubusercontent.com/Foundryborne/daggerheart/v14/system.json",
- "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.3.2/system.zip",
+ "download": "https://github.com/Foundryborne/daggerheart/releases/download/2.2.7/system.zip",
"authors": [
{
"name": "WBHarry"
@@ -244,14 +244,11 @@
"adversary": {
"htmlFields": ["notes", "description"]
},
- "npc": {
- "htmlFields": ["notes"]
- },
"environment": {
"htmlFields": ["notes", "description"]
},
"party": {
- "htmlFields": ["notes", "description"]
+ "htmlFields": ["notes"]
}
},
"Item": {
diff --git a/templates/dialogs/rerollDialog/damage/main.hbs b/templates/dialogs/rerollDialog/damage/main.hbs
new file mode 100644
index 00000000..5b994bf6
--- /dev/null
+++ b/templates/dialogs/rerollDialog/damage/main.hbs
@@ -0,0 +1,35 @@
+
+ {{#each damage}}
+
{{localize (concat 'DAGGERHEART.CONFIG.HealingType.' @key '.name')}}
+ {{#each this}}
+
+ {{#each this}}
+
+
+
+
+ {{this.selectedResults}}/{{this.maxSelected}} Selected
+
+
+
+ {{#each this.results}}
+
+ {{/each}}
+
+
+ {{/each}}
+
+ {{/each}}
+ {{/each}}
+
\ No newline at end of file
diff --git a/templates/dialogs/rerollDialog/footer.hbs b/templates/dialogs/rerollDialog/footer.hbs
new file mode 100644
index 00000000..5d4ae2b2
--- /dev/null
+++ b/templates/dialogs/rerollDialog/footer.hbs
@@ -0,0 +1,4 @@
+
+ {{localize "DAGGERHEART.GENERAL.reroll"}}
+ {{localize "DAGGERHEART.APPLICATIONS.RerollDialog.acceptCurrentRolls"}}
+
\ No newline at end of file
diff --git a/templates/dialogs/rerollDialog/main.hbs b/templates/dialogs/rerollDialog/main.hbs
new file mode 100644
index 00000000..6f10ce33
--- /dev/null
+++ b/templates/dialogs/rerollDialog/main.hbs
@@ -0,0 +1,35 @@
+
+ {{#each damage}}
+
{{localize (concat 'DAGGERHEART.CONFIG.HealingType.' @key '.name')}}
+ {{#each this}}
+
+ {{#each this}}
+
+
+
+
+ {{this.selectedResults}}/{{this.results.length}} Selected
+
+
+
+ {{#each this.results}}
+
+ {{/each}}
+
+
+ {{/each}}
+
+ {{/each}}
+ {{/each}}
+
\ No newline at end of file
diff --git a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs
index 2a366269..49fc8f4f 100644
--- a/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs
+++ b/templates/dialogs/tagTeamDialog/parts/tagTeamDamageParts.hbs
@@ -16,7 +16,7 @@
{{/unless}}
{{/each}}
{{#if part.modifierTotal}}
- {{#if part.dice.length}}{{#if (gte part.modifierTotal 0)}}+{{else}}-{{/if}} {{/if}}
+ {{#if (gte part.modifierTotal 0)}}+{{else}}-{{/if}}
{{positive part.modifierTotal}}
{{/if}}
diff --git a/templates/sheets-settings/adversary-settings/details.hbs b/templates/sheets-settings/adversary-settings/details.hbs
index 3160fbb9..dc2fd386 100644
--- a/templates/sheets-settings/adversary-settings/details.hbs
+++ b/templates/sheets-settings/adversary-settings/details.hbs
@@ -18,12 +18,6 @@
{{formField systemFields.motivesAndTactics value=document._source.system.motivesAndTactics label=(localize "DAGGERHEART.ACTORS.Adversary.FIELDS.motivesAndTactics.label")}}
-
- {{localize "DAGGERHEART.GENERAL.DamageThresholds.title"}}
- {{formGroup systemFields.damageThresholds.fields.major value=document._source.system.damageThresholds.major label=(localize "DAGGERHEART.GENERAL.DamageThresholds.majorThreshold")}}
- {{formGroup systemFields.damageThresholds.fields.severe value=document._source.system.damageThresholds.severe label=(localize "DAGGERHEART.GENERAL.DamageThresholds.severeThreshold")}}
-
-
{{localize "DAGGERHEART.GENERAL.Resource.plural"}}
@@ -32,4 +26,10 @@
{{/each}}
+
+
+ {{localize "DAGGERHEART.GENERAL.DamageThresholds.title"}}
+ {{formGroup systemFields.damageThresholds.fields.major value=document._source.system.damageThresholds.major label=(localize "DAGGERHEART.GENERAL.DamageThresholds.majorThreshold")}}
+ {{formGroup systemFields.damageThresholds.fields.severe value=document._source.system.damageThresholds.severe label=(localize "DAGGERHEART.GENERAL.DamageThresholds.severeThreshold")}}
+
diff --git a/templates/sheets-settings/npc-settings/details.hbs b/templates/sheets-settings/npc-settings/details.hbs
deleted file mode 100644
index 0e18b488..00000000
--- a/templates/sheets-settings/npc-settings/details.hbs
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
- {{localize "DAGGERHEART.GENERAL.description"}}
- {{formInput systemFields.description value=document._source.system.description}}
-
-
- {{formGroup systemFields.motives value=document._source.system.motives}}
- {{formGroup systemFields.difficulty value=document._source.system.difficulty localize=true}}
-
diff --git a/templates/sheets-settings/npc-settings/features.hbs b/templates/sheets-settings/npc-settings/features.hbs
deleted file mode 100644
index 2f2f5f47..00000000
--- a/templates/sheets-settings/npc-settings/features.hbs
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- {{localize "DOCUMENT.New" type=(localize "TYPES.Item.feature")}}
-
-
- {{localize tabs.features.label}}
-
- {{#each @root.features as |feature|}}
-
-
-
- {{feature.name}}
-
-
-
- {{/each}}
-
-
- {{localize "DAGGERHEART.GENERAL.dropFeaturesHere"}}
-
-
-
\ No newline at end of file
diff --git a/templates/sheets-settings/npc-settings/header.hbs b/templates/sheets-settings/npc-settings/header.hbs
deleted file mode 100644
index c9cb60fe..00000000
--- a/templates/sheets-settings/npc-settings/header.hbs
+++ /dev/null
@@ -1,3 +0,0 @@
-
\ No newline at end of file
diff --git a/templates/sheets/actors/adversary/header.hbs b/templates/sheets/actors/adversary/header.hbs
index 5adc235a..fba96980 100644
--- a/templates/sheets/actors/adversary/header.hbs
+++ b/templates/sheets/actors/adversary/header.hbs
@@ -44,9 +44,10 @@
- {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+
+ {{> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
- {{/ 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+
\ No newline at end of file
diff --git a/templates/sheets/actors/companion/header.hbs b/templates/sheets/actors/companion/header.hbs
index 9c324709..d10c0640 100644
--- a/templates/sheets/actors/companion/header.hbs
+++ b/templates/sheets/actors/companion/header.hbs
@@ -50,10 +50,9 @@
- {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
-
-
-
- {{/ 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+ {{> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+
+
+
\ No newline at end of file
diff --git a/templates/sheets/actors/environment/header.hbs b/templates/sheets/actors/environment/header.hbs
index 1b4073c7..2c6bbb5a 100644
--- a/templates/sheets/actors/environment/header.hbs
+++ b/templates/sheets/actors/environment/header.hbs
@@ -44,10 +44,9 @@
- {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
-
-
-
- {{/ 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+ {{> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
+
+
+
\ No newline at end of file
diff --git a/templates/sheets/actors/npc/features.hbs b/templates/sheets/actors/npc/features.hbs
deleted file mode 100644
index 3b495e74..00000000
--- a/templates/sheets/actors/npc/features.hbs
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
- {{> 'daggerheart.inventory-items'
- title=tabs.features.label
- type='feature'
- collection=@root.features
- hideContextMenu=true
- hideModifyControls=true
- canCreate=@root.editable
- showActions=@root.editable
- }}
-
-
\ No newline at end of file
diff --git a/templates/sheets/actors/npc/header.hbs b/templates/sheets/actors/npc/header.hbs
deleted file mode 100644
index fce300da..00000000
--- a/templates/sheets/actors/npc/header.hbs
+++ /dev/null
@@ -1,42 +0,0 @@
-
\ No newline at end of file
diff --git a/templates/sheets/actors/npc/navigation.hbs b/templates/sheets/actors/npc/navigation.hbs
deleted file mode 100644
index ae684f0d..00000000
--- a/templates/sheets/actors/npc/navigation.hbs
+++ /dev/null
@@ -1,7 +0,0 @@
-
- {{#> 'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
-
-
-
- {{/'systems/daggerheart/templates/sheets/global/tabs/tab-navigation.hbs'}}
-
\ No newline at end of file
diff --git a/templates/sheets/actors/npc/notes.hbs b/templates/sheets/actors/npc/notes.hbs
deleted file mode 100644
index bc9ac3cf..00000000
--- a/templates/sheets/actors/npc/notes.hbs
+++ /dev/null
@@ -1,11 +0,0 @@
-
- {{formInput notes.field value=notes.value enriched=notes.enriched toggled=true}}
-
- {{#if (and showAttribution document.system.attribution.artist)}}
- {{localize "DAGGERHEART.GENERAL.artistAttribution" artist=document.system.attribution.artist}}
- {{/if}}
-
\ No newline at end of file
diff --git a/templates/sheets/actors/party/party-members.hbs b/templates/sheets/actors/party/party-members.hbs
index 55cacb79..c7870bc6 100644
--- a/templates/sheets/actors/party/party-members.hbs
+++ b/templates/sheets/actors/party/party-members.hbs
@@ -42,7 +42,7 @@
{{#if member.difficulty includeZero=true}}
{{member.difficulty}}
{{/if}}
- {{#unless (or (eq member.type 'companion') (eq member.type 'npc'))}}
+ {{#unless (eq member.type 'companion')}}
{{localize "DAGGERHEART.ACTORS.Party.Thresholds.minor"}}
{{member.damageThresholds.major}}
@@ -58,7 +58,7 @@
- {{#unless (or (eq member.type 'companion') (eq member.type 'adversary') (eq member.type 'npc')) }}
+ {{#unless (or (eq member.type 'companion') (eq member.type 'adversary')) }}
{{localize "DAGGERHEART.GENERAL.hope"}}
{{#times member.resources.hope.max}}
@@ -79,7 +79,7 @@
- {{#unless (or (eq member.type 'companion') (eq member.type 'npc')) }}
+ {{#unless (eq member.type 'companion') }}
@@ -101,27 +101,25 @@
{{/unless}}
- {{#unless (eq member.type 'npc')}}
-
-
-
-
-
-
- {{member.resources.stress.value}}
- /
- {{member.resources.stress.max}}
-
-
-
- {{#times member.resources.stress.max}}
-
-
- {{/times}}
-
+
+
+
+
+
+
+ {{member.resources.stress.value}}
+ /
+ {{member.resources.stress.max}}
+
- {{/unless}}
+
+ {{#times member.resources.stress.max}}
+
+
+ {{/times}}
+
+
{{#if member.armorScore.max}}
diff --git a/templates/sheets/global/tabs/tab-navigation.hbs b/templates/sheets/global/tabs/tab-navigation.hbs
index 8af1f140..f9a31d3e 100755
--- a/templates/sheets/global/tabs/tab-navigation.hbs
+++ b/templates/sheets/global/tabs/tab-navigation.hbs
@@ -4,7 +4,7 @@
{{#each tabs as |tab|}}
-
+
{{localize tab.label}}
{{/each}}
diff --git a/templates/ui/chat/parts/roll-part.hbs b/templates/ui/chat/parts/roll-part.hbs
index cfee735f..14e3eaa6 100644
--- a/templates/ui/chat/parts/roll-part.hbs
+++ b/templates/ui/chat/parts/roll-part.hbs
@@ -12,9 +12,13 @@
{{/if}}
- {{#if roll.options.roll.difficulty}}
-
- {{localize "DAGGERHEART.GENERAL.difficulty"}} {{roll.options.roll.difficulty}}
+ {{#if roll.difficulty}}
+
+ {{!-- {{#if canViewSecret}} --}}
+ difficulty {{roll.difficulty}}
+ {{!-- {{else}}
+ {{localize (ifThen roll.success "DAGGERHEART.GENERAL.success" "DAGGERHEART.GENERAL.failure")}}
+ {{/if}} --}}
{{/if}}
diff --git a/templates/ui/combatTracker/combatTrackerHeader.hbs b/templates/ui/combatTracker/combatTrackerHeader.hbs
index 9f5a7561..803286ab 100644
--- a/templates/ui/combatTracker/combatTrackerHeader.hbs
+++ b/templates/ui/combatTracker/combatTrackerHeader.hbs
@@ -50,11 +50,6 @@
{{/if}}
- {{!-- Encounter Name --}}
- {{#if combat.name}}
-
{{ combat.name }}
- {{/if}}
-
{{!-- Combat Status --}}
diff --git a/templates/ui/countdowns.hbs b/templates/ui/countdowns.hbs
index faaffdc5..95067826 100644
--- a/templates/ui/countdowns.hbs
+++ b/templates/ui/countdowns.hbs
@@ -11,20 +11,18 @@
{{#each countdowns as | countdown id |}}
-
+
- {{#unless ../iconOnly}}
-
- {{/unless}}
+ {{#unless ../iconOnly}}
{{countdown.name}} {{/unless}}