Fix conflicts

This commit is contained in:
Dapoolp 2025-07-23 01:39:24 +02:00
commit 17dd9b1f61
44 changed files with 1140 additions and 337 deletions

View file

@ -2,14 +2,14 @@ import { SYSTEM } from './module/config/system.mjs';
import * as applications from './module/applications/_module.mjs'; import * as applications from './module/applications/_module.mjs';
import * as models from './module/data/_module.mjs'; import * as models from './module/data/_module.mjs';
import * as documents from './module/documents/_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 RegisterHandlebarsHelpers from './module/helpers/handlebarsHelper.mjs';
import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs'; import { enricherConfig, enricherRenderSetup } from './module/enrichers/_module.mjs';
import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs'; import { getCommandTarget, rollCommandToJSON } from './module/helpers/utils.mjs';
import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs'; import { NarrativeCountdowns } from './module/applications/ui/countdowns.mjs';
import { DualityRollColor } from './module/data/settings/Appearance.mjs'; import { DualityRollColor } from './module/data/settings/Appearance.mjs';
import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs'; import { DHRoll, DualityRoll, D20Roll, DamageRoll, DualityDie } from './module/dice/_module.mjs';
import { renderDualityButton } from './module/enrichers/DualityRollEnricher.mjs'; import { enrichedDualityRoll } from './module/enrichers/DualityRollEnricher.mjs';
import { renderMeasuredTemplate } from './module/enrichers/TemplateEnricher.mjs';
import { registerCountdownHooks } from './module/data/countdowns.mjs'; import { registerCountdownHooks } from './module/data/countdowns.mjs';
import { import {
handlebarsRegistration, handlebarsRegistration,
@ -20,14 +20,14 @@ import { placeables } from './module/canvas/_module.mjs';
import { registerRollDiceHooks } from './module/dice/dhRoll.mjs'; import { registerRollDiceHooks } from './module/dice/dhRoll.mjs';
import { registerDHActorHooks } from './module/documents/actor.mjs'; import { registerDHActorHooks } from './module/documents/actor.mjs';
import './node_modules/@yaireo/tagify/dist/tagify.css'; import './node_modules/@yaireo/tagify/dist/tagify.css';
import { renderDamageButton } from './module/enrichers/DamageEnricher.mjs';
Hooks.once('init', () => { Hooks.once('init', () => {
CONFIG.DH = SYSTEM; CONFIG.DH = SYSTEM;
game.system.api = { game.system.api = {
applications, applications,
models, models,
documents documents,
dice
}; };
CONFIG.TextEditor.enrichers.push(...enricherConfig); CONFIG.TextEditor.enrichers.push(...enricherConfig);
@ -49,7 +49,12 @@ Hooks.once('init', () => {
DamageRoll: DamageRoll 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; CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate;
const { DocumentSheetConfig } = foundry.applications.apps; const { DocumentSheetConfig } = foundry.applications.apps;
@ -188,49 +193,21 @@ Hooks.on('chatMessage', (_, message) => {
} }
const traitValue = rollCommand.trait?.toLowerCase(); 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 = getCommandTarget();
const target = traitValue ? getCommandTarget() : undefined; const title = traitValue
if (target || !traitValue) { ? game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', {
new Promise(async (resolve, reject) => { ability: game.i18n.localize(SYSTEM.ACTOR.abilities[traitValue].label)
const trait = target ? target.system.traits[traitValue] : undefined; })
if (traitValue && !trait) { : game.i18n.localize('DAGGERHEART.GENERAL.duality');
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();
});
}
enrichedDualityRoll({ traitValue, target, difficulty, title, label: 'test', actionType: null, advantage });
return false; return false;
} }
}); });

View file

@ -756,7 +756,7 @@
}, },
"SelectAction": { "SelectAction": {
"selectType": "Select Action Type", "selectType": "Select Action Type",
"selectAction": "Select Action" "selectAction": "Action Selection"
}, },
"Traits": { "Traits": {
"agility": { "agility": {
@ -1196,6 +1196,7 @@
}, },
"Roll": { "Roll": {
"attack": "Attack Roll", "attack": "Attack Roll",
"difficulty": "Roll (Difficulty {difficulty})",
"primaryWeaponAttack": "Primary Weapon Attack Roll", "primaryWeaponAttack": "Primary Weapon Attack Roll",
"secondaryWeaponAttack": "Secondary Weapon Attack Roll", "secondaryWeaponAttack": "Secondary Weapon Attack Roll",
"spellcast": "Spellcast Roll", "spellcast": "Spellcast Roll",
@ -1310,6 +1311,7 @@
"single": "Experience", "single": "Experience",
"plural": "Experiences" "plural": "Experiences"
}, },
"failure": "Failure",
"fear": "Fear", "fear": "Fear",
"features": "Features", "features": "Features",
"formula": "Formula", "formula": "Formula",
@ -1337,6 +1339,8 @@
"quantity": "Quantity", "quantity": "Quantity",
"range": "Range", "range": "Range",
"recovery": "Recovery", "recovery": "Recovery",
"reroll": "Reroll",
"rerollThing": "Reroll {thing}",
"resource": "Resource", "resource": "Resource",
"roll": "Roll", "roll": "Roll",
"rollAll": "Roll All", "rollAll": "Roll All",
@ -1345,6 +1349,7 @@
"scalable": "Scalable", "scalable": "Scalable",
"situationalBonus": "Situational Bonus", "situationalBonus": "Situational Bonus",
"stress": "Stress", "stress": "Stress",
"success": "Success",
"take": "Take", "take": "Take",
"Target": { "Target": {
"single": "Target", "single": "Target",
@ -1516,6 +1521,7 @@
} }
}, },
"Menu": { "Menu": {
"title": "Daggerheart Game Settings",
"automation": { "automation": {
"name": "Automation Settings", "name": "Automation Settings",
"label": "Configure Automation", "label": "Configure Automation",
@ -1611,6 +1617,10 @@
"title": "Heal - {healing}", "title": "Heal - {healing}",
"heal": "Heal" "heal": "Heal"
}, },
"reroll": {
"confirmTitle": "Reroll Dice",
"confirmText": "Are you sure you want to reroll?"
},
"resourceRoll": { "resourceRoll": {
"playerMessage": "{user} rerolled their {name}" "playerMessage": "{user} rerolled their {name}"
} }

View file

@ -1,5 +1,4 @@
export { default as BeastformDialog } from './beastformDialog.mjs'; export { default as BeastformDialog } from './beastformDialog.mjs';
export { default as costSelectionDialog } from './costSelectionDialog.mjs';
export { default as d20RollDialog } from './d20RollDialog.mjs'; export { default as d20RollDialog } from './d20RollDialog.mjs';
export { default as DamageDialog } from './damageDialog.mjs'; export { default as DamageDialog } from './damageDialog.mjs';
export { default as DamageReductionDialog } from './damageReductionDialog.mjs'; export { default as DamageReductionDialog } from './damageReductionDialog.mjs';

View file

@ -1,9 +1,11 @@
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api; const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api;
export default class BeastformDialog extends HandlebarsApplicationMixin(ApplicationV2) { export default class BeastformDialog extends HandlebarsApplicationMixin(ApplicationV2) {
constructor(configData) { constructor(configData, item) {
super(); super();
this.item = item;
this.configData = configData; this.configData = configData;
this.selected = null; this.selected = null;
this.evolved = { form: null }; this.evolved = { form: null };
@ -14,11 +16,14 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
classes: ['daggerheart', 'views', 'dh-style', 'beastform-selection'], classes: ['daggerheart', 'views', 'dialog', 'dh-style', 'beastform-selection'],
position: { position: {
width: 600, width: 600,
height: 'auto' height: 'auto'
}, },
window: {
icon: 'fa-solid fa-paw'
},
actions: { actions: {
selectBeastform: this.selectBeastform, selectBeastform: this.selectBeastform,
toggleHybridFeature: this.toggleHybridFeature, toggleHybridFeature: this.toggleHybridFeature,
@ -34,11 +39,12 @@ export default class BeastformDialog extends HandlebarsApplicationMixin(Applicat
}; };
get title() { get title() {
return game.i18n.localize('DAGGERHEART.ITEMS.Beastform.dialogTitle'); return this.item.name;
} }
/** @override */ /** @override */
static PARTS = { static PARTS = {
header: { template: 'systems/daggerheart/templates/dialogs/beastform/header.hbs' },
tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' }, tabs: { template: 'systems/daggerheart/templates/dialogs/beastform/tabs.hbs' },
beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.hbs' }, beastformTier: { template: 'systems/daggerheart/templates/dialogs/beastform/beastformTier.hbs' },
advanced: { template: 'systems/daggerheart/templates/dialogs/beastform/advanced.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; if (!options.submitted) this.selected = null;
} }
static async configure(configData) { static async configure(configData, item) {
return new Promise(resolve => { return new Promise(resolve => {
const app = new this(configData); const app = new this(configData, item);
const featureItem = item;
app.addEventListener( app.addEventListener(
'close', '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 } { once: true }
); );
app.render({ force: true }); app.render({ force: true });

View file

@ -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();
}
}

View file

@ -22,7 +22,7 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
id: 'roll-selection', id: 'roll-selection',
classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'roll-selection'], classes: ['daggerheart', 'dialog', 'dh-style', 'views', 'roll-selection'],
position: { position: {
width: 550 width: 'auto'
}, },
window: { window: {
icon: 'fa-solid fa-dice' icon: 'fa-solid fa-dice'
@ -52,10 +52,6 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio
rollSelection: { rollSelection: {
id: 'rollSelection', id: 'rollSelection',
template: 'systems/daggerheart/templates/dialogs/dice-roll/rollSelection.hbs' template: 'systems/daggerheart/templates/dialogs/dice-roll/rollSelection.hbs'
},
costSelection: {
id: 'costSelection',
template: 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'
} }
}; };

View file

@ -12,14 +12,17 @@ export default class DHAppearanceSettings extends HandlebarsApplicationMixin(App
} }
get title() { get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.appearance.name'); return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: 'daggerheart-appearance-settings', id: 'daggerheart-appearance-settings',
classes: ['daggerheart', 'setting', 'dh-style'], classes: ['daggerheart', 'dialog', 'dh-style', 'setting'],
position: { width: '600', height: 'auto' }, position: { width: '600', height: 'auto' },
window: {
icon: 'fa-solid fa-gears'
},
actions: { actions: {
reset: this.reset, reset: this.reset,
save: this.save save: this.save

View file

@ -12,14 +12,17 @@ export default class DhAutomationSettings extends HandlebarsApplicationMixin(App
} }
get title() { get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.automation.name'); return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: 'daggerheart-automation-settings', id: 'daggerheart-automation-settings',
classes: ['daggerheart', 'setting', 'dh-style'], classes: ['daggerheart', 'dh-style', 'dialog', 'setting'],
position: { width: '600', height: 'auto' }, position: { width: '600', height: 'auto' },
window: {
icon: 'fa-solid fa-gears'
},
actions: { actions: {
reset: this.reset, reset: this.reset,
save: this.save save: this.save

View file

@ -13,14 +13,17 @@ export default class DhHomebrewSettings extends HandlebarsApplicationMixin(Appli
} }
get title() { get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.homebrew.name'); return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: 'daggerheart-homebrew-settings', id: 'daggerheart-homebrew-settings',
classes: ['daggerheart', 'setting', 'dh-style'], classes: ['daggerheart', 'dh-style', 'dialog', 'setting'],
position: { width: '600', height: 'auto' }, position: { width: '600', height: 'auto' },
window: {
icon: 'fa-solid fa-gears'
},
actions: { actions: {
addItem: this.addItem, addItem: this.addItem,
editItem: this.editItem, editItem: this.editItem,

View file

@ -12,14 +12,17 @@ export default class DhRangeMeasurementSettings extends HandlebarsApplicationMix
} }
get title() { get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.automation.name'); return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: 'daggerheart-automation-settings', id: 'daggerheart-automation-settings',
classes: ['daggerheart', 'setting', 'dh-style'], classes: ['daggerheart', 'dialog', 'dh-style', 'setting'],
position: { width: '600', height: 'auto' }, position: { width: '600', height: 'auto' },
window: {
icon: 'fa-solid fa-gears'
},
actions: { actions: {
reset: this.reset, reset: this.reset,
save: this.save save: this.save

View file

@ -12,14 +12,17 @@ export default class DHVariantRuleSettings extends HandlebarsApplicationMixin(Ap
} }
get title() { get title() {
return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.variantRules.name'); return game.i18n.localize('DAGGERHEART.SETTINGS.Menu.title');
} }
static DEFAULT_OPTIONS = { static DEFAULT_OPTIONS = {
tag: 'form', tag: 'form',
id: 'daggerheart-appearance-settings', id: 'daggerheart-appearance-settings',
classes: ['daggerheart', 'setting', 'dh-style'], classes: ['daggerheart', 'dialog', 'dh-style', 'setting'],
position: { width: '600', height: 'auto' }, position: { width: '600', height: 'auto' },
window: {
icon: 'fa-solid fa-gears'
},
actions: { actions: {
reset: this.reset, reset: this.reset,
save: this.save save: this.save

View file

@ -46,17 +46,14 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
html.querySelectorAll('.target-indicator').forEach(element => html.querySelectorAll('.target-indicator').forEach(element =>
element.addEventListener('click', this.onToggleTargets) 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 => 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 => 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) { async getActor(id) {
// return game.actors.get(id);
return await fromUuid(id); return await fromUuid(id);
} }
@ -85,7 +81,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
return action; return action;
} }
onRollDamage = async (event, message) => { async onRollDamage(event, message) {
event.stopPropagation(); event.stopPropagation();
const actor = await this.getActor(message.system.source.actor); const actor = await this.getActor(message.system.source.actor);
if (game.user.character?.id !== actor.id && !game.user.isGM) return true; 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; if (!action || !action?.rollDamage) return;
await action.rollDamage(event, message); await action.rollDamage(event, message);
} }
}; }
onRollHealing = async (event, message) => { async onRollHealing(event, message) {
event.stopPropagation(); event.stopPropagation();
const actor = await this.getActor(message.system.source.actor); const actor = await this.getActor(message.system.source.actor);
if (!actor || !game.user.isGM) return true; 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; if (!action || !action?.rollHealing) return;
await action.rollHealing(event, message); await action.rollHealing(event, message);
} }
}; }
onRollSave = async (event, message) => { async onRollSave(event, message) {
event.stopPropagation(); event.stopPropagation();
const actor = await this.getActor(message.system.source.actor), const actor = await this.getActor(message.system.source.actor),
tokenId = event.target.closest('[data-token]')?.dataset.token, 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; if (!action || !action?.hasSave) return;
action.rollSave(token, event, message); action.rollSave(token, event, message);
} }
}; }
onRollAllSave = async (event, message) => { onRollAllSave(event, _message) {
event.stopPropagation(); event.stopPropagation();
const targets = event.target.parentElement.querySelectorAll( const targets = event.target.parentElement.querySelectorAll(
'.target-section > [data-token] .target-save-container' '.target-section > [data-token] .target-save-container'
@ -128,9 +124,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
targets.forEach(el => { targets.forEach(el => {
el.dispatchEvent(new PointerEvent('click', { shiftKey: true })); el.dispatchEvent(new PointerEvent('click', { shiftKey: true }));
}); });
}; }
onApplyEffect = async (event, message) => { async onApplyEffect(event, message) {
event.stopPropagation(); event.stopPropagation();
const actor = await this.getActor(message.system.source.actor); const actor = await this.getActor(message.system.source.actor);
if (!actor || !game.user.isGM) return true; 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')); ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected'));
await action.applyEffects(event, message, targets); await action.applyEffects(event, message, targets);
} }
}; }
onTargetSelection = async (event, message) => { onTargetSelection(event, message) {
event.stopPropagation(); event.stopPropagation();
const targetSelection = Boolean(event.target.dataset.targetHit), const targetSelection = Boolean(event.target.dataset.targetHit),
msg = ui.chat.collection.get(message._id); 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.targetSelection = targetSelection;
msg.system.prepareDerivedData(); msg.system.prepareDerivedData();
ui.chat.updateMessage(msg); ui.chat.updateMessage(msg);
}; }
getTargetList = (event, message) => { getTargetList(event, message) {
const targetSelection = event.target const targetSelection = event.target
.closest('.message-content') .closest('.message-content')
.querySelector('.button-target-selection.target-selected'), .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)) ? message.system.targets.filter(t => t.hit === true).map(target => game.canvas.tokens.get(target.id))
: Array.from(game.user.targets) : Array.from(game.user.targets)
}; };
}; }
hoverTarget = event => { hoverTarget(event) {
event.stopPropagation(); event.stopPropagation();
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token?.controlled) token._onHoverIn(event, { hoverOutOthers: true }); if (!token?.controlled) token._onHoverIn(event, { hoverOutOthers: true });
}; }
unhoverTarget = event => { unhoverTarget(event) {
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token?.controlled) token._onHoverOut(event); if (!token?.controlled) token._onHoverOut(event);
}; }
clickTarget = event => { clickTarget(event) {
event.stopPropagation(); event.stopPropagation();
const token = canvas.tokens.get(event.currentTarget.dataset.token); const token = canvas.tokens.get(event.currentTarget.dataset.token);
if (!token) { if (!token) {
@ -188,9 +184,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
return; return;
} }
game.canvas.pan(token); game.canvas.pan(token);
}; }
onDamage = async (event, message) => { async onDamage(event, message) {
event.stopPropagation(); event.stopPropagation();
const { isHit, targets } = this.getTargetList(event, message); 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); target.actor.takeDamage(damages);
} }
}; }
onHealing = async (event, message) => { async onHealing(event, message) {
event.stopPropagation(); event.stopPropagation();
const targets = Array.from(game.user.targets); 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) { for (var target of targets) {
target.actor.takeHealing(message.system.roll); target.actor.takeHealing(message.system.roll);
} }
}; }
/** /**
* Toggle visibility of target containers. * Toggle visibility of target containers.
@ -253,43 +249,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
.forEach(el => el.classList.toggle('hidden')); .forEach(el => el.classList.toggle('hidden'));
} }
/** async abilityUseButton(event, message) {
* 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) => {
event.stopPropagation(); event.stopPropagation();
const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)]; const action = message.system.actions[Number.parseInt(event.currentTarget.dataset.index)];
@ -297,7 +257,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo
await actor.use(action); await actor.use(action);
}; };
actionUseButton = async (event, message) => { async actionUseButton(event, message) {
const { moveIndex, actionIndex } = event.currentTarget.dataset; const { moveIndex, actionIndex } = event.currentTarget.dataset;
const parent = await foundry.utils.fromUuid(message.system.actor); const parent = await foundry.utils.fromUuid(message.system.actor);
const actionType = message.system.moves[moveIndex].actions[actionIndex]; 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); 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]
});
}
} }

View file

@ -10,7 +10,9 @@ export default class DhBeastformAction extends DHBaseAction {
const abort = await this.handleActiveTransformations(); const abort = await this.handleActiveTransformations();
if (abort) return; 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; if (!selected) return;
await this.transform(selected, evolved, hybrid); await this.transform(selected, evolved, hybrid);

View file

@ -6,7 +6,7 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel {
static defineSchema() { static defineSchema() {
return { return {
title: new fields.StringField(), title: new fields.StringField(),
roll: new fields.DataField(), roll: new fields.ObjectField(),
targets: new fields.ArrayField( targets: new fields.ArrayField(
new fields.SchemaField({ new fields.SchemaField({
id: new fields.StringField({}), id: new fields.StringField({}),

View file

@ -26,10 +26,7 @@ const stressDamageReductionRule = localizationPath =>
const bonusField = label => const bonusField = label =>
new fields.SchemaField({ new fields.SchemaField({
bonus: new fields.NumberField({ integer: true, initial: 0, label: `${game.i18n.localize(label)} Value` }), bonus: new fields.NumberField({ integer: true, initial: 0, label: `${game.i18n.localize(label)} Value` }),
dice: new fields.ArrayField( dice: new fields.ArrayField(new fields.StringField(), { label: `${game.i18n.localize(label)} Dice` })
new fields.StringField(),
{ label: `${game.i18n.localize(label)} Dice` }
)
}); });
export { attributeField, resourceField, stressDamageReductionRule, bonusField }; export { attributeField, resourceField, stressDamageReductionRule, bonusField };

View file

@ -147,7 +147,10 @@ export default class D20Roll extends DHRoll {
const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion;
target.hit = this.isCritical || roll.total >= difficulty; 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 = { data.advantage = {
type: config.roll.advantage, type: config.roll.advantage,
dice: roll.dAdvantage?.denomination, dice: roll.dAdvantage?.denomination,
@ -169,4 +172,22 @@ export default class D20Roll extends DHRoll {
resetFormula() { resetFormula() {
return (this._formula = this.constructor.getFormula(this.terms)); 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 };
}
} }

View file

@ -1,6 +1,7 @@
import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs';
import D20Roll from './d20Roll.mjs'; import D20Roll from './d20Roll.mjs';
import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; import { setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs';
import { getDiceSoNicePresets } from '../config/generalConfig.mjs';
export default class DualityRoll extends D20Roll { export default class DualityRoll extends D20Roll {
_advantageFaces = 6; _advantageFaces = 6;
@ -110,6 +111,13 @@ export default class DualityRoll extends D20Roll {
return [...(hooks ?? []), 'Duality']; 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() { createBaseDice() {
if ( if (
this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie && this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie &&
@ -186,4 +194,44 @@ export default class DualityRoll extends D20Roll {
return data; 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 };
}
} }

View file

@ -1,10 +1,10 @@
export default class DhpChatMessage extends foundry.documents.ChatMessage { export default class DhpChatMessage extends foundry.documents.ChatMessage {
async renderHTML() { async renderHTML() {
if (this.system.messageTemplate) if (this.system.messageTemplate)
this.content = await foundry.applications.handlebars.renderTemplate( this.content = await foundry.applications.handlebars.renderTemplate(this.system.messageTemplate, {
this.system.messageTemplate, ...this.system,
this.system _source: this.system._source
); });
/* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */ /* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */
const html = await super.renderHTML(); const html = await super.renderHTML();

View file

@ -21,19 +21,34 @@ function getDualityMessage(roll) {
? game.i18n.localize(abilities[roll.trait].label) ? game.i18n.localize(abilities[roll.trait].label)
: game.i18n.localize('DAGGERHEART.GENERAL.duality'); : 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'); const dualityElement = document.createElement('span');
dualityElement.innerHTML = ` dualityElement.innerHTML = `
<button class="duality-roll-button" <button class="duality-roll-button"
data-title="${label}" data-title="${label}"
data-label="${dataLabel}" data-label="${dataLabel}"
data-hope="${roll.hope ?? 'd12'}" data-hope="${roll.hope ?? 'd12'}"
data-fear="${roll.fear ?? 'd12'}" data-fear="${roll.fear ?? 'd12'}"
${advantage ? `data-advantage="${advantage}"` : ''}
${roll.difficulty !== undefined ? `data-difficulty="${roll.difficulty}"` : ''}
${roll.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''} ${roll.trait && abilities[roll.trait] ? `data-trait="${roll.trait}"` : ''}
${roll.advantage ? 'data-advantage="true"' : ''} ${roll.advantage ? 'data-advantage="true"' : ''}
${roll.disadvantage ? 'data-disadvantage="true"' : ''} ${roll.disadvantage ? 'data-disadvantage="true"' : ''}
> >
<i class="fa-solid fa-circle-half-stroke"></i> <i class="fa-solid fa-circle-half-stroke"></i>
${label} ${label}
${roll.difficulty || advantageLabel ? `(${[roll.difficulty, advantageLabel ? game.i18n.localize(`DAGGERHEART.GENERAL.${advantageLabel}.short`) : null].filter(x => x).join(' ')})` : ''}
</button> </button>
`; `;
@ -43,16 +58,39 @@ function getDualityMessage(roll) {
export const renderDualityButton = async event => { export const renderDualityButton = async event => {
const button = event.currentTarget, const button = event.currentTarget,
traitValue = button.dataset.trait?.toLowerCase(), 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; if (!target) return;
const config = { const config = {
event: event, event: event ?? {},
title: button.dataset.title, title: title,
roll: { roll: {
modifier: traitValue ? target.system.traits[traitValue].value : null, modifier: traitValue ? target.system.traits[traitValue].value : null,
label: button.dataset.label, label: label,
type: button.dataset.actionType ?? null // Need check difficulty: difficulty,
advantage,
type: actionType ?? null // Need check,
}, },
chatMessage: { chatMessage: {
template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs' template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'

View file

@ -30,6 +30,7 @@ export const preloadHandlebarsTemplates = async function () {
'systems/daggerheart/templates/ui/chat/parts/target-chat.hbs', 'systems/daggerheart/templates/ui/chat/parts/target-chat.hbs',
'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs', 'systems/daggerheart/templates/ui/tooltip/parts/tooltipChips.hbs',
'systems/daggerheart/templates/ui/tooltip/parts/tooltipTags.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'
]); ]);
}; };

View file

@ -1,19 +1,19 @@
@import '../../utils/fonts.less'; @import '../../utils/fonts.less';
.application.daggerheart.dh-style { .application.daggerheart.dh-style {
.actions-list { .actions-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 10px; gap: 10px;
.action-item { .action-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 5px; gap: 5px;
.label { .label {
font-family: @font-body; font-family: @font-body;
} }
} }
} }
} }

View file

@ -1,5 +1,6 @@
@import '../../utils/colors.less'; @import '../../utils/colors.less';
@import '../../utils/mixin.less'; @import '../../utils/mixin.less';
@import '../../utils/fonts.less';
.theme-light .application.daggerheart.dh-style.views.beastform-selection .beastforms-outer-container { .theme-light .application.daggerheart.dh-style.views.beastform-selection .beastforms-outer-container {
.beastform-title { .beastform-title {
@ -209,6 +210,9 @@
button { button {
flex: 1; flex: 1;
font-family: @font-body;
font-weight: bold;
height: 40px;
} }
} }
} }

View file

@ -13,6 +13,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 12px; gap: 12px;
max-width: 550px;
.dices-section { .dices-section {
display: flex; display: flex;
@ -131,13 +132,18 @@
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16px; gap: 16px;
height: 32px;
.roll-mode-select { .roll-mode-select {
width: min-content; width: min-content;
height: 100%;
} }
button { button {
flex: 1; flex: 1;
height: 100%;
font-weight: bold;
font-family: @font-body;
} }
} }
} }

View file

@ -0,0 +1,618 @@
@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;
}

View file

@ -15,6 +15,10 @@
color: light-dark(@dark-blue, @golden); color: light-dark(@dark-blue, @golden);
border: 1px solid light-dark(@dark, @beige); border: 1px solid light-dark(@dark, @beige);
&::placeholder {
color: light-dark(@dark-40, @beige-50);
}
&:hover[type='text'], &:hover[type='text'],
&:hover[type='number'], &:hover[type='number'],
&:focus[type='text'], &: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 { button {
background: light-dark(transparent, @golden); background: light-dark(transparent, @golden);
border: 1px solid light-dark(@dark-blue, @dark-blue); 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) { &:has(.list-w-img) {
gap: 0; gap: 0;
} }
@ -413,6 +460,7 @@
label { label {
font-size: 16px; font-size: 16px;
font-family: @font-body;
} }
.form-fields { .form-fields {

View file

@ -11,7 +11,7 @@
mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
padding: 20px 0; padding: 20px 0;
padding-top: 10px; padding-top: 10px;
height: 95%; height: 84%;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent; scrollbar-color: light-dark(@dark-blue, @golden) transparent;

View file

@ -56,7 +56,7 @@
overflow-y: auto; overflow-y: auto;
mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%); mask-image: linear-gradient(0deg, transparent 0%, black 5%, black 95%, transparent 100%);
padding: 20px 0; padding: 20px 0;
height: 80%; height: 73%;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent; scrollbar-color: light-dark(@dark-blue, @golden) transparent;
@ -65,6 +65,11 @@
.currency-section { .currency-section {
display: flex; display: flex;
gap: 10px; gap: 10px;
padding: 10px 10px 0;
input {
color: light-dark(@dark, @beige);
}
} }
} }
} }

View file

@ -97,7 +97,7 @@
overflow-y: auto; overflow-y: auto;
mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 98%, transparent 100%); mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 98%, transparent 100%);
padding: 20px 0; padding: 20px 0;
height: 90%; height: 84%;
scrollbar-width: thin; scrollbar-width: thin;
scrollbar-color: light-dark(@dark-blue, @golden) transparent; scrollbar-color: light-dark(@dark-blue, @golden) transparent;

View file

@ -10,7 +10,7 @@
height: 100%; height: 100%;
width: 100%; width: 100%;
padding-bottom: 0; padding-bottom: 0;
overflow: auto; overflow-x: auto;
.character-sidebar-sheet { .character-sidebar-sheet {
grid-row: 1 / span 2; grid-row: 1 / span 2;

View file

@ -44,7 +44,35 @@
&.duality { &.duality {
display: flex; display: flex;
gap: 0.25rem; 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; // margin: 0;
> .roll { > .roll {
display: flex; display: flex;
@ -52,6 +80,7 @@
justify-content: center; justify-content: center;
gap: 4px; gap: 4px;
margin-bottom: 4px; margin-bottom: 4px;
.dice-container { .dice-container {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

View file

@ -15,6 +15,10 @@
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
} }
} }
&.start-align {
align-self: flex-start;
}
} }
.setting-group-field { .setting-group-field {

View file

@ -0,0 +1,3 @@
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.ITEMS.Beastform.dialogTitle'}}</h1>
</header>

View file

@ -1,11 +1,15 @@
<section class='tab-navigation'> <section class='tab-navigation'>
<div class='navigation-container beastform-nav'> <div class='navigation-container beastform-nav'>
<nav class='feature-tab sheet-tabs tabs' data-group='primary'> <div class="navigation-inner-container">
{{#each tabs as |tab|}} <line-div></line-div>
<a class='{{tab.id}} {{tab.cssClass}}' data-action='tab' data-group='{{tab.group}}' data-tab='{{tab.id}}'> <nav class='feature-tab sheet-tabs tabs' data-group='primary'>
{{localize tab.label}} {{#each tabs as |tab|}}
</a> <a class='{{tab.id}} {{tab.cssClass}}' data-action='tab' data-group='{{tab.group}}' data-tab='{{tab.id}}'>
{{/each}} {{localize tab.label}}
</nav> </a>
{{/each}}
</nav>
<line-div></line-div>
</div>
</div> </div>
</section> </section>

View file

@ -1,21 +1,30 @@
<div> <fieldset class="one-column">
{{#if uses}} <legend>{{localize 'DAGGERHEART.GENERAL.Cost.single'}}</legend>
<div class="form-group"> <ul>
<div class="form-fields"> {{#if uses}}
<label for="uses.enabled">Uses: {{uses.value}}/{{uses.max}}</label> <li class="scalable-input">
<input name="uses.enabled" type="checkbox"{{#if uses.enabled}} checked{{/if}}> <div class="form-group">
<div class="form-fields nest-inputs">
<input name="uses.enabled" type="checkbox"{{#if uses.enabled}} checked{{/if}}>
<label for="uses.enabled">Uses</label>
</div>
</div>
<label class="modifier-label">{{uses.value}}/{{uses.max}}</label>
</li>
{{/if}}
{{#each costs as | cost index |}}
<li class="scalable-input">
<div class="form-group">
<div class="form-fields nest-inputs">
<input name="costs.{{index}}.enabled" type="checkbox"{{#if enabled}} checked{{/if}}>
<label>{{label}}</label>
</div>
</div> </div>
</div> {{#if scalable}}
{{/if}} <input type="range" value="{{scale}}" min="1" max="10" step="{{step}}" name="costs.{{index}}.scale">
{{#each costs as | cost index |}} {{/if}}
<div class="form-group"> <label class="modifier-label">{{total}}/10</label>
<div class="form-fields"> </li>
<label>{{label}}: {{total}}</label> {{/each}}
<input name="costs.{{index}}.enabled" type="checkbox"{{#if enabled}} checked{{/if}}> </ul>
{{#if scalable}} </fieldset>
<input type="range" value="{{scale}}" min="1" max="10" step="{{step}}" name="costs.{{index}}.scale">
{{/if}}
</div>
</div>
{{/each}}
</div>

View file

@ -135,21 +135,37 @@
{{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}} {{#if (eq @root.rollType 'DualityRoll')}}<span class="formula-label">{{localize "DAGGERHEART.GENERAL.situationalBonus"}}</span>{{/if}}
<input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}"> <input type="text" value="{{extraFormula}}" name="extraFormula" placeholder="{{#if (eq @root.rollType 'DualityRoll')}}Ex: 1d6 + 5{{else}}Situational Bonus{{/if}}">
</fieldset> </fieldset>
{{#if (or costs uses)}}
{{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}}
{{/if}}
{{/unless}} {{/unless}}
<span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span> <span class="formula-label"><b>{{localize "DAGGERHEART.GENERAL.formula"}}:</b> {{@root.formula}}</span>
<div class="roll-dialog-controls"> <div class="roll-dialog-controls">
<select class="roll-mode-select" name="selectedRollMode"> <select class="roll-mode-select" name="selectedRollMode">
{{selectOptions rollModes selected=selectedRollMode valueAttr="action" labelAttr="label" localize=true}} {{selectOptions rollModes selected=selectedRollMode valueAttr="action" labelAttr="label" localize=true}}
</select> </select>
<button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}> <button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>
<i class="fa-solid fa-dice"></i> <i class="fa-solid fa-dice"></i>
<span class="label">{{localize "DAGGERHEART.GENERAL.roll"}}</span> <span class="label">
{{#if @root.rollConfig.roll.difficulty}}
{{localize "DAGGERHEART.GENERAL.Roll.difficulty" difficulty=@root.rollConfig.roll.difficulty}}
{{else}}
{{localize "DAGGERHEART.GENERAL.roll"}}
{{/if}}
</span>
</button> </button>
</div> </div>
{{else}} {{else}}
<button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}> {{#if (or costs uses)}}
<span class="label">{{localize "DAGGERHEART.GENERAL.continue"}}</span> {{> 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs'}}
</button> {{/if}}
<div class="roll-dialog-controls">
<button class="sunmit-btn" data-action="submitRoll"{{#unless canRoll}} disabled{{/unless}}>
<span class="label">{{localize "DAGGERHEART.GENERAL.continue"}}</span>
</button>
</div>
{{/if}} {{/if}}
</div> </div>
</div> </div>

View file

@ -1,4 +1,7 @@
<div> <div>
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.appearance.name'}}</h1>
</header>
{{formGroup settingFields.schema.fields.displayFear value=settingFields._source.displayFear localize=true}} {{formGroup settingFields.schema.fields.displayFear value=settingFields._source.displayFear localize=true}}
{{formGroup settingFields.schema.fields.showGenericStatusEffects value=settingFields._source.showGenericStatusEffects localize=true}} {{formGroup settingFields.schema.fields.showGenericStatusEffects value=settingFields._source.showGenericStatusEffects localize=true}}

View file

@ -1,4 +1,7 @@
<div> <div>
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.automation.name'}}</h1>
</header>
<div class="form-group"> <div class="form-group">
<label>{{localize "DAGGERHEART.SETTINGS.Automation.FIELDS.hopeFear.label"}}</label> <label>{{localize "DAGGERHEART.SETTINGS.Automation.FIELDS.hopeFear.label"}}</label>
{{formGroup settingFields.schema.fields.hopeFear.fields.gm value=settingFields._source.hopeFear.gm localize=true}} {{formGroup settingFields.schema.fields.hopeFear.fields.gm value=settingFields._source.hopeFear.gm localize=true}}

View file

@ -1,4 +1,7 @@
<div class="scrollable"> <div class="scrollable">
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.homebrew.name'}}</h1>
</header>
{{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}} {{formGroup settingFields.schema.fields.maxFear value=settingFields._source.maxFear localize=true}}
<h4>{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}}</h4> <h4>{{localize "DAGGERHEART.SETTINGS.Homebrew.FIELDS.traitArray.label"}}</h4>
@ -27,7 +30,7 @@
<fieldset class="two-columns even"> <fieldset class="two-columns even">
<legend>{{localize "DAGGERHEART.SETTINGS.Homebrew.downtimeMoves"}}</legend> <legend>{{localize "DAGGERHEART.SETTINGS.Homebrew.downtimeMoves"}}</legend>
<fieldset> <fieldset class="start-align">
<legend> <legend>
{{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}} {{localize "DAGGERHEART.APPLICATIONS.Downtime.longRest.title"}}
<a data-action="addItem" data-type="longRest"><i class="fa-solid fa-plus"></i></a> <a data-action="addItem" data-type="longRest"><i class="fa-solid fa-plus"></i></a>
@ -48,7 +51,7 @@
</div> </div>
</fieldset> </fieldset>
<fieldset> <fieldset class="start-align">
<legend> <legend>
{{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}} {{localize "DAGGERHEART.APPLICATIONS.Downtime.shortRest.title"}}
<a data-action="addItem" data-type="shortRest"><i class="fa-solid fa-plus"></i></a> <a data-action="addItem" data-type="shortRest"><i class="fa-solid fa-plus"></i></a>

View file

@ -1,4 +1,7 @@
<div> <div>
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.range.name'}}</h1>
</header>
<div class="settings-col"> <div class="settings-col">
{{formGroup settingFields.schema.fields.enabled value=settingFields._source.enabled localize=true}} {{formGroup settingFields.schema.fields.enabled value=settingFields._source.enabled localize=true}}
{{formGroup settingFields.schema.fields.melee value=settingFields._source.melee localize=true}} {{formGroup settingFields.schema.fields.melee value=settingFields._source.melee localize=true}}

View file

@ -1,4 +1,8 @@
<div> <div>
<header class="dialog-header">
<h1>{{localize 'DAGGERHEART.SETTINGS.Menu.variantRules.name'}}</h1>
</header>
<div class="form-group"> <div class="form-group">
<label>{{localize "DAGGERHEART.SETTINGS.Menu.variantRules.actionTokens"}}</label> <label>{{localize "DAGGERHEART.SETTINGS.Menu.variantRules.actionTokens"}}</label>

View file

@ -12,6 +12,30 @@
</a> </a>
</div> </div>
<div class="currency-section">
<div class="input">
<span>{{localize this.inventory.currency.coins}}</span>
{{formInput systemFields.gold.fields.coins value=source.system.gold.coins enriched=source.system.gold.coins
localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.handfulls}}</span>
{{formInput systemFields.gold.fields.handfulls value=source.system.gold.handfulls
enriched=source.system.gold.handfulls localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.bags}}</span>
{{formInput systemFields.gold.fields.bags value=source.system.gold.bags enriched=source.system.gold.bags
localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.chests}}</span>
{{formInput systemFields.gold.fields.chests value=source.system.gold.chests
enriched=source.system.gold.chests localize=true toggled=true}}
</div>
</div>
<div class="items-section"> <div class="items-section">
{{> 'daggerheart.inventory-items' {{> 'daggerheart.inventory-items'
title='TYPES.Item.weapon' title='TYPES.Item.weapon'
@ -44,28 +68,4 @@
canCreate=true canCreate=true
}} }}
</div> </div>
<div class="currency-section">
<div class="input">
<span>{{localize this.inventory.currency.coins}}</span>
{{formInput systemFields.gold.fields.coins value=source.system.gold.coins enriched=source.system.gold.coins
localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.handfulls}}</span>
{{formInput systemFields.gold.fields.handfulls value=source.system.gold.handfulls
enriched=source.system.gold.handfulls localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.bags}}</span>
{{formInput systemFields.gold.fields.bags value=source.system.gold.bags enriched=source.system.gold.bags
localize=true toggled=true}}
</div>
<div class="input">
<span>{{localize this.inventory.currency.chests}}</span>
{{formInput systemFields.gold.fields.chests value=source.system.gold.chests
enriched=source.system.gold.chests localize=true toggled=true}}
</div>
</div>
</section> </section>

View file

@ -142,7 +142,7 @@
{{#each document.system.experiences as |experience id|}} {{#each document.system.experiences as |experience id|}}
<div class="experience-row"> <div class="experience-row">
<div class="experience-value"> <div class="experience-value">
+{{experience.total}} +{{experience.value}}
</div> </div>
<input name="system.experiences.{{id}}.name" data-experience={{id}} <input name="system.experiences.{{id}}.name" data-experience={{id}}
value="{{experience.name}}" type="text" /> value="{{experience.name}}" type="text" />

View file

@ -12,16 +12,13 @@
<span class="part-total">{{total}}</span> <span class="part-total">{{total}}</span>
</header> </header>
<div class="flexrow"> <div class="flexrow">
<ol class="dice-rolls"> <ol class="dice-rolls rerollable">
{{#each results}} <button type="checkbox" class="reroll-button" data-die-index="0" data-tooltip="{{localize "DAGGERHEART.GENERAL.reroll"}}">
<li class="roll die {{../dice}}{{#if discarded}} discarded{{/if}} min">{{result}}</li> {{#each results as |result index|}}
{{/each}} <li class="roll die {{../dice}}{{#if discarded}} discarded{{/if}} min">{{result.result}}</li>
{{/each}}
</button>
</ol> </ol>
{{#if (eq index 0)}}
<div class="attack-roll-advantage-container">
{{#if (eq ../roll.advantage.type 1)}}{{localize "DAGGERHEART.GENERAL.Advantage.full"}}{{/if}}{{#if (eq ../roll.advantage.type -1)}}{{localize "DAGGERHEART.GENERAL.Disadvantage.full"}}{{/if}}
</div>
{{/if}}
</div> </div>
{{/each}} {{/each}}
</div> </div>

View file

@ -1,6 +1,6 @@
<div class="dice-roll daggerheart chat roll" data-action="expandRoll"> <div class="dice-roll daggerheart chat roll" data-action="expandRoll">
<div class="dice-flavor">{{title}}</div> <div class="dice-flavor" data-action="expandRoll">{{title}}</div>
<div class="duality-modifiers"> <div class="duality-modifiers" data-action="expandRoll">
{{#each roll.modifiers}} {{#each roll.modifiers}}
<div class="duality-modifier"> <div class="duality-modifier">
{{localize label}} {{#if (gte value 0)}}+{{/if}}{{value}} {{localize label}} {{#if (gte value 0)}}+{{/if}}{{value}}
@ -22,12 +22,12 @@
</div> </div>
{{/if}} {{/if}}
</div> </div>
<div class="dice-result"> <div class="dice-result">
<div class="dice-formula">{{roll.formula}}</div> <div class="dice-formula" data-action="expandRoll">{{roll.formula}}</div>
<div class="dice-tooltip"> <div class="dice-tooltip">
<div class="wrapper"> <div class="wrapper">
<section class="tooltip-part"> <section class="tooltip-part">
<div class="dice"> <div class="dice" data-action="expandRoll">
<header class="part-header flexrow"> <header class="part-header flexrow">
<span class="part-formula"> <span class="part-formula">
<span>1{{roll.hope.dice}}</span> <span>1{{roll.hope.dice}}</span>
@ -38,25 +38,29 @@
</header> </header>
<div class="flexrow"> <div class="flexrow">
<ol class="dice-rolls duality"> <ol class="dice-rolls duality">
<li class="roll die {{roll.hope.dice}}" title="{{localize "DAGGERHEART.GENERAL.hope"}}"> <li class="roll die {{roll.hope.dice}}">
<div class="dice-container"> <div class="dice-container">
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div> <div class="dice-title">{{localize "DAGGERHEART.GENERAL.hope"}}</div>
<div class="dice-inner-container hope" title="{{localize "DAGGERHEART.GENERAL.hope"}}"> <div class="dice-inner-container hope" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.hope")}}">
<div class="dice-wrapper"> <button type="checkbox" class="reroll-button" data-die-index="0" data-type="hope">
<img class="dice" src="../icons/svg/{{roll.hope.dice}}-grey.svg"/> <div class="dice-wrapper">
</div> <img class="dice" src="../icons/svg/{{roll.hope.dice}}-grey.svg"/>
<div class="dice-value">{{roll.hope.value}}</div> </div>
<div class="dice-value">{{roll.hope.value}}</div>
</button>
</div> </div>
</div> </div>
</li> </li>
<li class="roll die {{roll.fear.dice}}" title="{{localize "DAGGERHEART.GENERAL.fear"}}"> <li class="roll die {{roll.fear.dice}}">
<div class="dice-container"> <div class="dice-container">
<div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div> <div class="dice-title">{{localize "DAGGERHEART.GENERAL.fear"}}</div>
<div class="dice-inner-container fear" title="{{localize "DAGGERHEART.GENERAL.fear"}}"> <div class="dice-inner-container fear" data-tooltip="{{localize "DAGGERHEART.GENERAL.rerollThing" thing=(localize "DAGGERHEART.GENERAL.fear")}}">
<div class="dice-wrapper"> <button type="checkbox" class="reroll-button" data-die-index="2" data-type="fear">
<img class="dice" src="../icons/svg/{{roll.fear.dice}}-grey.svg"/> <div class="dice-wrapper">
</div> <img class="dice" src="../icons/svg/{{roll.fear.dice}}-grey.svg"/>
<div class="dice-value">{{roll.fear.value}}</div> </div>
<div class="dice-value">{{roll.fear.value}}</div>
</button>
</div> </div>
</div> </div>
</li> </li>
@ -64,7 +68,7 @@
</div> </div>
</div> </div>
{{#if roll.advantage.type}} {{#if roll.advantage.type}}
<div class="dice"> <div class="dice" data-action="expandRoll">
<header class="part-header flexrow"> <header class="part-header flexrow">
<span class="part-formula"> <span class="part-formula">
<span>1{{roll.advantage.dice}}</span> <span>1{{roll.advantage.dice}}</span>
@ -112,7 +116,7 @@
</div> </div>
{{/if}} {{/if}}
{{#each roll.extra as | extra | }} {{#each roll.extra as | extra | }}
<div class="dice"> <div class="dice" data-action="expandRoll">
<header class="part-header flexrow"> <header class="part-header flexrow">
<span class="part-formula"> <span class="part-formula">
<span>1{{extra.dice}}</span> <span>1{{extra.dice}}</span>
@ -140,7 +144,17 @@
</div> </div>
</div> </div>
<div class="dice-total duality {{#if (eq roll.result.duality 1)}}hope{{else}}{{#if (eq roll.result.duality -1)}}fear{{else}}critical{{/if}}{{/if}}"> <div class="dice-total duality {{#if (eq roll.result.duality 1)}}hope{{else}}{{#if (eq roll.result.duality -1)}}fear{{else}}critical{{/if}}{{/if}}">
<div class="dice-total-label">{{roll.result.label}}</div> <div class="dice-total-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}}
</div>
<div class="dice-total-value"> <div class="dice-total-value">
{{roll.total}} {{roll.total}}
</div> </div>
@ -190,4 +204,4 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>