From 3d723e7d8cc7e89b0b1eb49b192194705662776a Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Tue, 22 Jul 2025 01:51:49 +0200 Subject: [PATCH 1/3] [Feature] Roll Difficulty Support (#393) * Added difficulty support in rollDialog/rollMessage and [[/dr]] * Fixed /dr chat command --- daggerheart.mjs | 56 +++++-------------- lang/en.json | 3 + module/documents/chatMessage.mjs | 8 +-- module/enrichers/DualityRollEnricher.mjs | 50 +++++++++++++++-- .../less/dialog/dice-roll/roll-selection.less | 4 ++ templates/dialogs/dice-roll/rollSelection.hbs | 10 +++- templates/ui/chat/duality-roll.hbs | 12 +++- 7 files changed, 89 insertions(+), 54 deletions(-) diff --git a/daggerheart.mjs b/daggerheart.mjs index 872da5f3..da04334c 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -8,7 +8,7 @@ import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs' import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs'; import { DualityRollColor } from './module/data/settings/Appearance.mjs'; import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs'; -import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; +import { enrichedDualityRoll, renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs'; import { registerCountdownHooks } from './module/data/countdowns.mjs'; import { @@ -188,49 +188,21 @@ Hooks.on('chatMessage', (_, message) => { } const traitValue = rollCommand.trait?.toLowerCase(); - const advantageState = rollCommand.advantage ? true : rollCommand.disadvantage ? false : null; + const advantage = rollCommand.advantage + ? CONFIG.DH.ACTIONS.advandtageState.advantage.value + : rollCommand.disadvantage + ? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value + : undefined; + const difficulty = rollCommand.difficulty; - // Target not required if an attribute is not used. - const target = traitValue ? getCommandTarget() : undefined; - if (target || !traitValue) { - new Promise(async (resolve, reject) => { - const trait = target ? target.system.traits[traitValue] : undefined; - if (traitValue && !trait) { - ui.notifications.error(game.i18n.localize('DAGGERHEART.UI.Notifications.attributeFaulty')); - reject(); - return; - } - - const title = traitValue - ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { - ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) - }) - : game.i18n.localize('DAGGERHEART.GENERAL.duality'); - - const config = { - title: title, - roll: { - trait: traitValue - }, - data: { - traits: { - [traitValue]: trait - } - }, - source: target, - hasSave: false, - dialog: { configure: false }, - evaluate: true, - advantage: rollCommand.advantage == true, - disadvantage: rollCommand.disadvantage == true - }; - - await CONFIG.Dice.daggerheart['DualityRoll'].build(config); - - resolve(); - }); - } + const target = getCommandTarget(); + const title = traitValue + ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { + ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label) + }) + : game.i18n.localize('DAGGERHEART.GENERAL.duality'); + enrichedDualityRoll({ traitValue, target, difficulty, title, label: 'test', actionType: null, advantage }); return false; } }); diff --git a/lang/en.json b/lang/en.json index ae6ccdf4..017d542d 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1196,6 +1196,7 @@ }, "Roll": { "attack": "Attack Roll", + "difficulty": "Roll (Difficulty {difficulty})", "primaryWeaponAttack": "Primary Weapon Attack Roll", "secondaryWeaponAttack": "Secondary Weapon Attack Roll", "spellcast": "Spellcast Roll", @@ -1310,6 +1311,7 @@ "single": "Experience", "plural": "Experiences" }, + "failure": "Failure", "fear": "Fear", "features": "Features", "formula": "Formula", @@ -1345,6 +1347,7 @@ "scalable": "Scalable", "situationalBonus": "Situational Bonus", "stress": "Stress", + "success": "Success", "take": "Take", "Target": { "single": "Target", diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 409b4dd0..46f95633 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -1,10 +1,10 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { async renderHTML() { if (this.system.messageTemplate) - this.content = await foundry.applications.handlebars.renderTemplate( - this.system.messageTemplate, - this.system - ); + this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, { + ...this.system, + _source: this.system._source + }); /* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */ const html = await super.renderHTML(); diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs index a2da2805..dde82a48 100644 --- a/module/enrichers/DualityRollEnricher.mjs +++ b/module/enrichers/DualityRollEnricher.mjs @@ -21,19 +21,34 @@ function getDualityMessage(roll) { ? game.i18n.localize(abilities[roll.trait].label) : game.i18n.localize('DAGGERHEART.GENERAL.duality'); + const advantage = roll.advantage + ? CONFIG.DH.ACTIONS.advandtageState.advantage.value + : roll.disadvantage + ? CONFIG.DH.ACTIONS.advandtageState.disadvantage.value + : undefined; + const advantageLabel = + advantage === CONFIG.DH.ACTIONS.advandtageState.advantage.value + ? 'Advantage' + : advantage === CONFIG.DH.ACTIONS.advandtageState.disadvantage.value + ? 'Disadvantage' + : undefined; + const dualityElement = document.createElement('span'); dualityElement.innerHTML = ` `; @@ -43,16 +58,39 @@ function getDualityMessage(roll) { export const renderDualityButton = async event => { const button = event.currentTarget, traitValue = button.dataset.trait?.toLowerCase(), - target = getCommandTarget(); + target = getCommandTarget(), + difficulty = button.dataset.difficulty, + advantage = button.dataset.advantage ? Number(button.dataset.advantage) : undefined; + + await enrichedDualityRoll( + { + traitValue, + target, + difficulty, + title: button.dataset.title, + label: button.dataset.label, + actionType: button.dataset.actionType, + advantage + }, + event + ); +}; + +export const enrichedDualityRoll = async ( + { traitValue, target, difficulty, title, label, actionType, advantage }, + event +) => { if (!target) return; const config = { - event: event, - title: button.dataset.title, + event: event ?? {}, + title: title, roll: { modifier: traitValue ? target.system.traits[traitValue].value : null, - label: button.dataset.label, - type: button.dataset.actionType ?? null // Need check + label: label, + difficulty: difficulty, + advantage, + type: actionType ?? null // Need check, }, chatMessage: { template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs' diff --git a/styles/less/dialog/dice-roll/roll-selection.less b/styles/less/dialog/dice-roll/roll-selection.less index af6c3c20..5e36990e 100644 --- a/styles/less/dialog/dice-roll/roll-selection.less +++ b/styles/less/dialog/dice-roll/roll-selection.less @@ -131,13 +131,17 @@ display: flex; align-items: center; gap: 16px; + height: 32px; .roll-mode-select { width: min-content; + height: 100%; } button { flex: 1; + height: 100%; + font-family: @font-body; } } } diff --git a/templates/dialogs/dice-roll/rollSelection.hbs b/templates/dialogs/dice-roll/rollSelection.hbs index ca918145..e3129e30 100644 --- a/templates/dialogs/dice-roll/rollSelection.hbs +++ b/templates/dialogs/dice-roll/rollSelection.hbs @@ -136,14 +136,22 @@ {{/unless}} + {{localize "DAGGERHEART.GENERAL.formula"}}: {{@root.formula}} +
{{else}} diff --git a/templates/ui/chat/duality-roll.hbs b/templates/ui/chat/duality-roll.hbs index 5e67d3a3..8076e093 100644 --- a/templates/ui/chat/duality-roll.hbs +++ b/templates/ui/chat/duality-roll.hbs @@ -140,7 +140,17 @@
-
{{roll.result.label}}
+
+ {{#unless (eq _source.roll.success undefined)}} + {{#if _source.roll.success}} + {{localize "DAGGERHEART.GENERAL.success"}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.result.label}} + {{else}} + {{localize "DAGGERHEART.GENERAL.failure"}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.result.label}} + {{/if}} + {{else}} + {{roll.result.label}} + {{/unless}} +
{{roll.total}}
From 2721dfe417ccc55696e18370434bf3c958e1b6b7 Mon Sep 17 00:00:00 2001 From: Murilo Brito <91566541+moliloo@users.noreply.github.com> Date: Mon, 21 Jul 2025 22:04:17 -0300 Subject: [PATCH 2/3] Feature/enhance style applications (#390) * enhance settings style applications * enhance beastform application and fix action selection style * Start-aligned downtime move fieldsets * requested changes * fixing continue button style * fixing double scroll bars in char sheet * set currency above item list * fix experience not appearing in sidebar --------- Co-authored-by: WBHarry --- lang/en.json | 3 +- module/applications/dialogs/_module.mjs | 1 - .../applications/dialogs/beastformDialog.mjs | 19 +- .../dialogs/costSelectionDialog.mjs | 66 -- module/applications/dialogs/d20RollDialog.mjs | 6 +- .../settings/appearanceSettings.mjs | 7 +- .../settings/automationSettings.mjs | 7 +- .../settings/homebrewSettings.mjs | 7 +- .../settings/rangeMeasurementSettings.mjs | 7 +- .../settings/variantRuleSettings.mjs | 7 +- .../sheets/api/application-mixin.mjs | 8 +- module/data/action/beastformAction.mjs | 4 +- module/systemRegistration/handlebars.mjs | 3 +- styles/less/dialog/beastform/sheet.less | 4 + .../less/dialog/dice-roll/roll-selection.less | 2 + styles/less/global/elements.css | 607 ++++++++++++++++++ styles/less/global/elements.less | 48 ++ .../sheets/actors/character/features.less | 2 +- .../sheets/actors/character/inventory.less | 7 +- .../less/sheets/actors/character/loadout.less | 2 +- .../less/sheets/actors/character/sheet.less | 2 +- styles/less/ui/settings/settings.less | 4 + templates/dialogs/beastform/header.hbs | 3 + templates/dialogs/beastform/tabs.hbs | 18 +- templates/dialogs/dice-roll/costSelection.hbs | 49 +- templates/dialogs/dice-roll/rollSelection.hbs | 14 +- templates/settings/appearance-settings.hbs | 3 + templates/settings/automation-settings.hbs | 3 + templates/settings/homebrew-settings.hbs | 7 +- .../settings/range-measurement-settings.hbs | 3 + templates/settings/variant-rules.hbs | 4 + .../sheets/actors/character/inventory.hbs | 48 +- templates/sheets/actors/character/sidebar.hbs | 2 +- 33 files changed, 823 insertions(+), 154 deletions(-) delete mode 100644 module/applications/dialogs/costSelectionDialog.mjs create mode 100644 styles/less/global/elements.css create mode 100644 templates/dialogs/beastform/header.hbs diff --git a/lang/en.json b/lang/en.json index 017d542d..fc51a610 100755 --- a/lang/en.json +++ b/lang/en.json @@ -756,7 +756,7 @@ }, "SelectAction": { "selectType": "Select Action Type", - "selectAction": "Select Action" + "selectAction": "Action Selection" }, "Traits": { "agility": { @@ -1519,6 +1519,7 @@ } }, "Menu": { + "title": "Daggerheart Game Settings", "automation": { "name": "Automation Settings", "label": "Configure Automation", diff --git a/module/applications/dialogs/_module.mjs b/module/applications/dialogs/_module.mjs index 0722c747..bbffb791 100644 --- a/module/applications/dialogs/_module.mjs +++ b/module/applications/dialogs/_module.mjs @@ -1,5 +1,4 @@ export { default as BeastformDialog } from './beastformDialog.mjs'; -export { default as costSelectionDialog } from './costSelectionDialog.mjs'; export { default as d20RollDialog } from './d20RollDialog.mjs'; export { default as DamageDialog } from './damageDialog.mjs'; export { default as DamageReductionDialog } from './damageReductionDialog.mjs'; diff --git a/module/applications/dialogs/beastformDialog.mjs b/module/applications/dialogs/beastformDialog.mjs index 1d6725ad..3c35b542 100644 --- a/module/applications/dialogs/beastformDialog.mjs +++ b/module/applications/dialogs/beastformDialog.mjs @@ -1,9 +1,11 @@ const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; export default class BeastformDialog extends HandlebarsApplicationMixin(ApplicationV2) { - constructor(configData) { + constructor(configData, item) { super(); + this.item = item; + this.configData = configData; this.selected = null; this.evolved = { form: null }; @@ -14,11 +16,14 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat static DEFAULT_OPTIONS = { tag: 'form', - classes: ['daggerheart', 'views', 'dh-style', 'beastform-selection'], + classes: ['daggerheart', 'views', 'dialog', 'dh-style', 'beastform-selection'], position: { width: 600, height: 'auto' }, + window: { + icon: 'fa-solid fa-paw' + }, actions: { selectBeastform: this.selectBeastform, toggleHybridFeature: this.toggleHybridFeature, @@ -34,11 +39,12 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat }; get title() { - return game.i18n.localize('DAGGERHEART.ITEMS.Beastform.dialogTitle'); + return this.item.name; } /** @override */ static PARTS = { + header: { template: 'systems/daggerheart/templates/dialogs/beastform/header.hbs' }, tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' }, beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.hbs' }, advanced: { template: 'systems/daggerheart/templates/dialogs/beastform/advanced.hbs' }, @@ -262,12 +268,13 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat if (!options.submitted) this.selected = null; } - static async configure(configData) { + static async configure(configData, item) { return new Promise(resolve => { - const app = new this(configData); + const app = new this(configData, item); + const featureItem = item; app.addEventListener( 'close', - () => resolve({ selected: app.selected, evolved: app.evolved, hybrid: app.hybrid }), + () => resolve({ selected: app.selected, evolved: app.evolved, hybrid: app.hybrid, item: featureItem }), { once: true } ); app.render({ force: true }); diff --git a/module/applications/dialogs/costSelectionDialog.mjs b/module/applications/dialogs/costSelectionDialog.mjs deleted file mode 100644 index abb79e6a..00000000 --- a/module/applications/dialogs/costSelectionDialog.mjs +++ /dev/null @@ -1,66 +0,0 @@ -const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; - -export default class CostSelectionDialog extends HandlebarsApplicationMixin(ApplicationV2) { - constructor(costs, uses, action, resolve) { - super({}); - this.costs = costs; - this.uses = uses; - this.action = action; - this.resolve = resolve; - } - - static DEFAULT_OPTIONS = { - tag: 'form', - classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'damage-selection'], - position: { - width: 400, - height: 'auto' - }, - actions: { - sendCost: this.sendCost - }, - form: { - handler: this.updateForm, - submitOnChange: true, - closeOnSubmit: false - } - }; - - /** @override */ - static PARTS = { - costSelection: { - id: 'costSelection', - template: 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs' - } - }; - - /* -------------------------------------------- */ - - /** @inheritDoc */ - get title() { - return `Cost Options`; - } - - async _prepareContext(_options) { - const updatedCosts = this.action.calcCosts(this.costs), - updatedUses = this.action.calcUses(this.uses); - return { - costs: updatedCosts, - uses: updatedUses, - canUse: this.action.hasCost(updatedCosts) && this.action.hasUses(updatedUses) - }; - } - - static async updateForm(event, _, formData) { - const data = foundry.utils.expandObject(formData.object); - this.costs = foundry.utils.mergeObject(this.costs, data.costs); - this.uses = foundry.utils.mergeObject(this.uses, data.uses); - this.render(true); - } - - static sendCost(event) { - event.preventDefault(); - this.resolve({ costs: this.action.getRealCosts(this.costs), uses: this.uses }); - this.close(); - } -} diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 67ca77e6..53fc9d69 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -22,7 +22,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio id: 'roll-selection', classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'roll-selection'], position: { - width: 550 + width: 'auto' }, window: { icon: 'fa-solid fa-dice' @@ -52,10 +52,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio rollSelection: { id: 'rollSelection', template: 'systems/daggerheart/templates/dialogs/dice-roll/rollSelection.hbs' - }, - costSelection: { - id: 'costSelection', - template: 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs' } }; diff --git a/module/applications/settings/appearanceSettings.mjs b/module/applications/settings/appearanceSettings.mjs index 006bab78..78f067c7 100644 --- a/module/applications/settings/appearanceSettings.mjs +++ b/module/applications/settings/appearanceSettings.mjs @@ -12,14 +12,17 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App } get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.appearance.name'); + return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); } static DEFAULT_OPTIONS = { tag: 'form', id: 'daggerheart-appearance-settings', - classes: ['daggerheart', 'setting', 'dh-style'], + classes: ['daggerheart', 'dialog', 'dh-style', 'setting'], position: { width: '600', height: 'auto' }, + window: { + icon: 'fa-solid fa-gears' + }, actions: { reset: this.reset, save: this.save diff --git a/module/applications/settings/automationSettings.mjs b/module/applications/settings/automationSettings.mjs index 75105b16..489bae02 100644 --- a/module/applications/settings/automationSettings.mjs +++ b/module/applications/settings/automationSettings.mjs @@ -12,14 +12,17 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App } get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.automation.name'); + return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); } static DEFAULT_OPTIONS = { tag: 'form', id: 'daggerheart-automation-settings', - classes: ['daggerheart', 'setting', 'dh-style'], + classes: ['daggerheart', 'dh-style', 'dialog', 'setting'], position: { width: '600', height: 'auto' }, + window: { + icon: 'fa-solid fa-gears' + }, actions: { reset: this.reset, save: this.save diff --git a/module/applications/settings/homebrewSettings.mjs b/module/applications/settings/homebrewSettings.mjs index e516be03..d2861595 100644 --- a/module/applications/settings/homebrewSettings.mjs +++ b/module/applications/settings/homebrewSettings.mjs @@ -13,14 +13,17 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli } get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.name'); + return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); } static DEFAULT_OPTIONS = { tag: 'form', id: 'daggerheart-homebrew-settings', - classes: ['daggerheart', 'setting', 'dh-style'], + classes: ['daggerheart', 'dh-style', 'dialog', 'setting'], position: { width: '600', height: 'auto' }, + window: { + icon: 'fa-solid fa-gears' + }, actions: { addItem: this.addItem, editItem: this.editItem, diff --git a/module/applications/settings/rangeMeasurementSettings.mjs b/module/applications/settings/rangeMeasurementSettings.mjs index e9fd332e..410b2cbe 100644 --- a/module/applications/settings/rangeMeasurementSettings.mjs +++ b/module/applications/settings/rangeMeasurementSettings.mjs @@ -12,14 +12,17 @@ export default class DhRangeMeasurementSettings extends HandlebarsApplicationMix } get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.automation.name'); + return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); } static DEFAULT_OPTIONS = { tag: 'form', id: 'daggerheart-automation-settings', - classes: ['daggerheart', 'setting', 'dh-style'], + classes: ['daggerheart', 'dialog', 'dh-style', 'setting'], position: { width: '600', height: 'auto' }, + window: { + icon: 'fa-solid fa-gears' + }, actions: { reset: this.reset, save: this.save diff --git a/module/applications/settings/variantRuleSettings.mjs b/module/applications/settings/variantRuleSettings.mjs index 059e1726..3bc11a68 100644 --- a/module/applications/settings/variantRuleSettings.mjs +++ b/module/applications/settings/variantRuleSettings.mjs @@ -12,14 +12,17 @@ export default class DHVariantRuleSettings extends HandlebarsApplicationMixin(Ap } get title() { - return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.variantRules.name'); + return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title'); } static DEFAULT_OPTIONS = { tag: 'form', id: 'daggerheart-appearance-settings', - classes: ['daggerheart', 'setting', 'dh-style'], + classes: ['daggerheart', 'dialog', 'dh-style', 'setting'], position: { width: '600', height: 'auto' }, + window: { + icon: 'fa-solid fa-gears' + }, actions: { reset: this.reset, save: this.save diff --git a/module/applications/sheets/api/application-mixin.mjs b/module/applications/sheets/api/application-mixin.mjs index 65a43123..6597f130 100644 --- a/module/applications/sheets/api/application-mixin.mjs +++ b/module/applications/sheets/api/application-mixin.mjs @@ -441,9 +441,13 @@ export default function DHApplicationMixin(Base) { const { type: actionType } = (await foundry.applications.api.DialogV2.input({ window: { title: 'Select Action Type' }, + classes: ['daggerheart', 'dh-style'], content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/actionTypes/actionType.hbs', - { types: CONFIG.DH.ACTIONS.actionTypes } + { + types: CONFIG.DH.ACTIONS.actionTypes, + itemName: game.i18n.localize('DAGGERHEART.CONFIG.SelectAction.selectAction') + } ), ok: { label: game.i18n.format('DOCUMENT.Create', { @@ -581,7 +585,7 @@ export default function DHApplicationMixin(Base) { const { actionId } = target.closest('[data-action-id]').dataset; const { actions, attack } = doc.system; const action = attack?.id === actionId ? attack : actions?.find(a => a.id === actionId); - await action.use(event); + await action.use(event, doc); } /** diff --git a/module/data/action/beastformAction.mjs b/module/data/action/beastformAction.mjs index 2116662c..bb926dac 100644 --- a/module/data/action/beastformAction.mjs +++ b/module/data/action/beastformAction.mjs @@ -10,7 +10,9 @@ export default class DhBeastformAction extends DHBaseAction { const abort = await this.handleActiveTransformations(); if (abort) return; - const { selected, evolved, hybrid } = await BeastformDialog.configure(beastformConfig); + const item = args[0]; + + const { selected, evolved, hybrid } = await BeastformDialog.configure(beastformConfig, item); if (!selected) return; await this.transform(selected, evolved, hybrid); diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index b15bf820..fc6decd3 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -30,6 +30,7 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/ui/chat/parts/target-chat.hbs', 'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs', 'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.hbs', - 'systems/daggerheart/templates/dialogs/downtime/activities.hbs' + 'systems/daggerheart/templates/dialogs/downtime/activities.hbs', + 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs' ]); }; diff --git a/styles/less/dialog/beastform/sheet.less b/styles/less/dialog/beastform/sheet.less index ce2e990d..26b6072a 100644 --- a/styles/less/dialog/beastform/sheet.less +++ b/styles/less/dialog/beastform/sheet.less @@ -1,5 +1,6 @@ @import '../../utils/colors.less'; @import '../../utils/mixin.less'; +@import '../../utils/fonts.less'; .theme-light .application.daggerheart.dh-style.views.beastform-selection .beastforms-outer-container { .beastform-title { @@ -209,6 +210,9 @@ button { flex: 1; + font-family: @font-body; + font-weight: bold; + height: 40px; } } } diff --git a/styles/less/dialog/dice-roll/roll-selection.less b/styles/less/dialog/dice-roll/roll-selection.less index 5e36990e..4ee2ee1f 100644 --- a/styles/less/dialog/dice-roll/roll-selection.less +++ b/styles/less/dialog/dice-roll/roll-selection.less @@ -13,6 +13,7 @@ display: flex; flex-direction: column; gap: 12px; + max-width: 550px; .dices-section { display: flex; @@ -141,6 +142,7 @@ button { flex: 1; height: 100%; + font-weight: bold; font-family: @font-body; } } diff --git a/styles/less/global/elements.css b/styles/less/global/elements.css new file mode 100644 index 00000000..2644d93f --- /dev/null +++ b/styles/less/global/elements.css @@ -0,0 +1,607 @@ +@keyframes glow { + 0% { + box-shadow: 0 0 1px 1px #f3c267; + } + 100% { + box-shadow: 0 0 2px 2px #f3c267; + } +} +@keyframes glow-dark { + 0% { + box-shadow: 0 0 1px 1px #18162e; + } + 100% { + box-shadow: 0 0 2px 2px #18162e; + } +} +@font-face { + font-family: 'Cinzel'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-tbnTYo.ttf) format('truetype'); +} +@font-face { + font-family: 'Cinzel'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-jHgTYo.ttf) format('truetype'); +} +@font-face { + font-family: 'Cinzel Decorative'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzeldecorative/v18/daaHSScvJGqLYhG8nNt8KPPswUAPniZoaelD.ttf) format('truetype'); +} +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype'); +} +@font-face { + font-family: 'Montserrat'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype'); +} +.application.sheet.daggerheart.dh-style h1 { + font-family: 'Cinzel Decorative', serif; + margin: 0; + border: none; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h2, +.application.sheet.daggerheart.dh-style h3 { + font-family: 'Cinzel', serif; + margin: 0; + border: none; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h4 { + font-family: 'Montserrat', sans-serif; + font-size: 14px; + border: none; + font-weight: 700; + margin: 0; + text-shadow: none; + color: #f3c267; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style h5 { + font-size: 14px; + color: #f3c267; + margin: 0; + font-weight: normal; +} +.application.sheet.daggerheart.dh-style p, +.application.sheet.daggerheart.dh-style span { + font-family: 'Montserrat', sans-serif; +} +.application.sheet.daggerheart.dh-style small { + font-family: 'Montserrat', sans-serif; + opacity: 0.8; +} +.application.dh-style { + border: 1px solid light-dark(#18162e, #f3c267); +} +.application.dh-style input[type='text'], +.application.dh-style input[type='number'] { + background: light-dark(transparent, transparent); + border-radius: 6px; + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.05); + backdrop-filter: blur(9.5px); + -webkit-backdrop-filter: blur(9.5px); + outline: none; + color: light-dark(#18162e, #f3c267); + border: 1px solid light-dark(#222, #efe6d8); +} +.application.dh-style input[type='text']:hover[type='text'], +.application.dh-style input[type='number']:hover[type='text'], +.application.dh-style input[type='text']:hover[type='number'], +.application.dh-style input[type='number']:hover[type='number'], +.application.dh-style input[type='text']:focus[type='text'], +.application.dh-style input[type='number']:focus[type='text'], +.application.dh-style input[type='text']:focus[type='number'], +.application.dh-style input[type='number']:focus[type='number'] { + background: light-dark(rgba(0, 0, 0, 0.05), rgba(24, 22, 46, 0.33)); + box-shadow: none; + outline: 2px solid light-dark(#222, #efe6d8); +} +.application.dh-style input[type='text']:disabled[type='text'], +.application.dh-style input[type='number']:disabled[type='text'], +.application.dh-style input[type='text']:disabled[type='number'], +.application.dh-style input[type='number']:disabled[type='number'] { + outline: 2px solid transparent; + cursor: not-allowed; +} +.application.dh-style input[type='text']:disabled[type='text']:hover, +.application.dh-style input[type='number']:disabled[type='text']:hover, +.application.dh-style input[type='text']:disabled[type='number']:hover, +.application.dh-style input[type='number']:disabled[type='number']:hover { + background: transparent; +} +.application.dh-style input[type='checkbox']:checked::after, +.application.dh-style input[type='radio']:checked::after { + color: light-dark(#222, #f3c267); +} +.application.dh-style input[type='checkbox']:checked::before, +.application.dh-style input[type='radio']:checked::before { + color: light-dark(#22222240, #f3c26740); +} +.application.dh-style input[type='checkbox']::before, +.application.dh-style input[type='radio']::before { + color: light-dark(#22222240, #f3c26740); +} +.application.dh-style button { + background: light-dark(transparent, #f3c267); + border: 1px solid light-dark(#18162e, #18162e); + color: light-dark(#18162e, #18162e); + outline: none; + box-shadow: none; +} +.application.dh-style button:hover { + background: light-dark(rgba(0, 0, 0, 0.3), #18162e); + color: light-dark(#18162e, #f3c267); +} +.application.dh-style button.glow { + animation: glow 0.75s infinite alternate; +} +.application.dh-style button:disabled { + background: light-dark(transparent, #f3c267); + color: light-dark(#18162e, #18162e); + opacity: 0.6; + cursor: not-allowed; +} +.application.dh-style button:disabled:hover { + background: light-dark(transparent, #f3c267); + color: light-dark(#18162e, #18162e); +} +.application.dh-style select { + background: light-dark(transparent, transparent); + color: light-dark(#222, #efe6d8); + font-family: 'Montserrat', sans-serif; + outline: 2px solid transparent; + border: 1px solid light-dark(#222, #efe6d8); +} +.application.dh-style select:focus, +.application.dh-style select:hover { + outline: 2px solid light-dark(#222, #efe6d8); + box-shadow: none; +} +.application.dh-style select option, +.application.dh-style select optgroup { + color: #efe6d8; + background-color: #18162e; + border-radius: 6px; +} +.application.dh-style select:disabled { + opacity: 0.6; + outline: 2px solid transparent; + cursor: not-allowed; +} +.application.dh-style multi-select { + position: relative; + height: 34px; +} +.application.dh-style multi-select .tags { + justify-content: flex-start; + margin: 4px; + height: inherit; +} +.application.dh-style multi-select .tags .tag { + padding: 0.3rem 0.5rem; + color: light-dark(#18162e, #f3c267); + background-color: light-dark(#18162e10, #f3c26740); + font-family: 'Montserrat', sans-serif; + border-radius: 3px; + transition: 0.13s ease-out; + gap: 0.5rem; + z-index: 1; +} +.application.dh-style multi-select .tags .tag .remove { + font-size: 10px; +} +.application.dh-style multi-select select { + position: absolute; + height: inherit; + outline: initial; +} +.application.dh-style p { + margin: 0; +} +.application.dh-style ul { + margin: 0; + padding: 0; + list-style: none; +} +.application.dh-style li { + margin: 0; +} +.application.dh-style a:hover, +.application.dh-style a.active { + font-weight: bold; + text-shadow: 0 0 8px light-dark(#18162e, #f3c267); +} +.application.dh-style fieldset { + align-items: center; + margin-top: 5px; + border-radius: 6px; + border-color: light-dark(#18162e, #f3c267); +} +.application.dh-style fieldset.glassy { + background-color: light-dark(#18162e10, #f3c26710); + border-color: transparent; +} +.application.dh-style fieldset.glassy legend { + padding: 2px 12px; + border-radius: 3px; + background-color: light-dark(#18162e, #f3c267); + color: light-dark(#efe6d8, #18162e); +} +.application.dh-style fieldset.fit-height { + height: 95%; +} +.application.dh-style fieldset.flex { + display: flex; + gap: 20px; +} +.application.dh-style fieldset.flex.wrap { + flex-wrap: wrap; + gap: 10px 20px; +} +.application.dh-style fieldset.flex .inline-child { + flex: 1; +} +.application.dh-style fieldset .list-w-img { + padding: 5px; +} +.application.dh-style fieldset .list-w-img label { + flex: 1; +} +.application.dh-style fieldset .list-w-img img { + width: 2rem; + height: 2rem; +} +.application.dh-style fieldset.one-column { + display: flex; + flex-direction: column; + align-items: start; + gap: 10px; + min-height: 64px; + flex: 1; +} +.application.dh-style fieldset.one-column > .one-column { + width: 100%; +} +.application.dh-style fieldset.two-columns { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 10px; +} +.application.dh-style fieldset.two-columns.even { + grid-template-columns: 1fr 1fr; +} +.application.dh-style fieldset.two-columns .full-width { + grid-column: span 2; +} +.application.dh-style fieldset legend { + font-family: 'Montserrat', sans-serif; + font-weight: bold; + color: light-dark(#18162e, #f3c267); +} +.application.dh-style fieldset input[type='text'], +.application.dh-style fieldset input[type='number'] { + color: light-dark(#222, #efe6d8); + font-family: 'Montserrat', sans-serif; + transition: all 0.3s ease; + outline: 2px solid transparent; +} +.application.dh-style fieldset input[type='text']:focus, +.application.dh-style fieldset input[type='number']:focus, +.application.dh-style fieldset input[type='text']:hover, +.application.dh-style fieldset input[type='number']:hover { + outline: 2px solid light-dark(#222, #efe6d8); +} +.application.dh-style fieldset[disabled], +.application.dh-style fieldset.child-disabled .form-group, +.application.dh-style fieldset select[disabled], +.application.dh-style fieldset input[disabled] { + opacity: 0.5; +} +.application.dh-style fieldset.child-disabled .form-group { + pointer-events: none; +} +.application.dh-style fieldset .nest-inputs { + display: flex; + align-items: center; + width: 100%; + gap: 5px; +} +.application.dh-style fieldset .nest-inputs .btn { + padding-top: 15px; +} +.application.dh-style fieldset .nest-inputs .image { + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; +} +.application.dh-style fieldset .nest-inputs > .checkbox { + align-self: end; +} +.application.dh-style fieldset .form-group { + width: 100%; +} +.application.dh-style fieldset .form-group label { + font-family: 'Montserrat', sans-serif; + font-weight: bold; + font-size: smaller; +} +.application.dh-style fieldset .form-group.checkbox { + width: fit-content; + display: flex; + align-items: center; +} +.application.dh-style fieldset .form-group.checkbox .form-fields { + height: 32px; + align-content: center; +} +.application.dh-style fieldset:has(.list-w-img) { + gap: 0; +} +.application.dh-style .two-columns { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 10px; +} +.application.dh-style .two-columns.even { + grid-template-columns: 1fr 1fr; +} +.application.dh-style line-div { + display: block; + height: 1px; + width: 100%; + border-bottom: 1px solid light-dark(#18162e, #f3c267); + mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); +} +.application.dh-style side-line-div { + display: block; + height: 1px; + width: 100%; + border-bottom: 1px solid light-dark(#18162e, #f3c267); + mask-image: linear-gradient(270deg, transparent 0%, black 100%); +} +.application.dh-style side-line-div.invert { + mask-image: linear-gradient(270deg, black 0%, transparent 100%); +} +.application.dh-style .item-description { + opacity: 1; + transform: translateY(0); + grid-column: 1/-1; + transition: opacity 0.3s ease-out, transform 0.3s ease-out; +} +.application.dh-style .item-description.invisible { + height: 0; + opacity: 0; + overflow: hidden; + transform: translateY(-20px); + transform-origin: top; +} +.application.dh-style .item-buttons { + grid-column: span 3; + display: flex; + gap: 8px; + flex-wrap: wrap; +} +.application.dh-style .item-buttons button { + white-space: nowrap; +} +.application.setting.dh-style fieldset h2, +.application.setting.dh-style fieldset h3, +.application.setting.dh-style fieldset h4 { + margin: 8px 0 4px; + text-align: center; +} +.application.setting.dh-style fieldset .title-hint { + font-size: 12px; + font-variant: small-caps; + text-align: center; +} +.application.setting.dh-style fieldset .field-section .split-section { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} +.application.setting.dh-style fieldset .label-container { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; +} +.application.setting.dh-style fieldset .label-container label { + align-self: center; + text-align: center; +} +.application.setting.dh-style footer { + margin-top: 8px; + display: flex; + gap: 8px; +} +.application.setting.dh-style footer button { + flex: 1; +} +.application.setting.dh-style .form-group { + display: flex; + justify-content: space-between; + align-items: center; +} +.application.setting.dh-style .form-group label { + font-size: 16px; + font-family: 'Montserrat', sans-serif; +} +.application.setting.dh-style .form-group .form-fields { + display: flex; + gap: 4px; + align-items: center; +} +.system-daggerheart .tagify { + background: light-dark(transparent, transparent); + border: 1px solid light-dark(#222, #efe6d8); + height: 34px; + --tags-disabled-bg: none; + --tags-border-color: none; + --tags-hover-border-color: none; + --tags-focus-border-color: none; + --tag-border-radius: 3px; + --tag-bg: light-dark(#18162e, #f3c267); + --tag-remove-btn-color: light-dark(#18162e, #f3c267); + --tag-hover: light-dark(#18162e, #f3c267); + --tag-text-color: light-dark(#efe6d8, #222); + --tag-text-color--edit: light-dark(#efe6d8, #222); + --tag-pad: 0.3em 0.5em; + --tag-inset-shadow-size: 1.2em; + --tag-invalid-color: #d39494; + --tag-invalid-bg: rgba(211, 148, 148, 0.5); + --tag--min-width: 1ch; + --tag--max-width: 100%; + --tag-hide-transition: 0.3s; + --tag-remove-bg: light-dark(#18162e40, #f3c26740); + --tag-remove-btn-color: light-dark(#efe6d8, #222); + --tag-remove-btn-bg: none; + --tag-remove-btn-bg--hover: light-dark(#efe6d8, #222); + --input-color: inherit; + --placeholder-color: light-dark(#efe6d815, #22222215); + --placeholder-color-focus: light-dark(#efe6d815, #22222215); + --loader-size: 0.8em; + --readonly-striped: 1; + border-radius: 3px; + margin-right: 1px; +} +.system-daggerheart .tagify tag div { + display: flex; + justify-content: space-between; + align-items: center; + height: 22px; +} +.system-daggerheart .tagify tag div span { + font-weight: 400; +} +.system-daggerheart .tagify tag div img { + margin-left: 8px; + height: 20px; + width: 20px; +} +.system-daggerheart .tagify__dropdown { + border: 1px solid light-dark(#222, #efe6d8) !important; + font-family: 'Montserrat', sans-serif; + color: light-dark(#222, #efe6d8); +} +.system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-dark.png); + background-color: transparent; + border: 0; + color: light-dark(#222, #efe6d8); +} +.system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper .tagify__dropdown__item--active { + background-color: light-dark(#222, #efe6d8); + color: light-dark(#efe6d8, #222); +} +.system-daggerheart.theme-light .tagify__dropdown .tagify__dropdown__wrapper { + background-image: url(../assets/parchments/dh-parchment-light.png); +} +.theme-light .application.sheet.dh-style button.glow { + animation: glow-dark 0.75s infinite alternate; +} +.theme-light .application .component.dh-style.card-preview-container { + background-image: url('../assets/parchments/dh-parchment-light.png'); +} +.theme-light .application .component.dh-style.card-preview-container .preview-text-container { + background-image: url(../assets/parchments/dh-parchment-dark.png); +} +.theme-light .application .component.dh-style.card-preview-container .preview-selected-icon-container { + background-image: url(../assets/parchments/dh-parchment-dark.png); + color: var(--color-light-5); +} +.application .component.dh-style.card-preview-container { + position: relative; + border-radius: 6px; + border: 2px solid var(--color-tabs-border); + display: flex; + flex-direction: column; + aspect-ratio: 0.75; + background-image: url('../assets/parchments/dh-parchment-dark.png'); +} +.application .component.dh-style.card-preview-container.selectable { + cursor: pointer; +} +.application .component.dh-style.card-preview-container.disabled { + pointer-events: none; + opacity: 0.4; +} +.application .component.dh-style.card-preview-container .preview-image-outer-container { + position: relative; + display: flex; + align-items: center; + justify-content: center; +} +.application .component.dh-style.card-preview-container .preview-image-container { + flex: 1; + border-radius: 4px 4px 0 0; +} +.application .component.dh-style.card-preview-container .preview-text-container { + flex: 1; + border-radius: 0 0 4px 4px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 18px; + text-align: center; + color: var(--color-text-selection-bg); + background-image: url(../assets/parchments/dh-parchment-light.png); +} +.application .component.dh-style.card-preview-container .preview-empty-container { + pointer-events: none; + position: relative; + display: flex; + align-items: center; + justify-content: center; + flex: 1; +} +.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container { + width: 100%; + display: flex; + justify-content: center; +} +.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-add-icon { + font-size: 48px; +} +.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-empty-subtext { + position: absolute; + top: 10%; + font-size: 18px; + font-variant: small-caps; + text-align: center; +} +.application .component.dh-style.card-preview-container .preview-selected-icon-container { + position: absolute; + height: 54px; + width: 54px; + border-radius: 50%; + border: 2px solid; + font-size: 48px; + display: flex; + align-items: center; + justify-content: center; + background-image: url(../assets/parchments/dh-parchment-light.png); + color: var(--color-dark-5); +} +.application .component.dh-style.card-preview-container .preview-selected-icon-container i { + position: relative; + right: 2px; +} diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index b9509b38..29a2c1dd 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -15,6 +15,10 @@ color: light-dark(@dark-blue, @golden); border: 1px solid light-dark(@dark, @beige); + &::placeholder { + color: light-dark(@dark-40, @beige-50); + } + &:hover[type='text'], &:hover[type='number'], &:focus[type='text'], @@ -48,6 +52,24 @@ } } + input[type='range'] { + &::-webkit-slider-runnable-track { + background: light-dark(@dark-blue-40, @golden-40); + } + &::-moz-range-track { + background: light-dark(@dark-blue-40, @golden-40); + } + &::-webkit-slider-thumb { + background: light-dark(@dark-blue, @golden); + border: none; + border-radius: 50%; + + &:hover { + box-shadow: 0 0 8px light-dark(@dark-blue, @golden); + } + } + } + button { background: light-dark(transparent, @golden); border: 1px solid light-dark(@dark-blue, @dark-blue); @@ -296,6 +318,31 @@ } } + .scalable-input { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + + .form-group { + width: fit-content; + .nest-inputs { + width: fit-content; + } + } + + label { + font-family: @font-body; + font-size: 14px; + font-weight: 400; + + &.modifier-label { + width: 6ch; + text-align: end; + } + } + } + &:has(.list-w-img) { gap: 0; } @@ -413,6 +460,7 @@ label { font-size: 16px; + font-family: @font-body; } .form-fields { diff --git a/styles/less/sheets/actors/character/features.less b/styles/less/sheets/actors/character/features.less index 767544c1..c2feb6b1 100644 --- a/styles/less/sheets/actors/character/features.less +++ b/styles/less/sheets/actors/character/features.less @@ -11,7 +11,7 @@ mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); padding: 20px 0; padding-top: 10px; - height: 95%; + height: 84%; scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; diff --git a/styles/less/sheets/actors/character/inventory.less b/styles/less/sheets/actors/character/inventory.less index 43669d7f..eac1065d 100644 --- a/styles/less/sheets/actors/character/inventory.less +++ b/styles/less/sheets/actors/character/inventory.less @@ -56,7 +56,7 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); padding: 20px 0; - height: 80%; + height: 73%; scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; @@ -65,6 +65,11 @@ .currency-section { display: flex; gap: 10px; + padding: 10px 10px 0; + + input { + color: light-dark(@dark, @beige); + } } } } diff --git a/styles/less/sheets/actors/character/loadout.less b/styles/less/sheets/actors/character/loadout.less index cdf0e2e4..b7863e77 100644 --- a/styles/less/sheets/actors/character/loadout.less +++ b/styles/less/sheets/actors/character/loadout.less @@ -97,7 +97,7 @@ overflow-y: auto; mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 98%, transparent 100%); padding: 20px 0; - height: 90%; + height: 84%; scrollbar-width: thin; scrollbar-color: light-dark(@dark-blue, @golden) transparent; diff --git a/styles/less/sheets/actors/character/sheet.less b/styles/less/sheets/actors/character/sheet.less index 8afd7404..3d19a3b2 100644 --- a/styles/less/sheets/actors/character/sheet.less +++ b/styles/less/sheets/actors/character/sheet.less @@ -10,7 +10,7 @@ height: 100%; width: 100%; padding-bottom: 0; - overflow: auto; + overflow-x: auto; .character-sidebar-sheet { grid-row: 1 / span 2; diff --git a/styles/less/ui/settings/settings.less b/styles/less/ui/settings/settings.less index 3bd200a2..580c79ca 100644 --- a/styles/less/ui/settings/settings.less +++ b/styles/less/ui/settings/settings.less @@ -15,6 +15,10 @@ grid-template-columns: 1fr 1fr; } } + + &.start-align { + align-self: flex-start; + } } .setting-group-field { diff --git a/templates/dialogs/beastform/header.hbs b/templates/dialogs/beastform/header.hbs new file mode 100644 index 00000000..ac92d14c --- /dev/null +++ b/templates/dialogs/beastform/header.hbs @@ -0,0 +1,3 @@ +
+

{{localize 'DAGGERHEART.ITEMS.Beastform.dialogTitle'}}

+
\ No newline at end of file diff --git a/templates/dialogs/beastform/tabs.hbs b/templates/dialogs/beastform/tabs.hbs index 25bb2180..0a252dd6 100644 --- a/templates/dialogs/beastform/tabs.hbs +++ b/templates/dialogs/beastform/tabs.hbs @@ -1,11 +1,15 @@
\ No newline at end of file diff --git a/templates/dialogs/dice-roll/costSelection.hbs b/templates/dialogs/dice-roll/costSelection.hbs index 91d0229f..d376c749 100644 --- a/templates/dialogs/dice-roll/costSelection.hbs +++ b/templates/dialogs/dice-roll/costSelection.hbs @@ -1,21 +1,30 @@ -
- {{#if uses}} -
-
- - +
+ {{localize 'DAGGERHEART.GENERAL.Cost.single'}} +
    + {{#if uses}} +
  • +
    +
    + + +
    +
    + +
  • + {{/if}} + {{#each costs as | cost index |}} +
  • +
    +
    + + +
    -
- {{/if}} - {{#each costs as | cost index |}} -
-
- - - {{#if scalable}} - - {{/if}} -
-
- {{/each}} -
\ No newline at end of file + {{#if scalable}} + + {{/if}} + + + {{/each}} + + \ No newline at end of file diff --git a/templates/dialogs/dice-roll/rollSelection.hbs b/templates/dialogs/dice-roll/rollSelection.hbs index e3129e30..995be022 100644 --- a/templates/dialogs/dice-roll/rollSelection.hbs +++ b/templates/dialogs/dice-roll/rollSelection.hbs @@ -135,6 +135,9 @@ {{#if (eq @root.rollType 'DualityRoll')}}{{localize "DAGGERHEART.GENERAL.situationalBonus"}}{{/if}} + {{#if (or costs uses)}} + {{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}} + {{/if}} {{/unless}} {{localize "DAGGERHEART.GENERAL.formula"}}: {{@root.formula}} @@ -155,9 +158,14 @@
{{else}} - + {{#if (or costs uses)}} + {{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}} + {{/if}} +
+ +
{{/if}}
\ No newline at end of file diff --git a/templates/settings/appearance-settings.hbs b/templates/settings/appearance-settings.hbs index da435c75..f297a28f 100644 --- a/templates/settings/appearance-settings.hbs +++ b/templates/settings/appearance-settings.hbs @@ -1,4 +1,7 @@
+
+

{{localize 'DAGGERHEART.SETTINGS.Menu.appearance.name'}}

+
{{formGroup settingFields.schema.fields.displayFear value=settingFields._source.displayFear localize=true}} {{formGroup settingFields.schema.fields.showGenericStatusEffects value=settingFields._source.showGenericStatusEffects localize=true}} diff --git a/templates/settings/automation-settings.hbs b/templates/settings/automation-settings.hbs index 910ace56..9ffe5049 100644 --- a/templates/settings/automation-settings.hbs +++ b/templates/settings/automation-settings.hbs @@ -1,4 +1,7 @@
+
+

{{localize 'DAGGERHEART.SETTINGS.Menu.automation.name'}}

+
{{formGroup settingFields.schema.fields.hopeFear.fields.gm value=settingFields._source.hopeFear.gm localize=true}} diff --git a/templates/settings/homebrew-settings.hbs b/templates/settings/homebrew-settings.hbs index 07ae0c1f..ada2c7a9 100644 --- a/templates/settings/homebrew-settings.hbs +++ b/templates/settings/homebrew-settings.hbs @@ -1,4 +1,7 @@
+
+

{{localize 'DAGGERHEART.SETTINGS.Menu.homebrew.name'}}

+
{{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}}

{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}}

@@ -27,7 +30,7 @@
{{localize "DAGGERHEART.SETTINGS.Homebrew.downtimeMoves"}} -
+
{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}} @@ -48,7 +51,7 @@
-
+
{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}} diff --git a/templates/settings/range-measurement-settings.hbs b/templates/settings/range-measurement-settings.hbs index 36357d57..617d1899 100644 --- a/templates/settings/range-measurement-settings.hbs +++ b/templates/settings/range-measurement-settings.hbs @@ -1,4 +1,7 @@
+
+

{{localize 'DAGGERHEART.SETTINGS.Menu.range.name'}}

+
{{formGroup settingFields.schema.fields.enabled value=settingFields._source.enabled localize=true}} {{formGroup settingFields.schema.fields.melee value=settingFields._source.melee localize=true}} diff --git a/templates/settings/variant-rules.hbs b/templates/settings/variant-rules.hbs index 1ee18b99..75a5534b 100644 --- a/templates/settings/variant-rules.hbs +++ b/templates/settings/variant-rules.hbs @@ -1,4 +1,8 @@
+
+

{{localize 'DAGGERHEART.SETTINGS.Menu.variantRules.name'}}

+
+
diff --git a/templates/sheets/actors/character/inventory.hbs b/templates/sheets/actors/character/inventory.hbs index 9610d8e2..24f7836f 100644 --- a/templates/sheets/actors/character/inventory.hbs +++ b/templates/sheets/actors/character/inventory.hbs @@ -12,6 +12,30 @@
+
+
+ {{localize this.inventory.currency.coins}} + {{formInput systemFields.gold.fields.coins value=source.system.gold.coins enriched=source.system.gold.coins + localize=true toggled=true}} +
+
+ {{localize this.inventory.currency.handfulls}} + {{formInput systemFields.gold.fields.handfulls value=source.system.gold.handfulls + enriched=source.system.gold.handfulls localize=true toggled=true}} +
+
+ {{localize this.inventory.currency.bags}} + {{formInput systemFields.gold.fields.bags value=source.system.gold.bags enriched=source.system.gold.bags + localize=true toggled=true}} +
+
+ {{localize this.inventory.currency.chests}} + {{formInput systemFields.gold.fields.chests value=source.system.gold.chests + enriched=source.system.gold.chests localize=true toggled=true}} +
+ +
+
{{> 'daggerheart.inventory-items' title='TYPES.Item.weapon' @@ -44,28 +68,4 @@ canCreate=true }}
- -
-
- {{localize this.inventory.currency.coins}} - {{formInput systemFields.gold.fields.coins value=source.system.gold.coins enriched=source.system.gold.coins - localize=true toggled=true}} -
-
- {{localize this.inventory.currency.handfulls}} - {{formInput systemFields.gold.fields.handfulls value=source.system.gold.handfulls - enriched=source.system.gold.handfulls localize=true toggled=true}} -
-
- {{localize this.inventory.currency.bags}} - {{formInput systemFields.gold.fields.bags value=source.system.gold.bags enriched=source.system.gold.bags - localize=true toggled=true}} -
-
- {{localize this.inventory.currency.chests}} - {{formInput systemFields.gold.fields.chests value=source.system.gold.chests - enriched=source.system.gold.chests localize=true toggled=true}} -
- -
\ No newline at end of file diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index b9ac28a6..6ed47fc7 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -142,7 +142,7 @@ {{#each document.system.experiences as |experience id|}}
- +{{experience.total}} + +{{experience.value}}
From 6301e575e3dcb6df04415dff35c024f9d96f73c4 Mon Sep 17 00:00:00 2001 From: WBHarry <89362246+WBHarry@users.noreply.github.com> Date: Wed, 23 Jul 2025 01:01:21 +0200 Subject: [PATCH 3/3] [Feature] Allow Dice Reroll in ChatMessage (#395) * Troubleshooting Created test button in 'duality-roll.hbs' and functionality in chatLog.mjs * Updated functionality dialog recheck. * Update duality-roll.hbs testing toggle on specific areas so only tooltip is triggered. Rest of CSS functionality not affected. * Redoing Dice Reroll functionality Attempting something new * The rise of NaNs Resolved Dice Parsing Errors, now dealing with parsing errors from system values. * Forcing string evaluation for testing * Fixed rerolling of duality dice * Fixed message.rolls not being updated * Added support for d20 rolls * PR fixes --------- Co-authored-by: Nikhil Nagarajan --- daggerheart.mjs | 15 +- lang/en.json | 6 + module/applications/ui/chatLog.mjs | 131 ++-- module/data/chat-message/adversaryRoll.mjs | 2 +- module/data/fields/actorField.mjs | 5 +- module/dice/d20Roll.mjs | 23 +- module/dice/dualityRoll.mjs | 48 ++ module/enrichers/DualityRollEnricher.mjs | 2 +- styles/less/dialog/actions/action-list.less | 38 +- styles/less/global/elements.css | 723 ++++++++++---------- styles/less/ui/chat/chat.less | 29 + templates/ui/chat/adversary-roll.hbs | 15 +- templates/ui/chat/duality-roll.hbs | 46 +- 13 files changed, 593 insertions(+), 490 deletions(-) diff --git a/daggerheart.mjs b/daggerheart.mjs index da04334c..4568c670 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -2,14 +2,14 @@ import { SYSTEM } from './module/config/system.mjs'; import * as applications from './module/applications/_module.mjs'; import * as models from './module/data/_module.mjs'; import * as documents from './module/documents/_module.mjs'; +import * as dice from './module/dice/_module.mjs'; import RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs'; import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs'; import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs'; import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs'; import { DualityRollColor } from './module/data/settings/Appearance.mjs'; import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs'; -import { enrichedDualityRoll, renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; -import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs'; +import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs'; import { registerCountdownHooks } from './module/data/countdowns.mjs'; import { handlebarsRegistration, @@ -20,14 +20,14 @@ import { placeables } from './module/canvas/_module.mjs'; import { registerRollDiceHooks } from './module/dice/dhRoll.mjs'; import { registerDHActorHooks } from './module/documents/actor.mjs'; import './node_modules/@yaireo/tagify/dist/tagify.css'; -import { renderDamageButton } from './module/enrichers/DamageEnricher.mjs'; Hooks.once('init', () => { CONFIG.DH = SYSTEM; game.system.api = { applications, models, - documents + documents, + dice }; CONFIG.TextEditor.enrichers.push(...enricherConfig); @@ -49,7 +49,12 @@ Hooks.once('init', () => { DamageRoll: DamageRoll }; - CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, ...[DHRoll, DualityRoll, D20Roll, DamageRoll]]; + CONFIG.Dice.terms = { + ...CONFIG.Dice.terms, + DualityDie + }; + + CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, DHRoll, DualityRoll, D20Roll, DamageRoll]; CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate; const { DocumentSheetConfig } = foundry.applications.apps; diff --git a/lang/en.json b/lang/en.json index fc51a610..8af39fa3 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1339,6 +1339,8 @@ "quantity": "Quantity", "range": "Range", "recovery": "Recovery", + "reroll": "Reroll", + "rerollThing": "Reroll {thing}", "resource": "Resource", "roll": "Roll", "rollAll": "Roll All", @@ -1615,6 +1617,10 @@ "title": "Heal - {healing}", "heal": "Heal" }, + "reroll": { + "confirmTitle": "Reroll Dice", + "confirmText": "Are you sure you want to reroll?" + }, "resourceRoll": { "playerMessage": "{user} rerolled their {name}" } diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 41f9ef20..bcdff961 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -46,17 +46,14 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo html.querySelectorAll('.target-indicator').forEach(element => element.addEventListener('click', this.onToggleTargets) ); - html.querySelectorAll('.advantage').forEach(element => - element.addEventListener('mouseenter', this.hoverAdvantage) - ); - html.querySelectorAll('.advantage').forEach(element => - element.addEventListener('click', event => this.selectAdvantage.call(this, event, data.message)) - ); html.querySelectorAll('.ability-use-button').forEach(element => - element.addEventListener('click', event => this.abilityUseButton.call(this, event, data.message)) + element.addEventListener('click', event => this.abilityUseButton(this, event, data.message)) ); html.querySelectorAll('.action-use-button').forEach(element => - element.addEventListener('click', event => this.actionUseButton.call(this, event, data.message)) + element.addEventListener('click', event => this.actionUseButton(this, event, data.message)) + ); + html.querySelectorAll('.reroll-button').forEach(element => + element.addEventListener('click', event => this.rerollEvent(this, event, data.message)) ); }; @@ -70,7 +67,6 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } async getActor(id) { - // return game.actors.get(id); return await fromUuid(id); } @@ -85,7 +81,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo return action; } - onRollDamage = async (event, message) => { + async onRollDamage(event, message) { event.stopPropagation(); const actor = await this.getActor(message.system.source.actor); if (game.user.character?.id !== actor.id && !game.user.isGM) return true; @@ -94,9 +90,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (!action || !action?.rollDamage) return; await action.rollDamage(event, message); } - }; + } - onRollHealing = async (event, message) => { + async onRollHealing(event, message) { event.stopPropagation(); const actor = await this.getActor(message.system.source.actor); if (!actor || !game.user.isGM) return true; @@ -105,9 +101,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (!action || !action?.rollHealing) return; await action.rollHealing(event, message); } - }; + } - onRollSave = async (event, message) => { + async onRollSave(event, message) { event.stopPropagation(); const actor = await this.getActor(message.system.source.actor), tokenId = event.target.closest('[data-token]')?.dataset.token, @@ -118,9 +114,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (!action || !action?.hasSave) return; action.rollSave(token, event, message); } - }; + } - onRollAllSave = async (event, message) => { + onRollAllSave(event, _message) { event.stopPropagation(); const targets = event.target.parentElement.querySelectorAll( '.target-section > [data-token] .target-save-container' @@ -128,9 +124,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo targets.forEach(el => { el.dispatchEvent(new PointerEvent('click', { shiftKey: true })); }); - }; + } - onApplyEffect = async (event, message) => { + async onApplyEffect(event, message) { event.stopPropagation(); const actor = await this.getActor(message.system.source.actor); if (!actor || !game.user.isGM) return true; @@ -142,9 +138,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); await action.applyEffects(event, message, targets); } - }; + } - onTargetSelection = async (event, message) => { + onTargetSelection(event, message) { event.stopPropagation(); const targetSelection = Boolean(event.target.dataset.targetHit), msg = ui.chat.collection.get(message._id); @@ -154,9 +150,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo msg.system.targetSelection = targetSelection; msg.system.prepareDerivedData(); ui.chat.updateMessage(msg); - }; + } - getTargetList = (event, message) => { + getTargetList(event, message) { const targetSelection = event.target .closest('.message-content') .querySelector('.button-target-selection.target-selected'), @@ -167,20 +163,20 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo ? message.system.targets.filter(t => t.hit === true).map(target => game.canvas.tokens.get(target.id)) : Array.from(game.user.targets) }; - }; + } - hoverTarget = event => { + hoverTarget(event) { event.stopPropagation(); const token = canvas.tokens.get(event.currentTarget.dataset.token); if (!token?.controlled) token._onHoverIn(event, { hoverOutOthers: true }); - }; + } - unhoverTarget = event => { + unhoverTarget(event) { const token = canvas.tokens.get(event.currentTarget.dataset.token); if (!token?.controlled) token._onHoverOut(event); - }; + } - clickTarget = event => { + clickTarget(event) { event.stopPropagation(); const token = canvas.tokens.get(event.currentTarget.dataset.token); if (!token) { @@ -188,9 +184,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo return; } game.canvas.pan(token); - }; + } - onDamage = async (event, message) => { + async onDamage(event, message) { event.stopPropagation(); const { isHit, targets } = this.getTargetList(event, message); @@ -228,9 +224,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo target.actor.takeDamage(damages); } - }; + } - onHealing = async (event, message) => { + async onHealing(event, message) { event.stopPropagation(); const targets = Array.from(game.user.targets); @@ -240,7 +236,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo for (var target of targets) { target.actor.takeHealing(message.system.roll); } - }; + } /** * Toggle visibility of target containers. @@ -253,51 +249,15 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo .forEach(el => el.classList.toggle('hidden')); } - /** - * Highlight advantage icons on hover. - * @param {MouseEvent} event - */ - hoverAdvantage(event) { - const parent = event.currentTarget.parentElement; - if (!parent) return; - - parent.querySelectorAll('.advantage').forEach(el => { - if (el !== event.currentTarget) { - el.classList.toggle('unused'); - } - }); - } - - /** - * Handle selecting an advantage and disable further selection. - * @param {MouseEvent} event - * @param {object} message - */ - async selectAdvantage(event, message) { - event.stopPropagation(); - - const updateMessage = game.messages.get(message._id); - await updateMessage?.update({ - system: { advantageSelected: event.currentTarget.id === 'hope' ? 1 : 2 } - }); - - const parent = event.currentTarget.parentElement; - if (!parent) return; - - parent.querySelectorAll('.advantage').forEach(el => { - el.replaceWith(el.cloneNode(true)); - }); - } - - abilityUseButton = async (event, message) => { + async abilityUseButton(event, message) { event.stopPropagation(); const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)]; const actor = game.actors.get(message.system.source.actor); await actor.useAction(action); - }; + } - actionUseButton = async (event, message) => { + async actionUseButton(event, message) { const { moveIndex, actionIndex } = event.currentTarget.dataset; const parent = await foundry.utils.fromUuid(message.system.actor); const actionType = message.system.moves[moveIndex].actions[actionIndex]; @@ -308,5 +268,30 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo ); action.use(event); - }; + } + + async rerollEvent(event, message) { + if (!event.shiftKey) { + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { + title: game.i18n.localize('DAGGERHEART.UI.Chat.reroll.confirmTitle') + }, + content: game.i18n.localize('DAGGERHEART.UI.Chat.reroll.confirmText') + }); + if (!confirmed) return; + } + + const target = event.target.closest('button[data-die-index]'); + let originalRoll_parsed = message.rolls.map(roll => JSON.parse(roll))[0]; + const rollClass = + game.system.api.dice[ + message.type === 'dualityRoll' ? 'DualityRoll' : target.dataset.type === 'damage' ? 'DHRoll' : 'D20Roll' + ]; + const { newRoll, parsedRoll } = await rollClass.reroll(originalRoll_parsed, target, message); + + await game.messages.get(message._id).update({ + 'system.roll': newRoll, + 'rolls': [parsedRoll] + }); + } } diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index 9210ef99..1e2d8da1 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -6,7 +6,7 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { static defineSchema() { return { title: new fields.StringField(), - roll: new fields.DataField(), + roll: new fields.ObjectField(), targets: new fields.ArrayField( new fields.SchemaField({ id: new fields.StringField({}), diff --git a/module/data/fields/actorField.mjs b/module/data/fields/actorField.mjs index 047b6f4f..0b1113fb 100644 --- a/module/data/fields/actorField.mjs +++ b/module/data/fields/actorField.mjs @@ -26,10 +26,7 @@ const stressDamageReductionRule = localizationPath => const bonusField = label => new fields.SchemaField({ bonus: new fields.NumberField({ integer: true, initial: 0, label: `${game.i18n.localize(label)} Value` }), - dice: new fields.ArrayField( - new fields.StringField(), - { label: `${game.i18n.localize(label)} Dice` } - ) + dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` }) }); export { attributeField, resourceField, stressDamageReductionRule, bonusField }; diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index 95cba5ca..5f95b80d 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -147,7 +147,10 @@ export default class D20Roll extends DHRoll { const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; target.hit = this.isCritical || roll.total >= difficulty; }); - } else if (config.roll.difficulty) data.success = roll.isCritical || roll.total >= config.roll.difficulty; + } else if (config.roll.difficulty) { + data.difficulty = config.roll.difficulty; + data.success = roll.isCritical || roll.total >= config.roll.difficulty; + } data.advantage = { type: config.roll.advantage, dice: roll.dAdvantage?.denomination, @@ -169,4 +172,22 @@ export default class D20Roll extends DHRoll { resetFormula() { return (this._formula = this.constructor.getFormula(this.terms)); } + + static async reroll(rollString, _target, message) { + let parsedRoll = game.system.api.dice.D20Roll.fromData(rollString); + parsedRoll = await parsedRoll.reroll(); + const newRoll = game.system.api.dice.D20Roll.postEvaluate(parsedRoll, { + targets: message.system.targets, + roll: { + advantage: message.system.roll.advantage?.type, + difficulty: message.system.roll.difficulty ? Number(message.system.roll.difficulty) : null + } + }); + + if (game.modules.get('dice-so-nice')?.active) { + await game.dice3d.showForRoll(parsedRoll, game.user, true); + } + + return { newRoll, parsedRoll }; + } } diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 142f21e8..151d63df 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -1,6 +1,7 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20Roll from './d20Roll.mjs'; import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; +import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; export default class DualityRoll extends D20Roll { _advantageFaces = 6; @@ -110,6 +111,13 @@ export default class DualityRoll extends D20Roll { return [...(hooks ?? []), 'Duality']; } + /** @inheritDoc */ + static fromData(data) { + data.terms[0].class = game.system.api.dice.DualityDie.name; + data.terms[2].class = game.system.api.dice.DualityDie.name; + return super.fromData(data); + } + createBaseDice() { if ( this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && @@ -186,4 +194,44 @@ export default class DualityRoll extends D20Roll { return data; } + + static async reroll(rollString, target, message) { + let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...rollString, evaluated: false }); + const term = parsedRoll.terms[target.dataset.dieIndex]; + await term.reroll(`/r1=${term.total}`); + if (game.modules.get('dice-so-nice')?.active) { + const diceSoNiceRoll = { + _evaluated: true, + dice: [ + new foundry.dice.terms.Die({ + ...term, + faces: term._faces, + results: term.results.filter(x => !x.rerolled) + }) + ], + options: { appearance: {} } + }; + + const diceSoNicePresets = getDiceSoNicePresets(); + const type = target.dataset.type; + if (diceSoNicePresets[type]) { + diceSoNiceRoll.dice[0].options = { appearance: diceSoNicePresets[type] }; + } + + await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); + } + + await parsedRoll.evaluate(); + + const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, { + targets: message.system.targets, + roll: { + advantage: message.system.roll.advantage?.type, + difficulty: message.system.roll.difficulty ? Number(message.system.roll.difficulty) : null + } + }); + newRoll.extra = newRoll.extra.slice(2); + + return { newRoll, parsedRoll }; + } } diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs index dde82a48..70f376e7 100644 --- a/module/enrichers/DualityRollEnricher.mjs +++ b/module/enrichers/DualityRollEnricher.mjs @@ -48,7 +48,7 @@ function getDualityMessage(roll) { > ${label} - ${roll.difficulty || advantageLabel ? `(${[roll.difficulty, game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`)].filter(x => x).join(' ')})` : ''} + ${roll.difficulty || advantageLabel ? `(${[roll.difficulty, advantageLabel ? game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`) : null].filter(x => x).join(' ')})` : ''} `; diff --git a/styles/less/dialog/actions/action-list.less b/styles/less/dialog/actions/action-list.less index 800f7d8e..1f405b5d 100644 --- a/styles/less/dialog/actions/action-list.less +++ b/styles/less/dialog/actions/action-list.less @@ -1,19 +1,19 @@ -@import '../../utils/fonts.less'; - -.application.daggerheart.dh-style { - .actions-list { - display: flex; - flex-direction: column; - gap: 10px; - - .action-item { - display: flex; - align-items: center; - gap: 5px; - - .label { - font-family: @font-body; - } - } - } -} +@import '../../utils/fonts.less'; + +.application.daggerheart.dh-style { + .actions-list { + display: flex; + flex-direction: column; + gap: 10px; + + .action-item { + display: flex; + align-items: center; + gap: 5px; + + .label { + font-family: @font-body; + } + } + } +} diff --git a/styles/less/global/elements.css b/styles/less/global/elements.css index 2644d93f..5c9d36d1 100644 --- a/styles/less/global/elements.css +++ b/styles/less/global/elements.css @@ -1,104 +1,105 @@ @keyframes glow { - 0% { - box-shadow: 0 0 1px 1px #f3c267; - } - 100% { - box-shadow: 0 0 2px 2px #f3c267; - } + 0% { + box-shadow: 0 0 1px 1px #f3c267; + } + 100% { + box-shadow: 0 0 2px 2px #f3c267; + } } @keyframes glow-dark { - 0% { - box-shadow: 0 0 1px 1px #18162e; - } - 100% { - box-shadow: 0 0 2px 2px #18162e; - } + 0% { + box-shadow: 0 0 1px 1px #18162e; + } + 100% { + box-shadow: 0 0 2px 2px #18162e; + } } @font-face { - font-family: 'Cinzel'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-tbnTYo.ttf) format('truetype'); + font-family: 'Cinzel'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-tbnTYo.ttf) format('truetype'); } @font-face { - font-family: 'Cinzel'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-jHgTYo.ttf) format('truetype'); + font-family: 'Cinzel'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzel/v25/8vIU7ww63mVu7gtR-kwKxNvkNOjw-jHgTYo.ttf) format('truetype'); } @font-face { - font-family: 'Cinzel Decorative'; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(https://fonts.gstatic.com/s/cinzeldecorative/v18/daaHSScvJGqLYhG8nNt8KPPswUAPniZoaelD.ttf) format('truetype'); + font-family: 'Cinzel Decorative'; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://fonts.gstatic.com/s/cinzeldecorative/v18/daaHSScvJGqLYhG8nNt8KPPswUAPniZoaelD.ttf) + format('truetype'); } @font-face { - font-family: 'Montserrat'; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype'); + font-family: 'Montserrat'; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Ew-.ttf) format('truetype'); } @font-face { - font-family: 'Montserrat'; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype'); + font-family: 'Montserrat'; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://fonts.gstatic.com/s/montserrat/v30/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu170w-.ttf) format('truetype'); } .application.sheet.daggerheart.dh-style h1 { - font-family: 'Cinzel Decorative', serif; - margin: 0; - border: none; - font-weight: normal; + font-family: 'Cinzel Decorative', serif; + margin: 0; + border: none; + font-weight: normal; } .application.sheet.daggerheart.dh-style h2, .application.sheet.daggerheart.dh-style h3 { - font-family: 'Cinzel', serif; - margin: 0; - border: none; - font-weight: normal; + font-family: 'Cinzel', serif; + margin: 0; + border: none; + font-weight: normal; } .application.sheet.daggerheart.dh-style h4 { - font-family: 'Montserrat', sans-serif; - font-size: 14px; - border: none; - font-weight: 700; - margin: 0; - text-shadow: none; - color: #f3c267; - font-weight: normal; + font-family: 'Montserrat', sans-serif; + font-size: 14px; + border: none; + font-weight: 700; + margin: 0; + text-shadow: none; + color: #f3c267; + font-weight: normal; } .application.sheet.daggerheart.dh-style h5 { - font-size: 14px; - color: #f3c267; - margin: 0; - font-weight: normal; + font-size: 14px; + color: #f3c267; + margin: 0; + font-weight: normal; } .application.sheet.daggerheart.dh-style p, .application.sheet.daggerheart.dh-style span { - font-family: 'Montserrat', sans-serif; + font-family: 'Montserrat', sans-serif; } .application.sheet.daggerheart.dh-style small { - font-family: 'Montserrat', sans-serif; - opacity: 0.8; + font-family: 'Montserrat', sans-serif; + opacity: 0.8; } .application.dh-style { - border: 1px solid light-dark(#18162e, #f3c267); + border: 1px solid light-dark(#18162e, #f3c267); } .application.dh-style input[type='text'], .application.dh-style input[type='number'] { - background: light-dark(transparent, transparent); - border-radius: 6px; - box-shadow: 0 4px 30px rgba(0, 0, 0, 0.05); - backdrop-filter: blur(9.5px); - -webkit-backdrop-filter: blur(9.5px); - outline: none; - color: light-dark(#18162e, #f3c267); - border: 1px solid light-dark(#222, #efe6d8); + background: light-dark(transparent, transparent); + border-radius: 6px; + box-shadow: 0 4px 30px rgba(0, 0, 0, 0.05); + backdrop-filter: blur(9.5px); + -webkit-backdrop-filter: blur(9.5px); + outline: none; + color: light-dark(#18162e, #f3c267); + border: 1px solid light-dark(#222, #efe6d8); } .application.dh-style input[type='text']:hover[type='text'], .application.dh-style input[type='number']:hover[type='text'], @@ -108,500 +109,510 @@ .application.dh-style input[type='number']:focus[type='text'], .application.dh-style input[type='text']:focus[type='number'], .application.dh-style input[type='number']:focus[type='number'] { - background: light-dark(rgba(0, 0, 0, 0.05), rgba(24, 22, 46, 0.33)); - box-shadow: none; - outline: 2px solid light-dark(#222, #efe6d8); + background: light-dark(rgba(0, 0, 0, 0.05), rgba(24, 22, 46, 0.33)); + box-shadow: none; + outline: 2px solid light-dark(#222, #efe6d8); } .application.dh-style input[type='text']:disabled[type='text'], .application.dh-style input[type='number']:disabled[type='text'], .application.dh-style input[type='text']:disabled[type='number'], .application.dh-style input[type='number']:disabled[type='number'] { - outline: 2px solid transparent; - cursor: not-allowed; + outline: 2px solid transparent; + cursor: not-allowed; } .application.dh-style input[type='text']:disabled[type='text']:hover, .application.dh-style input[type='number']:disabled[type='text']:hover, .application.dh-style input[type='text']:disabled[type='number']:hover, .application.dh-style input[type='number']:disabled[type='number']:hover { - background: transparent; + background: transparent; } .application.dh-style input[type='checkbox']:checked::after, .application.dh-style input[type='radio']:checked::after { - color: light-dark(#222, #f3c267); + color: light-dark(#222, #f3c267); } .application.dh-style input[type='checkbox']:checked::before, .application.dh-style input[type='radio']:checked::before { - color: light-dark(#22222240, #f3c26740); + color: light-dark(#22222240, #f3c26740); } .application.dh-style input[type='checkbox']::before, .application.dh-style input[type='radio']::before { - color: light-dark(#22222240, #f3c26740); + color: light-dark(#22222240, #f3c26740); } .application.dh-style button { - background: light-dark(transparent, #f3c267); - border: 1px solid light-dark(#18162e, #18162e); - color: light-dark(#18162e, #18162e); - outline: none; - box-shadow: none; + background: light-dark(transparent, #f3c267); + border: 1px solid light-dark(#18162e, #18162e); + color: light-dark(#18162e, #18162e); + outline: none; + box-shadow: none; } .application.dh-style button:hover { - background: light-dark(rgba(0, 0, 0, 0.3), #18162e); - color: light-dark(#18162e, #f3c267); + background: light-dark(rgba(0, 0, 0, 0.3), #18162e); + color: light-dark(#18162e, #f3c267); } .application.dh-style button.glow { - animation: glow 0.75s infinite alternate; + animation: glow 0.75s infinite alternate; } .application.dh-style button:disabled { - background: light-dark(transparent, #f3c267); - color: light-dark(#18162e, #18162e); - opacity: 0.6; - cursor: not-allowed; + background: light-dark(transparent, #f3c267); + color: light-dark(#18162e, #18162e); + opacity: 0.6; + cursor: not-allowed; } .application.dh-style button:disabled:hover { - background: light-dark(transparent, #f3c267); - color: light-dark(#18162e, #18162e); + background: light-dark(transparent, #f3c267); + color: light-dark(#18162e, #18162e); } .application.dh-style select { - background: light-dark(transparent, transparent); - color: light-dark(#222, #efe6d8); - font-family: 'Montserrat', sans-serif; - outline: 2px solid transparent; - border: 1px solid light-dark(#222, #efe6d8); + background: light-dark(transparent, transparent); + color: light-dark(#222, #efe6d8); + font-family: 'Montserrat', sans-serif; + outline: 2px solid transparent; + border: 1px solid light-dark(#222, #efe6d8); } .application.dh-style select:focus, .application.dh-style select:hover { - outline: 2px solid light-dark(#222, #efe6d8); - box-shadow: none; + outline: 2px solid light-dark(#222, #efe6d8); + box-shadow: none; } .application.dh-style select option, .application.dh-style select optgroup { - color: #efe6d8; - background-color: #18162e; - border-radius: 6px; + color: #efe6d8; + background-color: #18162e; + border-radius: 6px; } .application.dh-style select:disabled { - opacity: 0.6; - outline: 2px solid transparent; - cursor: not-allowed; + opacity: 0.6; + outline: 2px solid transparent; + cursor: not-allowed; } .application.dh-style multi-select { - position: relative; - height: 34px; + position: relative; + height: 34px; } .application.dh-style multi-select .tags { - justify-content: flex-start; - margin: 4px; - height: inherit; + justify-content: flex-start; + margin: 4px; + height: inherit; } .application.dh-style multi-select .tags .tag { - padding: 0.3rem 0.5rem; - color: light-dark(#18162e, #f3c267); - background-color: light-dark(#18162e10, #f3c26740); - font-family: 'Montserrat', sans-serif; - border-radius: 3px; - transition: 0.13s ease-out; - gap: 0.5rem; - z-index: 1; + padding: 0.3rem 0.5rem; + color: light-dark(#18162e, #f3c267); + background-color: light-dark(#18162e10, #f3c26740); + font-family: 'Montserrat', sans-serif; + border-radius: 3px; + transition: 0.13s ease-out; + gap: 0.5rem; + z-index: 1; } .application.dh-style multi-select .tags .tag .remove { - font-size: 10px; + font-size: 10px; } .application.dh-style multi-select select { - position: absolute; - height: inherit; - outline: initial; + position: absolute; + height: inherit; + outline: initial; } .application.dh-style p { - margin: 0; + margin: 0; } .application.dh-style ul { - margin: 0; - padding: 0; - list-style: none; + margin: 0; + padding: 0; + list-style: none; } .application.dh-style li { - margin: 0; + margin: 0; } .application.dh-style a:hover, .application.dh-style a.active { - font-weight: bold; - text-shadow: 0 0 8px light-dark(#18162e, #f3c267); + font-weight: bold; + text-shadow: 0 0 8px light-dark(#18162e, #f3c267); } .application.dh-style fieldset { - align-items: center; - margin-top: 5px; - border-radius: 6px; - border-color: light-dark(#18162e, #f3c267); + align-items: center; + margin-top: 5px; + border-radius: 6px; + border-color: light-dark(#18162e, #f3c267); } .application.dh-style fieldset.glassy { - background-color: light-dark(#18162e10, #f3c26710); - border-color: transparent; + background-color: light-dark(#18162e10, #f3c26710); + border-color: transparent; } .application.dh-style fieldset.glassy legend { - padding: 2px 12px; - border-radius: 3px; - background-color: light-dark(#18162e, #f3c267); - color: light-dark(#efe6d8, #18162e); + padding: 2px 12px; + border-radius: 3px; + background-color: light-dark(#18162e, #f3c267); + color: light-dark(#efe6d8, #18162e); } .application.dh-style fieldset.fit-height { - height: 95%; + height: 95%; } .application.dh-style fieldset.flex { - display: flex; - gap: 20px; + display: flex; + gap: 20px; } .application.dh-style fieldset.flex.wrap { - flex-wrap: wrap; - gap: 10px 20px; + flex-wrap: wrap; + gap: 10px 20px; } .application.dh-style fieldset.flex .inline-child { - flex: 1; + flex: 1; } .application.dh-style fieldset .list-w-img { - padding: 5px; + padding: 5px; } .application.dh-style fieldset .list-w-img label { - flex: 1; + flex: 1; } .application.dh-style fieldset .list-w-img img { - width: 2rem; - height: 2rem; + width: 2rem; + height: 2rem; } .application.dh-style fieldset.one-column { - display: flex; - flex-direction: column; - align-items: start; - gap: 10px; - min-height: 64px; - flex: 1; + display: flex; + flex-direction: column; + align-items: start; + gap: 10px; + min-height: 64px; + flex: 1; } .application.dh-style fieldset.one-column > .one-column { - width: 100%; + width: 100%; } .application.dh-style fieldset.two-columns { - display: grid; - grid-template-columns: 1fr 2fr; - gap: 10px; + display: grid; + grid-template-columns: 1fr 2fr; + gap: 10px; } .application.dh-style fieldset.two-columns.even { - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr; } .application.dh-style fieldset.two-columns .full-width { - grid-column: span 2; + grid-column: span 2; } .application.dh-style fieldset legend { - font-family: 'Montserrat', sans-serif; - font-weight: bold; - color: light-dark(#18162e, #f3c267); + font-family: 'Montserrat', sans-serif; + font-weight: bold; + color: light-dark(#18162e, #f3c267); } .application.dh-style fieldset input[type='text'], .application.dh-style fieldset input[type='number'] { - color: light-dark(#222, #efe6d8); - font-family: 'Montserrat', sans-serif; - transition: all 0.3s ease; - outline: 2px solid transparent; + color: light-dark(#222, #efe6d8); + font-family: 'Montserrat', sans-serif; + transition: all 0.3s ease; + outline: 2px solid transparent; } .application.dh-style fieldset input[type='text']:focus, .application.dh-style fieldset input[type='number']:focus, .application.dh-style fieldset input[type='text']:hover, .application.dh-style fieldset input[type='number']:hover { - outline: 2px solid light-dark(#222, #efe6d8); + outline: 2px solid light-dark(#222, #efe6d8); } .application.dh-style fieldset[disabled], .application.dh-style fieldset.child-disabled .form-group, .application.dh-style fieldset select[disabled], .application.dh-style fieldset input[disabled] { - opacity: 0.5; + opacity: 0.5; } .application.dh-style fieldset.child-disabled .form-group { - pointer-events: none; + pointer-events: none; } .application.dh-style fieldset .nest-inputs { - display: flex; - align-items: center; - width: 100%; - gap: 5px; + display: flex; + align-items: center; + width: 100%; + gap: 5px; } .application.dh-style fieldset .nest-inputs .btn { - padding-top: 15px; + padding-top: 15px; } .application.dh-style fieldset .nest-inputs .image { - height: 40px; - width: 40px; - object-fit: cover; - border-radius: 6px; - border: none; + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 6px; + border: none; } .application.dh-style fieldset .nest-inputs > .checkbox { - align-self: end; + align-self: end; } .application.dh-style fieldset .form-group { - width: 100%; + width: 100%; } .application.dh-style fieldset .form-group label { - font-family: 'Montserrat', sans-serif; - font-weight: bold; - font-size: smaller; + font-family: 'Montserrat', sans-serif; + font-weight: bold; + font-size: smaller; } .application.dh-style fieldset .form-group.checkbox { - width: fit-content; - display: flex; - align-items: center; + width: fit-content; + display: flex; + align-items: center; } .application.dh-style fieldset .form-group.checkbox .form-fields { - height: 32px; - align-content: center; + height: 32px; + align-content: center; } .application.dh-style fieldset:has(.list-w-img) { - gap: 0; + gap: 0; } .application.dh-style .two-columns { - display: grid; - grid-template-columns: 1fr 2fr; - gap: 10px; + display: grid; + grid-template-columns: 1fr 2fr; + gap: 10px; } .application.dh-style .two-columns.even { - grid-template-columns: 1fr 1fr; + grid-template-columns: 1fr 1fr; } .application.dh-style line-div { - display: block; - height: 1px; - width: 100%; - border-bottom: 1px solid light-dark(#18162e, #f3c267); - mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); + display: block; + height: 1px; + width: 100%; + border-bottom: 1px solid light-dark(#18162e, #f3c267); + mask-image: linear-gradient(270deg, transparent 0%, black 50%, transparent 100%); } .application.dh-style side-line-div { - display: block; - height: 1px; - width: 100%; - border-bottom: 1px solid light-dark(#18162e, #f3c267); - mask-image: linear-gradient(270deg, transparent 0%, black 100%); + display: block; + height: 1px; + width: 100%; + border-bottom: 1px solid light-dark(#18162e, #f3c267); + mask-image: linear-gradient(270deg, transparent 0%, black 100%); } .application.dh-style side-line-div.invert { - mask-image: linear-gradient(270deg, black 0%, transparent 100%); + mask-image: linear-gradient(270deg, black 0%, transparent 100%); } .application.dh-style .item-description { - opacity: 1; - transform: translateY(0); - grid-column: 1/-1; - transition: opacity 0.3s ease-out, transform 0.3s ease-out; + opacity: 1; + transform: translateY(0); + grid-column: 1/-1; + transition: + opacity 0.3s ease-out, + transform 0.3s ease-out; } .application.dh-style .item-description.invisible { - height: 0; - opacity: 0; - overflow: hidden; - transform: translateY(-20px); - transform-origin: top; + height: 0; + opacity: 0; + overflow: hidden; + transform: translateY(-20px); + transform-origin: top; } .application.dh-style .item-buttons { - grid-column: span 3; - display: flex; - gap: 8px; - flex-wrap: wrap; + grid-column: span 3; + display: flex; + gap: 8px; + flex-wrap: wrap; } .application.dh-style .item-buttons button { - white-space: nowrap; + white-space: nowrap; } .application.setting.dh-style fieldset h2, .application.setting.dh-style fieldset h3, .application.setting.dh-style fieldset h4 { - margin: 8px 0 4px; - text-align: center; + margin: 8px 0 4px; + text-align: center; } .application.setting.dh-style fieldset .title-hint { - font-size: 12px; - font-variant: small-caps; - text-align: center; + font-size: 12px; + font-variant: small-caps; + text-align: center; } .application.setting.dh-style fieldset .field-section .split-section { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; } .application.setting.dh-style fieldset .label-container { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 10px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 10px; } .application.setting.dh-style fieldset .label-container label { - align-self: center; - text-align: center; + align-self: center; + text-align: center; } .application.setting.dh-style footer { - margin-top: 8px; - display: flex; - gap: 8px; + margin-top: 8px; + display: flex; + gap: 8px; } .application.setting.dh-style footer button { - flex: 1; + flex: 1; } .application.setting.dh-style .form-group { - display: flex; - justify-content: space-between; - align-items: center; + display: flex; + justify-content: space-between; + align-items: center; } .application.setting.dh-style .form-group label { - font-size: 16px; - font-family: 'Montserrat', sans-serif; + font-size: 16px; + font-family: 'Montserrat', sans-serif; } .application.setting.dh-style .form-group .form-fields { - display: flex; - gap: 4px; - align-items: center; + display: flex; + gap: 4px; + align-items: center; } .system-daggerheart .tagify { - background: light-dark(transparent, transparent); - border: 1px solid light-dark(#222, #efe6d8); - height: 34px; - --tags-disabled-bg: none; - --tags-border-color: none; - --tags-hover-border-color: none; - --tags-focus-border-color: none; - --tag-border-radius: 3px; - --tag-bg: light-dark(#18162e, #f3c267); - --tag-remove-btn-color: light-dark(#18162e, #f3c267); - --tag-hover: light-dark(#18162e, #f3c267); - --tag-text-color: light-dark(#efe6d8, #222); - --tag-text-color--edit: light-dark(#efe6d8, #222); - --tag-pad: 0.3em 0.5em; - --tag-inset-shadow-size: 1.2em; - --tag-invalid-color: #d39494; - --tag-invalid-bg: rgba(211, 148, 148, 0.5); - --tag--min-width: 1ch; - --tag--max-width: 100%; - --tag-hide-transition: 0.3s; - --tag-remove-bg: light-dark(#18162e40, #f3c26740); - --tag-remove-btn-color: light-dark(#efe6d8, #222); - --tag-remove-btn-bg: none; - --tag-remove-btn-bg--hover: light-dark(#efe6d8, #222); - --input-color: inherit; - --placeholder-color: light-dark(#efe6d815, #22222215); - --placeholder-color-focus: light-dark(#efe6d815, #22222215); - --loader-size: 0.8em; - --readonly-striped: 1; - border-radius: 3px; - margin-right: 1px; + background: light-dark(transparent, transparent); + border: 1px solid light-dark(#222, #efe6d8); + height: 34px; + --tags-disabled-bg: none; + --tags-border-color: none; + --tags-hover-border-color: none; + --tags-focus-border-color: none; + --tag-border-radius: 3px; + --tag-bg: light-dark(#18162e, #f3c267); + --tag-remove-btn-color: light-dark(#18162e, #f3c267); + --tag-hover: light-dark(#18162e, #f3c267); + --tag-text-color: light-dark(#efe6d8, #222); + --tag-text-color--edit: light-dark(#efe6d8, #222); + --tag-pad: 0.3em 0.5em; + --tag-inset-shadow-size: 1.2em; + --tag-invalid-color: #d39494; + --tag-invalid-bg: rgba(211, 148, 148, 0.5); + --tag--min-width: 1ch; + --tag--max-width: 100%; + --tag-hide-transition: 0.3s; + --tag-remove-bg: light-dark(#18162e40, #f3c26740); + --tag-remove-btn-color: light-dark(#efe6d8, #222); + --tag-remove-btn-bg: none; + --tag-remove-btn-bg--hover: light-dark(#efe6d8, #222); + --input-color: inherit; + --placeholder-color: light-dark(#efe6d815, #22222215); + --placeholder-color-focus: light-dark(#efe6d815, #22222215); + --loader-size: 0.8em; + --readonly-striped: 1; + border-radius: 3px; + margin-right: 1px; } .system-daggerheart .tagify tag div { - display: flex; - justify-content: space-between; - align-items: center; - height: 22px; + display: flex; + justify-content: space-between; + align-items: center; + height: 22px; } .system-daggerheart .tagify tag div span { - font-weight: 400; + font-weight: 400; } .system-daggerheart .tagify tag div img { - margin-left: 8px; - height: 20px; - width: 20px; + margin-left: 8px; + height: 20px; + width: 20px; } .system-daggerheart .tagify__dropdown { - border: 1px solid light-dark(#222, #efe6d8) !important; - font-family: 'Montserrat', sans-serif; - color: light-dark(#222, #efe6d8); + border: 1px solid light-dark(#222, #efe6d8) !important; + font-family: 'Montserrat', sans-serif; + color: light-dark(#222, #efe6d8); } .system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper { - background-image: url(../assets/parchments/dh-parchment-dark.png); - background-color: transparent; - border: 0; - color: light-dark(#222, #efe6d8); + background-image: url(../assets/parchments/dh-parchment-dark.png); + background-color: transparent; + border: 0; + color: light-dark(#222, #efe6d8); } .system-daggerheart .tagify__dropdown .tagify__dropdown__wrapper .tagify__dropdown__item--active { - background-color: light-dark(#222, #efe6d8); - color: light-dark(#efe6d8, #222); + background-color: light-dark(#222, #efe6d8); + color: light-dark(#efe6d8, #222); } .system-daggerheart.theme-light .tagify__dropdown .tagify__dropdown__wrapper { - background-image: url(../assets/parchments/dh-parchment-light.png); + background-image: url(../assets/parchments/dh-parchment-light.png); } .theme-light .application.sheet.dh-style button.glow { - animation: glow-dark 0.75s infinite alternate; + animation: glow-dark 0.75s infinite alternate; } .theme-light .application .component.dh-style.card-preview-container { - background-image: url('../assets/parchments/dh-parchment-light.png'); + background-image: url('../assets/parchments/dh-parchment-light.png'); } .theme-light .application .component.dh-style.card-preview-container .preview-text-container { - background-image: url(../assets/parchments/dh-parchment-dark.png); + background-image: url(../assets/parchments/dh-parchment-dark.png); } .theme-light .application .component.dh-style.card-preview-container .preview-selected-icon-container { - background-image: url(../assets/parchments/dh-parchment-dark.png); - color: var(--color-light-5); + background-image: url(../assets/parchments/dh-parchment-dark.png); + color: var(--color-light-5); } .application .component.dh-style.card-preview-container { - position: relative; - border-radius: 6px; - border: 2px solid var(--color-tabs-border); - display: flex; - flex-direction: column; - aspect-ratio: 0.75; - background-image: url('../assets/parchments/dh-parchment-dark.png'); + position: relative; + border-radius: 6px; + border: 2px solid var(--color-tabs-border); + display: flex; + flex-direction: column; + aspect-ratio: 0.75; + background-image: url('../assets/parchments/dh-parchment-dark.png'); } .application .component.dh-style.card-preview-container.selectable { - cursor: pointer; + cursor: pointer; } .application .component.dh-style.card-preview-container.disabled { - pointer-events: none; - opacity: 0.4; + pointer-events: none; + opacity: 0.4; } .application .component.dh-style.card-preview-container .preview-image-outer-container { - position: relative; - display: flex; - align-items: center; - justify-content: center; + position: relative; + display: flex; + align-items: center; + justify-content: center; } .application .component.dh-style.card-preview-container .preview-image-container { - flex: 1; - border-radius: 4px 4px 0 0; + flex: 1; + border-radius: 4px 4px 0 0; } .application .component.dh-style.card-preview-container .preview-text-container { - flex: 1; - border-radius: 0 0 4px 4px; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: 18px; - text-align: center; - color: var(--color-text-selection-bg); - background-image: url(../assets/parchments/dh-parchment-light.png); + flex: 1; + border-radius: 0 0 4px 4px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 18px; + text-align: center; + color: var(--color-text-selection-bg); + background-image: url(../assets/parchments/dh-parchment-light.png); } .application .component.dh-style.card-preview-container .preview-empty-container { - pointer-events: none; - position: relative; - display: flex; - align-items: center; - justify-content: center; - flex: 1; + pointer-events: none; + position: relative; + display: flex; + align-items: center; + justify-content: center; + flex: 1; } .application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container { - width: 100%; - display: flex; - justify-content: center; + width: 100%; + display: flex; + justify-content: center; } -.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-add-icon { - font-size: 48px; +.application + .component.dh-style.card-preview-container + .preview-empty-container + .preview-empty-inner-container + .preview-add-icon { + font-size: 48px; } -.application .component.dh-style.card-preview-container .preview-empty-container .preview-empty-inner-container .preview-empty-subtext { - position: absolute; - top: 10%; - font-size: 18px; - font-variant: small-caps; - text-align: center; +.application + .component.dh-style.card-preview-container + .preview-empty-container + .preview-empty-inner-container + .preview-empty-subtext { + position: absolute; + top: 10%; + font-size: 18px; + font-variant: small-caps; + text-align: center; } .application .component.dh-style.card-preview-container .preview-selected-icon-container { - position: absolute; - height: 54px; - width: 54px; - border-radius: 50%; - border: 2px solid; - font-size: 48px; - display: flex; - align-items: center; - justify-content: center; - background-image: url(../assets/parchments/dh-parchment-light.png); - color: var(--color-dark-5); + position: absolute; + height: 54px; + width: 54px; + border-radius: 50%; + border: 2px solid; + font-size: 48px; + display: flex; + align-items: center; + justify-content: center; + background-image: url(../assets/parchments/dh-parchment-light.png); + color: var(--color-dark-5); } .application .component.dh-style.card-preview-container .preview-selected-icon-container i { - position: relative; - right: 2px; + position: relative; + right: 2px; } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index c2c72d48..c593a919 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -44,7 +44,35 @@ &.duality { display: flex; gap: 0.25rem; + + > .roll { + background-image: none; + + .reroll-button { + border: none; + background: initial; + width: 42px; + + &:hover { + background: var(--button-background-color); + border: 1px solid var(--button-border-color); + } + } + } } + + &.rerollable { + .reroll-button { + border: none; + background: initial; + + &:hover { + background: var(--button-background-color); + border: 1px solid var(--button-border-color); + } + } + } + // margin: 0; > .roll { display: flex; @@ -52,6 +80,7 @@ justify-content: center; gap: 4px; margin-bottom: 4px; + .dice-container { display: flex; flex-direction: column; diff --git a/templates/ui/chat/adversary-roll.hbs b/templates/ui/chat/adversary-roll.hbs index a37f93e3..acf9a759 100644 --- a/templates/ui/chat/adversary-roll.hbs +++ b/templates/ui/chat/adversary-roll.hbs @@ -12,16 +12,13 @@ {{total}}
-
    - {{#each results}} -
  1. {{result}}
  2. - {{/each}} +
      +
    - {{#if (eq index 0)}} -
    - {{#if (eq ../roll.advantage.type 1)}}{{localize "DAGGERHEART.GENERAL.Advantage.full"}}{{/if}}{{#if (eq ../roll.advantage.type -1)}}{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}{{/if}} -
    - {{/if}}
{{/each}}
diff --git a/templates/ui/chat/duality-roll.hbs b/templates/ui/chat/duality-roll.hbs index 8076e093..d83136fe 100644 --- a/templates/ui/chat/duality-roll.hbs +++ b/templates/ui/chat/duality-roll.hbs @@ -1,6 +1,6 @@ -
-
{{title}}
-
+
+
{{title}}
+
{{#each roll.modifiers}}
{{localize label}} {{#if (gte value 0)}}+{{/if}}{{value}} @@ -22,12 +22,12 @@
{{/if}}
-
-
{{roll.formula}}
+
+
{{roll.formula}}
-
+
1{{roll.hope.dice}} @@ -38,25 +38,29 @@
    -
  1. +
  2. {{localize "DAGGERHEART.GENERAL.hope"}}
    -
    -
    - -
    -
    {{roll.hope.value}}
    +
    +
  3. -
  4. +
  5. {{localize "DAGGERHEART.GENERAL.fear"}}
    -
    -
    - -
    -
    {{roll.fear.value}}
    +
    +
  6. @@ -64,7 +68,7 @@
{{#if roll.advantage.type}} -
+
1{{roll.advantage.dice}} @@ -112,7 +116,7 @@
{{/if}} {{#each roll.extra as | extra | }} -
+
1{{extra.dice}} @@ -200,4 +204,4 @@
-
+
\ No newline at end of file