diff --git a/assets/parchments/dh-parchment-critical.png b/assets/parchments/dh-parchment-critical.png new file mode 100644 index 00000000..67ae027f Binary files /dev/null and b/assets/parchments/dh-parchment-critical.png differ diff --git a/assets/parchments/dh-parchment-fear.png b/assets/parchments/dh-parchment-fear.png new file mode 100644 index 00000000..d4c9716e Binary files /dev/null and b/assets/parchments/dh-parchment-fear.png differ diff --git a/assets/parchments/dh-parchment-hope.png b/assets/parchments/dh-parchment-hope.png new file mode 100644 index 00000000..aa80be07 Binary files /dev/null and b/assets/parchments/dh-parchment-hope.png differ diff --git a/daggerheart.mjs b/daggerheart.mjs index 16271d2e..025dde3a 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -56,6 +56,8 @@ Hooks.once('init', () => { }; CONFIG.Dice.rolls = [...CONFIG.Dice.rolls, DHRoll, DualityRoll, D20Roll, DamageRoll]; + Roll.CHAT_TEMPLATE = "systems/daggerheart/templates/ui/chat/foundryRoll.hbs"; + Roll.TOOLTIP_TEMPLATE = "systems/daggerheart/templates/ui/chat/foundryRollTooltip.hbs"; CONFIG.MeasuredTemplate.objectClass = placeables.DhMeasuredTemplate; const { DocumentSheetConfig } = foundry.applications.apps; @@ -129,6 +131,7 @@ Hooks.once('init', () => { CONFIG.ChatMessage.dataModels = models.chatMessages.config; CONFIG.ChatMessage.documentClass = documents.DhChatMessage; + CONFIG.ChatMessage.template = 'systems/daggerheart/templates/ui/chat/chat-message.hbs'; CONFIG.Canvas.rulerClass = placeables.DhRuler; CONFIG.Canvas.layers.templates.layerClass = placeables.DhTemplateLayer; @@ -173,8 +176,10 @@ Hooks.on('ready', () => { Hooks.once('dicesoniceready', () => {}); -Hooks.on('renderChatMessageHTML', (_, element) => { +Hooks.on('renderChatMessageHTML', (_, element, message) => { enricherRenderSetup(element); + const cssClass = message.message.flags?.daggerheart?.cssClass; + if (cssClass) cssClass.split(' ').forEach(cls => element.classList.add(cls)); }); Hooks.on('renderJournalEntryPageProseMirrorSheet', (_, element) => { diff --git a/lang/en.json b/lang/en.json index 48b01ea7..e15c9af5 100755 --- a/lang/en.json +++ b/lang/en.json @@ -1577,6 +1577,7 @@ }, "Bonuses": { "rest": { + "downtimeAction": "Downtime Action", "shortRest": { "shortRestMoves": { "label": "Short Rest: Bonus Short Rest Moves", @@ -1743,6 +1744,7 @@ }, "Roll": { "attack": "Attack Roll", + "basic": "Roll", "difficulty": "Roll (Difficulty {difficulty})", "primaryWeaponAttack": "Primary Weapon Attack Roll", "secondaryWeaponAttack": "Secondary Weapon Attack Roll", @@ -1850,7 +1852,10 @@ "burden": "Burden", "continue": "Continue", "criticalSuccess": "Critical Success", + "criticalShort": "Critical", + "d20Roll": "D20 Roll", "damage": "Damage", + "damageRoll": "Damage Roll", "damageType": "Damage Type", "description": "Description", "difficulty": "Difficulty", @@ -1869,6 +1874,11 @@ "features": "Features", "formula": "Formula", "healing": "Healing", + "healingRoll": "Healing Roll", + "hit": { + "single": "Hit", + "plural": "Hits" + }, "HitPoints": { "single": "Hit Point", "plural": "Hit Points", @@ -1885,10 +1895,15 @@ "levelUp": "Level Up", "loadout": "Loadout", "max": "Max", + "miss": { + "single": "Miss", + "plural": "Miss" + }, "maxWithThing": "Max {thing}", "multiclass": "Multiclass", "newCategory": "New Category", "none": "None", + "noTarget": "No current target", "partner": "Partner", "proficiency": "Proficiency", "quantity": "Quantity", @@ -2158,6 +2173,9 @@ }, "UI": { "Chat": { + "action": { + "title": "Action" + }, "applyEffect": { "title": "Apply Effects - {name}" }, @@ -2172,12 +2190,16 @@ "dealDamageToTargets": "Damage Hit Targets", "dealDamage": "Deal Damage", "rollDamage": "Roll Damage", - "hitTarget": "Hit Targets", - "selectedTarget": "Selected" + "hitTarget": "Hit", + "selectedTarget": "Selected", + "currentTarget": "Current" }, "deathMove": { "title": "Death Move" }, + "dicePool": { + "title": "Dice Pool" + }, "domainCard": { "title": "Domain Card" }, @@ -2283,6 +2305,7 @@ "dragApplyEffect": "Drag effect to apply it to an actor", "appliedEvenIfSuccessful": "Applied even if save succeeded", "diceIsRerolled": "The dice has been rerolled (x{times})", + "pendingSaves": "Pending Reaction Rolls", "openSheetSettings": "Open Settings" } } diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 9027bbea..4b8749a3 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -152,8 +152,8 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio this.config.roll.type = this.reactionOverride ? CONFIG.DH.ITEM.actionTypes.reaction.id : this.config.roll.type === CONFIG.DH.ITEM.actionTypes.reaction.id - ? null - : this.config.roll.type; + ? null + : this.config.roll.type; this.render(); } } diff --git a/module/applications/dialogs/deathMove.mjs b/module/applications/dialogs/deathMove.mjs index 093d9680..d0686d2b 100644 --- a/module/applications/dialogs/deathMove.mjs +++ b/module/applications/dialogs/deathMove.mjs @@ -47,20 +47,31 @@ export default class DhpDeathMove extends HandlebarsApplicationMixin(Application static async takeMove() { const cls = getDocumentClass('ChatMessage'); - const msg = new cls({ + const msg = { user: game.user.id, content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/deathMove.hbs', { player: this.actor.name, + actor: { name: this.actor.name, img: this.actor.img }, + author: game.users.get(game.user.id), title: game.i18n.localize(this.selectedMove.name), img: this.selectedMove.img, description: game.i18n.localize(this.selectedMove.description) } - ) - }); + ), + title: game.i18n.localize( + 'DAGGERHEART.UI.Chat.deathMove.title' + ), + speaker: cls.getSpeaker(), + flags: { + daggerheart: { + cssClass: 'dh-chat-message dh-style' + } + } + }; - cls.create(msg.toObject()); + cls.create(msg); this.close(); } diff --git a/module/applications/dialogs/downtime.mjs b/module/applications/dialogs/downtime.mjs index d0da7d72..d6bfc7ac 100644 --- a/module/applications/dialogs/downtime.mjs +++ b/module/applications/dialogs/downtime.mjs @@ -133,22 +133,34 @@ export default class DhpDowntime extends HandlebarsApplicationMixin(ApplicationV }); const cls = getDocumentClass('ChatMessage'); - const msg = new cls({ + const msg = { user: game.user.id, system: { moves: moves, actor: this.actor.uuid }, + speaker: cls.getSpeaker(), + title: game.i18n.localize( + `DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title` + ), content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/downtime.hbs', { - title: `${this.actor.name} - ${game.i18n.localize(`DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title`)}`, + title: game.i18n.localize( + `DAGGERHEART.APPLICATIONS.Downtime.${this.shortrest ? 'shortRest' : 'longRest'}.title` + ), + actor: { name: this.actor.name, img: this.actor.img }, moves: moves } - ) - }); + ), + flags: { + daggerheart: { + cssClass: 'dh-chat-message dh-style' + } + } + }; - cls.create(msg.toObject()); + cls.create(msg); // Reset selection and update number of taken moves for (const [catName, category] of Object.entries(this.moveData)) { diff --git a/module/applications/dialogs/resourceDiceDialog.mjs b/module/applications/dialogs/resourceDiceDialog.mjs index 8205dee5..32e1e5d8 100644 --- a/module/applications/dialogs/resourceDiceDialog.mjs +++ b/module/applications/dialogs/resourceDiceDialog.mjs @@ -74,7 +74,7 @@ export default class ResourceDiceDialog extends HandlebarsApplicationMixin(Appli this.resetUsed = true; const cls = getDocumentClass('ChatMessage'); - const msg = new cls({ + const msg = { user: game.user.id, content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/resource-roll.hbs', @@ -83,9 +83,9 @@ export default class ResourceDiceDialog extends HandlebarsApplicationMixin(Appli name: this.item.name } ) - }); + }; - cls.create(msg.toObject()); + cls.create(msg); this.close(); } diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index 6af1b42e..ea3c6f31 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -16,7 +16,7 @@ export default class DHActionConfig extends DaggerheartSheet(ApplicationV2) { static DEFAULT_OPTIONS = { tag: 'form', - classes: ['daggerheart', 'dh-style', 'dialog'], + classes: ['daggerheart', 'dh-style', 'dialog', 'max-800'], window: { icon: 'fa-solid fa-wrench', resizable: false diff --git a/module/applications/sheets/actors/adversary.mjs b/module/applications/sheets/actors/adversary.mjs index f6324881..e21f1773 100644 --- a/module/applications/sheets/actors/adversary.mjs +++ b/module/applications/sheets/actors/adversary.mjs @@ -108,17 +108,15 @@ export default class AdversarySheet extends DHBaseActorSheet { */ static #reactionRoll(event) { const config = { - event: event, + event, title: `Reaction Roll: ${this.actor.name}`, headerTitle: 'Adversary Reaction Roll', roll: { type: 'reaction' }, - chatMessage: { - type: 'adversaryRoll', - template: 'systems/daggerheart/templates/ui/chat/adversary-roll.hbs', - mute: true - } + type: 'trait', + hasRoll: true, + data: this.actor.getRollData() }; this.actor.diceRoll(config); diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index b8f78a15..6e38e25d 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -611,9 +611,16 @@ export default class CharacterSheet extends DHBaseActorSheet { }), roll: { trait: button.dataset.attribute - } + }, + hasRoll: true }; - this.document.diceRoll(config); + this.document.diceRoll({ + ...config, + headerTitle: `${game.i18n.localize('DAGGERHEART.GENERAL.dualityRoll')}: ${this.actor.name}`, + title: game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { + ability: abilityLabel + }) + }); } //TODO: redo toggleEquipItem method diff --git a/module/applications/sheets/api/base-actor.mjs b/module/applications/sheets/api/base-actor.mjs index 346a0ab6..56e48232 100644 --- a/module/applications/sheets/api/base-actor.mjs +++ b/module/applications/sheets/api/base-actor.mjs @@ -121,21 +121,37 @@ export default class DHBaseActorSheet extends DHApplicationMixin(ActorSheetV2) { */ static async #sendExpToChat(_, button) { const experience = this.document.system.experiences[button.dataset.id]; + const cls = getDocumentClass('ChatMessage'); const systemData = { - name: game.i18n.localize('DAGGERHEART.GENERAL.Experience.single'), - description: `${experience.name} ${experience.value.signedString()}` + actor: { name: this.actor.name, img: this.actor.img }, + author: game.users.get(game.user.id), + action: { + name: `${experience.name} ${experience.value.signedString()}`, + img: '/icons/sundries/misc/admission-ticket-blue.webp' + }, + itemOrigin: { + name: game.i18n.localize('DAGGERHEART.GENERAL.Experience.single') + }, + description: experience.description }; - foundry.documents.ChatMessage.implementation.create({ - type: 'abilityUse', + const msg = { user: game.user.id, - system: systemData, content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/ui/chat/ability-use.hbs', + 'systems/daggerheart/templates/ui/chat/action.hbs', systemData - ) - }); + ), + title: game.i18n.localize('DAGGERHEART.ACTIONS.Config.displayInChat'), + speaker: cls.getSpeaker(), + flags: { + daggerheart: { + cssClass: 'dh-chat-message dh-style' + } + } + }; + + cls.create(msg); } /* -------------------------------------------- */ diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 8454baf7..9e07c050 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -15,11 +15,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo this.setupHooks(); } + /** @inheritDoc */ + static DEFAULT_OPTIONS = { + classes: ['daggerheart'] + }; + addChatListeners = async (app, html, data) => { html.querySelectorAll('.duality-action-damage').forEach(element => element.addEventListener('click', event => this.onRollDamage(event, data.message)) ); - html.querySelectorAll('.target-save-container').forEach(element => + html.querySelectorAll('.target-save').forEach(element => element.addEventListener('click', event => this.onRollSave(event, data.message)) ); html.querySelectorAll('.roll-all-save-button').forEach(element => @@ -28,6 +33,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo html.querySelectorAll('.duality-action-effect').forEach(element => element.addEventListener('click', event => this.onApplyEffect(event, data.message)) ); + html.querySelectorAll('.simple-roll-button').forEach(element => + element.addEventListener('click', event => this.onRollSimple(event, data.message)) + ); html.querySelectorAll('.target-container').forEach(element => { element.addEventListener('mouseenter', this.hoverTarget); element.addEventListener('mouseleave', this.unhoverTarget); @@ -119,7 +127,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo event.stopPropagation(); if (!game.user.isGM) return; const targets = event.target.parentElement.querySelectorAll( - '.target-section > [data-token] .target-save-container' + '[data-token] .target-save' ); const actor = await this.getActor(message.system.source.actor), action = this.getAction(actor, message.system.source.item, message.system.source.action); @@ -160,8 +168,8 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo const targetSelection = Boolean(event.target.dataset.targetHit), msg = ui.chat.collection.get(message._id); if (msg.system.targetSelection === targetSelection) return; - if (targetSelection !== true && !Array.from(game.user.targets).length) - return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); + // if (targetSelection !== true && !Array.from(game.user.targets).length) + // return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); msg.system.targetSelection = targetSelection; msg.system.prepareDerivedData(); ui.chat.updateMessage(msg); @@ -224,8 +232,9 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); for (let target of targets) { - let damages = foundry.utils.deepClone(message.system.damage?.roll ?? message.system.roll); + let damages = foundry.utils.deepClone(message.system.damage); if ( + !message.system.hasHealing && message.system.onSave && message.system.targets.find(t => t.id === target.id)?.saved?.success === true ) { @@ -244,6 +253,33 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } } + async onRollSimple(event, message) { + const buttonType = event.target.dataset.type ?? 'damage', + total = message.rolls.reduce((a,c) => a + Roll.fromJSON(c).total, 0), + damages = { + 'hitPoints': { + parts: [ + { + applyTo: 'hitPoints', + damageTypes: [], + total + } + ] + } + }, + targets = Array.from(game.user.targets); + + if (targets.length === 0) + return ui.notifications.info(game.i18n.localize('DAGGERHEART.UI.Notifications.noTargetsSelected')); + + targets.forEach(target => { + if(buttonType === 'healing') + target.actor.takeHealing(damages); + else + target.actor.takeDamage(damages); + }) + } + /** * Toggle visibility of target containers. * @param {MouseEvent} event diff --git a/module/data/action/attackAction.mjs b/module/data/action/attackAction.mjs index 83613a9e..4713938c 100644 --- a/module/data/action/attackAction.mjs +++ b/module/data/action/attackAction.mjs @@ -8,10 +8,6 @@ export default class DHAttackAction extends DHDamageAction { return parent.parent.type === 'weapon' ? 'attack' : 'spellcast'; } - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'; - } - prepareData() { super.prepareData(); if (!!this.item?.system?.attack) { diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 8376447a..a7523b29 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -1,6 +1,7 @@ import DhpActor from '../../documents/actor.mjs'; import D20RollDialog from '../../applications/dialogs/d20RollDialog.mjs'; import { ActionMixin } from '../fields/actionField.mjs'; +import { abilities } from '../../config/actorConfig.mjs'; const fields = foundry.data.fields; @@ -69,10 +70,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel : this.item?.actor; } - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'; - } - static getRollType(parent) { return 'trait'; } @@ -161,21 +158,26 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel prepareConfig(event) { return { event, - title: this.item.name, + title: `${this.item.name}: ${this.name}`, source: { item: this.item._id, action: this._id, actor: this.actor.uuid }, - dialog: {}, + dialog: { + configure: this.hasRoll + }, type: this.type, + hasRoll: this.hasRoll, hasDamage: this.damage?.parts?.length && this.type !== 'healing', hasHealing: this.damage?.parts?.length && this.type === 'healing', hasEffect: !!this.effects?.length, hasSave: this.hasSave, + hasTarget: true, selectedRollMode: game.settings.get('core', 'rollMode'), isFastForward: event.shiftKey, - data: this.getRollData() + data: this.getRollData(), + evaluate: this.hasRoll }; } @@ -192,7 +194,9 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel formula: this.roll.getFormula(), advantage: CONFIG.DH.ACTIONS.advantageState[this.roll.advState].value }; - if (this.roll?.type === 'diceSet') roll.lite = true; + if (this.roll?.type === 'diceSet' + || !this.hasRoll + ) roll.lite = true; return roll; } @@ -296,19 +300,27 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel /* SAVE */ async rollSave(actor, event, message) { if (!actor) return; + const title = actor.isNPC + ? game.i18n.localize('DAGGERHEART.GENERAL.reactionRoll') + : game.i18n.format('DAGGERHEART.UI.Chat.dualityRoll.abilityCheckTitle', { + ability: game.i18n.localize(abilities[this.save.trait]?.label) + }); return actor.diceRoll({ event, - title: 'Roll Save', + title, roll: { trait: this.save.trait, difficulty: this.save.difficulty ?? this.actor?.baseSaveDifficulty, type: 'reaction' }, + type: 'trait', + hasRoll: true, data: actor.getRollData() }); } updateSaveMessage(result, message, targetId) { + if(!result) return; const updateMsg = this.updateChatMessage.bind(this, message, targetId, { result: result.roll.total, success: result.roll.success diff --git a/module/data/action/damageAction.mjs b/module/data/action/damageAction.mjs index d7ad6f1c..3cfa7a5a 100644 --- a/module/data/action/damageAction.mjs +++ b/module/data/action/damageAction.mjs @@ -44,19 +44,14 @@ export default class DHDamageAction extends DHBaseAction { formulas = this.formatFormulas(formulas, systemData); + delete systemData.evaluate; + systemData.targets.forEach(t => t.hit = true); const config = { - title: game.i18n.format(`DAGGERHEART.UI.Chat.${this.type === 'healing' ? 'healing' : 'damage'}Roll.title`, { - damage: game.i18n.localize(this.name) - }), + ...systemData, roll: formulas, - targets: systemData.targets?.filter(t => t.hit) ?? data.targets, - hasSave: this.hasSave, - isCritical: systemData.roll?.isCritical ?? false, - isHealing: this.type === 'healing', - source: systemData.source, - data: this.getRollData(), - event - }; + dialog: {}, + data: this.getRollData() + } if (this.hasSave) config.onSave = this.save.damageMod; if (data.system) { config.source.message = data._id; diff --git a/module/data/action/healingAction.mjs b/module/data/action/healingAction.mjs index dad67dec..5efdc459 100644 --- a/module/data/action/healingAction.mjs +++ b/module/data/action/healingAction.mjs @@ -1,4 +1,3 @@ -import DHBaseAction from './baseAction.mjs'; import DHDamageAction from './damageAction.mjs'; export default class DHHealingAction extends DHDamageAction { @@ -7,49 +6,4 @@ export default class DHHealingAction extends DHDamageAction { static getRollType(parent) { return 'spellcast'; } - - /* static extraSchemas = [...super.extraSchemas, 'target', 'effects', 'healing', 'roll']; - - static getRollType(parent) { - return 'spellcast'; - } - - getFormulaValue(data) { - let formulaValue = this.healing.value; - if (this.hasRoll && this.healing.resultBased && data.system.roll.result.duality === -1) - return this.healing.valueAlt; - return formulaValue; - } - - async rollHealing(event, data) { - const systemData = data.system ?? data; - let formulas = [ - { - formula: this.getFormulaValue(data).getFormula(this.actor), - applyTo: this.healing.applyTo - } - ]; - - const config = { - title: game.i18n.format('DAGGERHEART.UI.Chat.healingRoll.title', { - healing: game.i18n.localize(CONFIG.DH.GENERAL.healingTypes[this.healing.applyTo].label) - }), - roll: formulas, - targets: systemData.targets?.filter(t => t.hit), - messageType: 'healing', - source: systemData.source, - data: this.getRollData(), - event - }; - - return CONFIG.Dice.daggerheart.DamageRoll.build(config); - } - - get chatTemplate() { - return 'systems/daggerheart/templates/ui/chat/healing-roll.hbs'; - } - - get modifiers() { - return []; - } */ } diff --git a/module/data/chat-message/_modules.mjs b/module/data/chat-message/_modules.mjs index 84f75c1b..2612622c 100644 --- a/module/data/chat-message/_modules.mjs +++ b/module/data/chat-message/_modules.mjs @@ -1,21 +1,11 @@ import DHAbilityUse from "./abilityUse.mjs"; -import DHAdversaryRoll from "./adversaryRoll.mjs"; -import DHDamageRoll from "./damageRoll.mjs"; -import DHDualityRoll from "./dualityRoll.mjs"; +import DHActorRoll from "./adversaryRoll.mjs"; import DHApplyEffect from './applyEffects.mjs' -export { - DHAbilityUse, - DHAdversaryRoll, - DHDamageRoll, - DHDualityRoll, - DHApplyEffect -} - export const config = { abilityUse: DHAbilityUse, - adversaryRoll: DHAdversaryRoll, - damageRoll: DHDamageRoll, - dualityRoll: DHDualityRoll, + adversaryRoll: DHActorRoll, + damageRoll: DHActorRoll, + dualityRoll: DHActorRoll, applyEffect: DHApplyEffect }; diff --git a/module/data/chat-message/adversaryRoll.mjs b/module/data/chat-message/adversaryRoll.mjs index 45f6fe39..24cac3d7 100644 --- a/module/data/chat-message/adversaryRoll.mjs +++ b/module/data/chat-message/adversaryRoll.mjs @@ -1,6 +1,6 @@ const fields = foundry.data.fields; -export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { +export default class DHActorRoll extends foundry.abstract.TypeDataModel { static defineSchema() { return { title: new fields.StringField(), @@ -20,22 +20,29 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { }) }) ), - targetSelection: new fields.BooleanField({ initial: true }), + targetSelection: new fields.BooleanField({ initial: false }), + hasRoll: new fields.BooleanField({ initial: false }), hasDamage: new fields.BooleanField({ initial: false }), hasHealing: new fields.BooleanField({ initial: false }), hasEffect: new fields.BooleanField({ initial: false }), hasSave: new fields.BooleanField({ initial: false }), + hasTarget: new fields.BooleanField({ initial: false }), + isCritical: new fields.BooleanField({ initial: false }), + onSave: new fields.StringField(), source: new fields.SchemaField({ actor: new fields.StringField(), item: new fields.StringField(), action: new fields.StringField() }), - damage: new fields.ObjectField() + damage: new fields.ObjectField(), + costs: new fields.ArrayField( + new fields.ObjectField() + ) }; } get messageTemplate() { - return 'systems/daggerheart/templates/ui/chat/adversary-roll.hbs'; + return 'systems/daggerheart/templates/ui/chat/roll.hbs'; } prepareDerivedData() { @@ -46,5 +53,15 @@ export default class DHAdversaryRoll extends foundry.abstract.TypeDataModel { game.system.api.fields.ActionFields.TargetField.formatTarget(t) ) : this.targets; + if(this.targetSelection === true) { + this.targetShort = this.targets.reduce((a,c) => { + if(c.hit) a.hit += 1; + else c.miss += 1; + return a; + }, {hit: 0, miss: 0}) + } + this.pendingSaves = this.targets.filter( + target => target.hit && target.saved.success === null + ).length > 0; } } diff --git a/module/data/chat-message/damageRoll.mjs b/module/data/chat-message/damageRoll.mjs deleted file mode 100644 index 167e97d9..00000000 --- a/module/data/chat-message/damageRoll.mjs +++ /dev/null @@ -1,49 +0,0 @@ -export default class DHDamageRoll extends foundry.abstract.TypeDataModel { - static defineSchema() { - const fields = foundry.data.fields; - - return { - messageType: new fields.StringField({ initial: 'damage' }), - title: new fields.StringField(), - roll: new fields.DataField({}), - targets: new fields.ArrayField( - new fields.SchemaField({ - id: new fields.StringField({ required: true }), - actorId: new fields.StringField({}), - name: new fields.StringField(), - img: new fields.StringField(), - hit: new fields.BooleanField({ initial: false }), - saved: new fields.SchemaField({ - result: new fields.NumberField(), - success: new fields.BooleanField({ nullable: true, initial: null }) - }) - }) - ), - targetSelection: new fields.BooleanField({ initial: true }), - hasSave: new fields.BooleanField({ initial: false }), - isHealing: new fields.BooleanField({ initial: false }), - onSave: new fields.StringField(), - source: new fields.SchemaField({ - actor: new fields.StringField(), - item: new fields.StringField(), - action: new fields.StringField(), - message: new fields.StringField() - }), - directDamage: new fields.BooleanField({ initial: true }) - }; - } - - get messageTemplate() { - return `systems/daggerheart/templates/ui/chat/${this.messageType}-roll.hbs`; - } - - prepareDerivedData() { - this.hasHitTarget = this.targets.filter(t => t.hit === true).length > 0; - this.currentTargets = - this.targetSelection !== true - ? Array.from(game.user.targets).map(t => - game.system.api.fields.ActionFields.TargetField.formatTarget(t) - ) - : this.targets; - } -} diff --git a/module/data/chat-message/dualityRoll.mjs b/module/data/chat-message/dualityRoll.mjs deleted file mode 100644 index 63fa9fa3..00000000 --- a/module/data/chat-message/dualityRoll.mjs +++ /dev/null @@ -1,7 +0,0 @@ -import DHAdversaryRoll from './adversaryRoll.mjs'; - -export default class DHDualityRoll extends DHAdversaryRoll { - get messageTemplate() { - return 'systems/daggerheart/templates/ui/chat/duality-roll.hbs'; - } -} diff --git a/module/data/fields/action/costField.mjs b/module/data/fields/action/costField.mjs index ef51e086..abfc2e63 100644 --- a/module/data/fields/action/costField.mjs +++ b/module/data/fields/action/costField.mjs @@ -26,7 +26,7 @@ export default class CostField extends fields.ArrayField { } static calcCosts(costs) { - console.log(costs, CostField.getResources.call(this, costs)); + // console.log(costs, CostField.getResources.call(this, costs)); const resources = CostField.getResources.call(this, costs); return costs.map(c => { c.scale = c.scale ?? 1; diff --git a/module/data/fields/action/rollField.mjs b/module/data/fields/action/rollField.mjs index d53dfa6c..9ba57154 100644 --- a/module/data/fields/action/rollField.mjs +++ b/module/data/fields/action/rollField.mjs @@ -54,7 +54,7 @@ export class DHActionRollData extends foundry.abstract.DataModel { this.diceRolling.multiplier === 'flat' ? this.diceRolling.flatMultiplier : `@${this.diceRolling.multiplier}`; - if (this.diceRolling.compare && this.diceRolling.threshold) { + if (this.diceRolling.compare && this.diceRolling.treshold) { formula = `${multiplier}${this.diceRolling.dice}cs${CONFIG.DH.ACTIONS.diceCompare[this.diceRolling.compare].operator}${this.diceRolling.treshold}`; } else { formula = `${multiplier}${this.diceRolling.dice}`; diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index 8cf7b30c..00948f40 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -252,19 +252,27 @@ export function ActionMixin(Base) { const systemData = { title: game.i18n.localize('DAGGERHEART.CONFIG.ActionType.action'), origin: origin, - img: this.img, - name: this.name, - description: this.description, - actions: [] + action: { name: this.name, img: this.img, tags: this.tags ? this.tags : ['Spell', 'Arcana', 'Lv 10'] }, + itemOrigin: this.item, + description: this.description }; const msg = { type: 'abilityUse', user: game.user.id, + actor: { name: this.actor.name, img: this.actor.img }, + author: this.author, + speaker: cls.getSpeaker(), + title: game.i18n.localize('DAGGERHEART.UI.Chat.action.title'), system: systemData, content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/ui/chat/ability-use.hbs', + 'systems/daggerheart/templates/ui/chat/action.hbs', systemData - ) + ), + flags: { + daggerheart: { + cssClass: 'dh-chat-message dh-style' + } + } }; cls.create(msg); diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index 8cec2669..28f7ecf7 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -13,12 +13,16 @@ export default class D20Roll extends DHRoll { DISADVANTAGE: -1 }; - static messageType = 'adversaryRoll'; - static CRITICAL_TRESHOLD = 20; static DefaultDialog = D20RollDialog; + get title() { + return game.i18n.localize( + "DAGGERHEART.GENERAL.d20Roll" + ); + } + get d20() { if (!(this.terms[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); return this.terms[0]; @@ -136,7 +140,9 @@ export default class D20Roll extends DHRoll { static postEvaluate(roll, config = {}) { const data = super.postEvaluate(roll, config); + data.type = config.roll?.type; if (config.targets?.length) { + config.targetSelection = true; config.targets.forEach(target => { const difficulty = config.roll.difficulty ?? target.difficulty ?? target.evasion; target.hit = this.isCritical || roll.total >= difficulty; @@ -145,7 +151,6 @@ export default class D20Roll extends DHRoll { data.difficulty = config.roll.difficulty; data.success = roll.isCritical || roll.total >= config.roll.difficulty; } - data.type = config.roll.type; data.advantage = { type: config.roll.advantage, dice: roll.dAdvantage?.denomination, @@ -159,7 +164,7 @@ export default class D20Roll extends DHRoll { rerolls: dice.results.filter(x => x.rerolled) } })); - data.isCritical = roll.isCritical; + data.isCritical = config.isCritical = roll.isCritical; data.extra = roll.dice .filter(d => !roll.baseTerms.includes(d)) .map(d => { diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index b805bdbd..bab685b4 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -6,23 +6,17 @@ export default class DamageRoll extends DHRoll { super(formula, data, options); } - static messageType = 'damageRoll'; - static DefaultDialog = DamageDialog; static async buildEvaluate(roll, config = {}, message = {}) { - if (config.evaluate !== false) { - // if (config.dialog.configure === false) roll.constructFormula(config); + if (config.evaluate !== false) for (const roll of config.roll) await roll.roll.evaluate(); - } + roll._evaluated = true; - const parts = []; - for (let r of config.roll) { - const part = this.postEvaluate(r); - parts.push(part); - } + const parts = config.roll.map(r => this.postEvaluate(r)); - config.roll = this.unifyDamageRoll(parts); + config.damage = this.unifyDamageRoll(parts); + config.targetSelection = config.targets?.length } static postEvaluate(roll, config = {}) { @@ -37,11 +31,18 @@ export default class DamageRoll extends DHRoll { } static async buildPost(roll, config, message) { + if (game.modules.get('dice-so-nice')?.active) { + const pool = foundry.dice.terms.PoolTerm.fromRolls( + Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll)) + ), + diceRoll = Roll.fromTerms([pool]); + await game.dice3d.showForRoll(diceRoll, game.user, true); + } await super.buildPost(roll, config, message); if (config.source?.message) { const chatMessage = ui.chat.collection.get(config.source.message); - chatMessage.update({ 'system.damage': config }); - } + chatMessage.update({ 'system.damage': config.damage }); + } } static unifyDamageRoll(rolls) { diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index bacaf47b..1b490921 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -7,6 +7,12 @@ export default class DHRoll extends Roll { if (!this.data || !Object.keys(this.data).length) this.data = options.data; } + get title() { + return game.i18n.localize( + "DAGGERHEART.GENERAL.Roll.basic" + ); + } + static messageType = 'adversaryRoll'; static DefaultDialog = D20RollDialog; @@ -46,8 +52,10 @@ export default class DHRoll extends Roll { } static async buildEvaluate(roll, config = {}, message = {}) { - if (config.evaluate !== false) await roll.evaluate(); - config.roll = this.postEvaluate(roll, config); + if (config.evaluate !== false) { + await roll.evaluate(); + config.roll = this.postEvaluate(roll, config); + } } static async buildPost(roll, config, message) { @@ -56,15 +64,8 @@ export default class DHRoll extends Roll { } // Create Chat Message - if (roll instanceof CONFIG.Dice.daggerheart.DamageRoll && Object.values(config.roll)?.length) { - const pool = foundry.dice.terms.PoolTerm.fromRolls( - Object.values(config.roll).flatMap(r => r.parts.map(p => p.roll)) - ); - roll = Roll.fromTerms([pool]); - } - if (config.source?.message) { - if (game.modules.get('dice-so-nice')?.active) await game.dice3d.showForRoll(roll, game.user, true); - } else config.message = await this.toMessage(roll, config); + if (!config.source?.message) + config.message = await this.toMessage(roll, config); } static postEvaluate(roll, config = {}) { @@ -85,11 +86,14 @@ export default class DHRoll extends Roll { msg = { type: this.messageType, user: game.user.id, + title: roll.title, + speaker: cls.getSpeaker(), sound: config.mute ? null : CONFIG.sounds.dice, system: config, rolls: [roll] }; - return await cls.create(msg, { rollMode: config.selectedRollMode }); + if(roll._evaluated) return await cls.create(msg, { rollMode: config.selectedRollMode }); + return msg; } static applyKeybindings(config) { @@ -178,7 +182,7 @@ export default class DHRoll extends Roll { export const registerRollDiceHooks = () => { Hooks.on(`${CONFIG.DH.id}.postRollDuality`, async (config, message) => { - const hopeFearAutomation = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).hopeFear; + const hopeFearAutomation = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation).hopeFear; if ( !config.source?.actor || (game.user.isGM ? !hopeFearAutomation.gm : !hopeFearAutomation.players) || diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index ab6264c6..b180396e 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -17,6 +17,12 @@ export default class DualityRoll extends D20Roll { static DefaultDialog = D20RollDialog; + get title() { + return game.i18n.localize( + "DAGGERHEART.GENERAL.dualityRoll" + ); + } + get dHope() { // if ( !(this.terms[0] instanceof foundry.dice.terms.Die) ) return; if (!(this.dice[0] instanceof CONFIG.Dice.daggerheart.DualityDie)) this.createBaseDice(); diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index cee90b91..9eec2ffa 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -115,24 +115,26 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { async toChat(origin) { const cls = getDocumentClass('ChatMessage'); + const actor = game.actors.get(cls.getSpeaker().actor); const systemData = { - title: game.i18n.localize('DAGGERHEART.CONFIG.ActionType.action'), + action: { img: this.img, name: this.name }, + actor: { name: actor.name, img: actor.img }, + author: this.author, + speaker: cls.getSpeaker(), origin: origin, - img: this.img, - name: this.name, description: this.description, actions: [] }; - const msg = new cls({ - type: 'abilityUse', + const msg = { + title: game.i18n.localize('DAGGERHEART.GENERAL.Effect.single'), user: game.user.id, system: systemData, content: await foundry.applications.handlebars.renderTemplate( - 'systems/daggerheart/templates/ui/chat/ability-use.hbs', + 'systems/daggerheart/templates/ui/chat/action.hbs', systemData ) - }); + }; - cls.create(msg.toObject()); + cls.create(msg); } } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index dad36ec7..ef968b47 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -541,12 +541,12 @@ export default class DhpActor extends Actor { } canResist(type, resistance) { - if (!type) return 0; + if (!type?.length) return false; return type.every(t => this.system.resistance[t]?.[resistance] === true); } getDamageTypeReduction(type) { - if (!type) return 0; + if (!type?.length) return 0; const reduction = Object.entries(this.system.resistance).reduce( (a, [index, value]) => (type.includes(index) ? Math.min(value.reduction, a) : a), Infinity diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 46f95633..51b34ab0 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -6,13 +6,18 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { _source: this.system._source }); + const actor = game.actors.get(this.speaker.actor); + const actorData = actor ?? { + img: this.author.avatar ? this.author.avatar : 'icons/svg/mystery-man.svg', + name: '' + }; /* We can change to fully implementing the renderHTML function if needed, instead of augmenting it. */ - const html = await super.renderHTML(); + const html = await super.renderHTML({ actor: actorData, author: this.author }); this.applyPermission(html); if (this.type === 'dualityRoll') { html.classList.add('duality'); - switch (this.system.roll.result.duality) { + switch (this.system.roll?.result?.duality) { case 1: html.classList.add('hope'); break; diff --git a/module/documents/item.mjs b/module/documents/item.mjs index 21ba8bc4..3c074f44 100644 --- a/module/documents/item.mjs +++ b/module/documents/item.mjs @@ -102,9 +102,9 @@ export default class DHItem extends foundry.documents.Item { * Generate an array of localized tag. * @returns {string[]} An array of localized tag strings. */ - getTags() { + _getTags() { const tags = []; - if (this.system.getTags) tags.push(...this.system.getTags()); + if (this.system._getTags) tags.push(...this.system._getTags()); return tags; } @@ -143,20 +143,33 @@ export default class DHItem extends foundry.documents.Item { : game.i18n.localize('DAGGERHEART.UI.Chat.foundationCard.subclassFeatureTitle'), origin: origin, img: this.img, - name: this.name, + item: { + name: this.name, + img: this.img, + tags: this._getTags() + }, description: this.system.description, - actions: [] + actions: this.system.actions }; - const msg = new cls({ + const msg = { type: 'abilityUse', user: game.user.id, + actor: game.actors.get(cls.getSpeaker().actor), + author: this.author, + speaker: cls.getSpeaker(), system: systemData, + title: game.i18n.localize('DAGGERHEART.ACTIONS.Config.displayInChat'), content: await foundry.applications.handlebars.renderTemplate( 'systems/daggerheart/templates/ui/chat/ability-use.hbs', systemData - ) - }); + ), + flags: { + daggerheart: { + cssClass: 'dh-chat-message dh-style' + } + } + }; - cls.create(msg.toObject()); + cls.create(msg); } } diff --git a/module/enrichers/DualityRollEnricher.mjs b/module/enrichers/DualityRollEnricher.mjs index 4a6fac23..360b08ae 100644 --- a/module/enrichers/DualityRollEnricher.mjs +++ b/module/enrichers/DualityRollEnricher.mjs @@ -93,9 +93,8 @@ export const enrichedDualityRoll = async ( advantage, type: reaction ? 'reaction' : null }, - chatMessage: { - template: 'systems/daggerheart/templates/ui/chat/duality-roll.hbs' - } + type: 'trait', + hasRoll: true }; if (target) { diff --git a/module/helpers/handlebarsHelper.mjs b/module/helpers/handlebarsHelper.mjs index 7c862f92..6d6c2bbc 100644 --- a/module/helpers/handlebarsHelper.mjs +++ b/module/helpers/handlebarsHelper.mjs @@ -11,7 +11,8 @@ export default class RegisterHandlebarsHelpers { damageSymbols: this.damageSymbols, rollParsed: this.rollParsed, hasProperty: foundry.utils.hasProperty, - setVar: this.setVar + setVar: this.setVar, + empty: this.empty }); } static add(a, b) { @@ -65,4 +66,9 @@ export default class RegisterHandlebarsHelpers { static setVar(name, value, context) { this[name] = value; } + + static empty(object) { + if(!(typeof object === 'object')) return true; + return Object.keys(object).length === 0; + } } diff --git a/module/systemRegistration/handlebars.mjs b/module/systemRegistration/handlebars.mjs index fc6decd3..48a99735 100644 --- a/module/systemRegistration/handlebars.mjs +++ b/module/systemRegistration/handlebars.mjs @@ -26,11 +26,15 @@ export const preloadHandlebarsTemplates = async function () { 'systems/daggerheart/templates/actionTypes/effect.hbs', 'systems/daggerheart/templates/actionTypes/beastform.hbs', 'systems/daggerheart/templates/settings/components/settings-item-line.hbs', - 'systems/daggerheart/templates/ui/chat/parts/damage-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/tooltipTags.hbs', 'systems/daggerheart/templates/dialogs/downtime/activities.hbs', - 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs' + 'systems/daggerheart/templates/dialogs/dice-roll/costSelection.hbs', + + + 'systems/daggerheart/templates/ui/chat/parts/roll-part.hbs', + 'systems/daggerheart/templates/ui/chat/parts/damage-part.hbs', + 'systems/daggerheart/templates/ui/chat/parts/target-part.hbs', + 'systems/daggerheart/templates/ui/chat/parts/button-part.hbs', ]); }; diff --git a/styles/less/dialog/actions/action-list.less b/styles/less/dialog/actions/action-list.less index 6a899ca7..33b3d0bb 100644 --- a/styles/less/dialog/actions/action-list.less +++ b/styles/less/dialog/actions/action-list.less @@ -2,6 +2,13 @@ @import '../../utils/colors.less'; .application.daggerheart.dh-style { + &.max-800 { + max-height: 800px; + .tab.active { + overflow: auto; + } + } + .actions-list, .action-buttons-list { display: flex; diff --git a/styles/less/global/chat.less b/styles/less/global/chat.less new file mode 100644 index 00000000..1e37309d --- /dev/null +++ b/styles/less/global/chat.less @@ -0,0 +1,79 @@ +@import '../utils/colors.less'; +@import '../utils/fonts.less'; +@import '../utils/mixin.less'; + +.theme-light { + .daggerheart.chat-sidebar .chat-log, + #chat-notifications .chat-log { + .chat-message { + background-image: url('../assets/parchments/dh-parchment-light.png'); + } + } +} + +#chat-message { + font-family: @font-body; + padding: 8px; +} + +.daggerheart.chat-sidebar, +#chat-notifications { + .chat-log { + .chat-message { + border: none !important; + padding: 0; + background-image: url('../assets/parchments/dh-parchment-dark.png'); + + .message-header { + display: flex; + gap: 4px; + padding: 8px; + + .message-header-metadata { + flex: none; + display: flex; + + .message-metadata { + font-family: @font-body; + color: light-dark(@dark, @beige); + } + } + + .message-header-main { + display: flex; + align-items: center; + gap: 8px; + flex: 1; + overflow: hidden; + + .actor-img { + border-radius: 50%; + width: 40px; + height: 40px; + object-fit: cover; + } + + .message-sub-header-container { + flex: 1; + display: flex; + flex-direction: column; + justify-content: space-between; + color: light-dark(@dark, @beige); + + h4 { + font-size: 16px; + font-weight: bold; + margin-bottom: 0; + font-family: @font-subtitle; + color: light-dark(@dark-blue, @golden); + } + } + } + } + + .message-content { + padding-bottom: 8px; + } + } + } +} diff --git a/styles/less/global/dice.less b/styles/less/global/dice.less new file mode 100644 index 00000000..075fa9b4 --- /dev/null +++ b/styles/less/global/dice.less @@ -0,0 +1,80 @@ +.dice { + position: relative; + height: 2rem; + aspect-ratio: 1; + font-size: 1rem; + paint-order: stroke fill; + -webkit-text-stroke: 2px black; + z-index: 1; + + &.xxs { + height: 1rem; + font-size: .5rem; + -webkit-text-stroke: 1px black; + } + + &.xs { + height: 1.5rem; + font-size: .75rem; + } + + &.lg { + height: 2.5rem; + font-size: 1.25rem; + } + + &.xl { + height: 3rem; + font-size: 1.5rem; + } + + &.discarded { + opacity: .5; + } + + &:before { + content: ' '; + position: absolute; + width: 100%; + height: 100%; + z-index: -1; + mask: var(--svg-die) no-repeat center; + mask-size: contain; + background: linear-gradient(139.01deg, #EFE6D8 3.51%, #372E1F 96.49%); + } + + &.d4:before { + --svg-die: url(../assets/icons/dice/default/d4.svg); + } + &.d6:before { + --svg-die: url(../assets/icons/dice/default/d6.svg); + } + &.d8:before { + --svg-die: url(../assets/icons/dice/default/d8.svg); + } + &.d10:before { + --svg-die: url(../assets/icons/dice/default/d10.svg); + } + &.d12:before { + --svg-die: url('../assets/icons/dice/default/d12.svg'); + } + &.d20:before { + --svg-die: url(../assets/icons/dice/default/d20.svg); + } + + &.color-hope:before { + background: linear-gradient(139.01deg, #F3C267 3.51%, #4C3407 96.49%); + } + + &.color-fear:before { + background: linear-gradient(151.21deg, #352AB2 7.21%, #18162E 92.79%); + } + + &.color-adv:before { + background: linear-gradient(139.01deg, #40A640 3.51%, #011B01 96.49%); + } + + &.color-dis:before { + background: linear-gradient(139.01deg, #E54E4E 3.51%, #3C0000 82.19%); + } +} \ No newline at end of file diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 0b689a7e..6bda8af6 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -1,7 +1,7 @@ @import '../utils/colors.less'; @import '../utils/fonts.less'; -.application.dh-style { +.dh-style { border: 1px solid light-dark(@dark-blue, @golden); input[type='text'], diff --git a/styles/less/global/index.less b/styles/less/global/index.less index 031a9cfc..d6c8459e 100644 --- a/styles/less/global/index.less +++ b/styles/less/global/index.less @@ -1,5 +1,6 @@ @import './sheet.less'; @import './dialog.less'; +@import './chat.less'; @import './elements.less'; @import './tab-navigation.less'; @import './tab-form-footer.less'; @@ -15,3 +16,4 @@ @import './prose-mirror.less'; @import './filter-menu.less'; @import './tab-attachments.less'; +@import './dice.less'; diff --git a/styles/less/global/inventory-item.less b/styles/less/global/inventory-item.less index a761b4eb..274f51a5 100644 --- a/styles/less/global/inventory-item.less +++ b/styles/less/global/inventory-item.less @@ -51,6 +51,10 @@ .roll-img { position: absolute; transition: opacity 300ms ease-in; + height: 40px; + width: 40px; + object-fit: cover; + border-radius: 3px; } .roll-img { diff --git a/styles/less/sheets/actors/adversary/sidebar.less b/styles/less/sheets/actors/adversary/sidebar.less index f1c89e41..eec3b6cf 100644 --- a/styles/less/sheets/actors/adversary/sidebar.less +++ b/styles/less/sheets/actors/adversary/sidebar.less @@ -262,6 +262,7 @@ display: flex; flex-direction: column; gap: 5px; + margin-bottom: 10px; .inventory-item { padding: 0 10px; diff --git a/styles/less/sheets/actors/character/sidebar.less b/styles/less/sheets/actors/character/sidebar.less index 61f8cc70..db4c9cbb 100644 --- a/styles/less/sheets/actors/character/sidebar.less +++ b/styles/less/sheets/actors/character/sidebar.less @@ -434,6 +434,7 @@ display: flex; flex-direction: column; gap: 5px; + margin-bottom: 10px; .inventory-item { padding: 0 10px; diff --git a/styles/less/ui/chat/ability-use.less b/styles/less/ui/chat/ability-use.less new file mode 100644 index 00000000..3e747380 --- /dev/null +++ b/styles/less/ui/chat/ability-use.less @@ -0,0 +1,118 @@ +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +.daggerheart.chat { + &.domain-card { + display: flex; + flex-direction: column; + align-items: center; + + .card-img { + width: 100%; + height: 200px; + mask-image: linear-gradient(0deg, transparent 0%, black 10%, black 90%, transparent 100%); + object-fit: cover; + } + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .domain-card-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .domain-card-header { + display: flex; + flex-direction: row; + align-items: center; + margin: 8px; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; + + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + + .domain-label { + display: flex; + flex-direction: column; + width: 100%; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + + .title { + font-size: 20px; + color: @golden; + font-family: @font-subtitle; + margin: 0; + } + + .tags { + display: flex; + gap: 10px; + flex-wrap: wrap; + + .tag { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + padding: 3px 5px; + font-size: 12px; + font-family: @font-body; + + background: light-dark(@dark-15, @beige-15); + border: 1px solid light-dark(@dark, @beige); + color: light-dark(@dark, @beige); + border-radius: 3px; + } + } + } + } + } + + .description { + color: @beige; + padding: 8px; + font-family: @font-body; + } + + .ability-card-footer { + display: flex; + flex-wrap: wrap; + gap: 5px; + width: 100%; + padding: 0 8px; + + button { + font-family: @font-body; + font-weight: 600; + height: 40px; + flex: 1 1 calc(50% - 5px); + + &:nth-last-child(1):nth-child(odd) { + flex-basis: 100%; + } + } + + .ability-card-action-cost { + margin: auto; + font-size: 1.5em; + } + } + } +} diff --git a/styles/less/ui/chat/action.less b/styles/less/ui/chat/action.less new file mode 100644 index 00000000..c3c51816 --- /dev/null +++ b/styles/less/ui/chat/action.less @@ -0,0 +1,101 @@ +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +.daggerheart.chat { + &.action { + display: flex; + flex-direction: column; + align-items: center; + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .action-move { + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .action-section { + display: flex; + flex-direction: row; + align-items: center; + margin: 8px 8px 0; + padding-bottom: 5px; + width: -webkit-fill-available; + gap: 5px; + border-bottom: 1px solid @golden; + + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + + .action-img { + width: 40px; + height: 40px; + border-radius: 3px; + object-fit: cover; + } + + .action-header { + display: flex; + flex-direction: column; + gap: 5px; + + .title { + font-size: 20px; + color: @golden; + font-family: @font-subtitle; + margin: 0; + } + + .label { + font-size: 12px; + color: @beige; + font-family: @font-body; + margin: 0; + } + } + } + } + + .description { + color: @beige; + padding: 8px; + font-family: @font-body; + } + + .ability-card-footer { + display: flex; + flex-wrap: wrap; + gap: 5px; + width: 100%; + padding: 0 8px; + + button { + font-family: @font-body; + font-weight: 600; + height: 40px; + flex: 1 1 calc(50% - 5px); + + &:nth-last-child(1):nth-child(odd) { + flex-basis: 100%; + } + } + + .ability-card-action-cost { + margin: auto; + font-size: 1.5em; + } + } + } +} diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index 4558cf8e..69bdd6f5 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -1,31 +1,8 @@ @import '../../utils/colors.less'; +@import '../../utils/fonts.less'; @import '../../utils/spacing.less'; .daggerheart.chat { - &.downtime { - display: flex; - flex-direction: column; - align-items: center; - - .downtime-title-container { - display: flex; - flex-direction: column; - align-items: center; - - .downtime-subtitle { - font-size: 17px; - } - } - - .downtime-image { - width: 80px; - } - - .action-use-button { - width: 100%; - } - } - &.resource-roll { .reroll-message { text-align: center; @@ -34,7 +11,7 @@ } } - &.roll { + /* &.roll { .dice-flavor { text-align: center; font-weight: bold; @@ -342,6 +319,9 @@ button { flex: 1; + height: 40px; + font-family: @font-body; + font-weight: 600; } } @@ -356,59 +336,7 @@ &:not(.expanded) .dice-tooltip { grid-template-rows: 0fr; } - } - - &.domain-card { - display: flex; - flex-direction: column; - align-items: center; - - .domain-card-title { - width: 100%; - display: flex; - flex-direction: column; - align-items: center; - - div { - font-size: 20px; - font-variant: small-caps; - font-weight: bold; - } - - h2 { - width: 100%; - text-align: center; - margin: 0; - } - } - - .ability-card-footer { - display: flex; - width: 100%; - margin-top: @fullMargin; - flex-wrap: wrap; - - button { - border-radius: 6px; - background: @positive; - border-color: black; - flex-basis: calc(50% - 2px); - - &:nth-of-type(n + 3) { - margin-top: @tinyMargin; - } - } - - .ability-card-action-cost { - margin: auto; - font-size: 1.5em; - } - } - - img { - width: 80px; - } - } + } */ button { &.inner-button { @@ -435,3 +363,362 @@ } } } + +.daggerheart, +#chat-notifications { + .chat-message { + --text-color: light-dark(@dark-blue, @golden); + --bg-color: light-dark(@dark-blue-40, @golden-40); + + &.duality { + &.hope { + --text-color: @golden; + --bg-color: @golden-40; + .message-header, + .message-content { + background-color: @golden-bg; + } + } + + &.fear { + --text-color: @chat-blue; + --bg-color: @chat-blue-40; + .message-header, + .message-content { + background-color: @chat-blue-bg; + } + } + + &.critical { + --text-color: @chat-purple; + --bg-color: @chat-purple-40; + .message-header, + .message-content { + background-color: @chat-purple-bg; + } + } + } + + .chat-roll { + font-size: var(--font-size-12); + padding: 0 20px; + + > .roll-part-header { + font-size: var(--font-size-14); + } + + .roll-part-header { + display: grid; + grid-template-columns: 1fr auto 1fr; + align-items: center; + color: light-dark(@dark, @beige); + margin: 5px 0; + + span { + display: flex; + align-items: center; + gap: 5px; + text-transform: capitalize; + padding: 0 10px; + } + + &:before, + &:after { + content: ' '; + height: 1px; + } + + &:before { + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--text-color) 100%); + } + + &:after { + background: linear-gradient(90deg, var(--text-color) 0%, rgba(0, 0, 0, 0) 100%); + } + } + + .roll-part-extra { + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + margin-top: 8px; + } + + .roll-part-content { + display: flex; + flex-direction: column; + align-items: center; + gap: 5px; + padding: 5px 0; + + .dice-tooltip { + width: 100%; + + .wrapper { + display: flex; + flex-direction: column; + gap: 10px; + + > :first-child:not(.target-selector) { + margin-top: 5px; + } + + > :last-child { + margin-bottom: 5px; + } + } + } + + .roll-result-container { + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + color: var(--text-color); + font-weight: 700; + font-family: 'Cinzel', sans-serif; + + .roll-result-value { + font-size: var(--font-size-24); + } + + .roll-result-desc { + font-size: var(--font-size-16); + margin-top: 2px; + } + } + + .roll-difficulty { + margin-top: -5px; + } + } + } + + .roll-dice { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + font-weight: 700; + font-family: 'Cinzel', sans-serif; + flex-wrap: wrap; + + .roll-die { + display: flex; + flex-direction: column; + gap: 3px; + + label { + text-align: center; + height: var(--font-size-12); + } + + > div { + display: flex; + align-items: center; + justify-content: center; + gap: 5px; + // font-size: var(--font-size-20); + } + } + } + + fieldset { + display: flex; + flex-direction: column; + // gap: 10px; + border-color: var(--text-color); + border-radius: 5px; + + legend { + display: flex; + align-items: center; + gap: 10px; + padding: 0 5px; + color: var(--text-color); + } + } + + .target-selector { + + .roll-part-extra { + margin: 0; + } + + .target-choice { + display: flex; + font-size: var(--font-size-14); + color: var(--text-color); + padding: 5px 0; + + .button-target-selection { + flex: 1; + text-align: center; + } + + .button-target-selection:hover, + .target-selected { + font-weight: bold; + text-shadow: 0px 0px 8px var(--text-color); + } + } + } + + i { + text-align: center; + } + + .roll-target { + display: flex; + width: 100%; + gap: 10px; + align-items: center; + + .target-img { + border-radius: 50%; + width: 40px; + height: 40px; + object-fit: cover; + } + + .target-data { + flex: 1; + } + + .target-save { + display: flex; + align-items: center; + justify-content: center; + width: 22px; + height: 22px; + &:hover > i { + scale: 1.2; + } + + i { + &.fa-check { + color: @green; + } + &.fa-xmark { + color: @medium-red; + } + } + } + } + + .roll-formula { + background-color: var(--bg-color); + color: var(--text-color); + border-radius: 4px; + padding: 3px 5px; + width: fit-content; + margin: auto; + } + + .roll-difficulty, + .target-hit-status { + color: @green; + background-color: @green-10; + border: 1px solid currentColor; + border-radius: 4px; + padding: 3px 5px; + text-transform: uppercase; + font-weight: 600; + + &.is-miss { + color: @medium-red; + background-color: @medium-red-10; + } + } + + .target-hit-status { + width: fit-content; + margin-top: 2px; + } + + div[data-action='expandRoll'] { + .roll-part-header > div > span { + &:before, + &:after { + content: '\f078'; + font-family: var(--font-awesome); + color: var(--text-color); + transition: all 0.3s ease; + } + } + + .on-reduced { + display: grid; + overflow: hidden; + grid-template-rows: 1fr; + transition: grid-template-rows 250ms ease; + + .wrapper { + display: flex; + gap: 10px; + overflow: hidden; + } + } + + &.expanded { + .roll-part-header > div > span { + &:before, + &:after { + transform: rotate(180deg); + } + } + + .on-reduced { + grid-template-rows: 0fr; + } + } + } + + .roll-part + .roll-part { + margin-top: 0; + } + + .target-section { + .roll-part-content { + gap: 10px; + } + + .roll-part-extra { + position: relative; + + .target-pending-saves { + display: flex; + align-items: center; + justify-content: center; + height: 25px; + width: 25px; + &.is-absolute { + position: absolute; + bottom: 0; + right: 0; + } + } + } + } + + .roll-buttons { + display: flex; + gap: 5px; + margin-top: 8px; + button { + flex: 1; + } + } + + .font-20 { + font-size: var(--font-size-20); + } + + .dice-roll .dice-tooltip fieldset { + margin-bottom: 5px; + .roll-dice { + gap: 10px; + } + } + } +} diff --git a/styles/less/ui/chat/downtime.less b/styles/less/ui/chat/downtime.less new file mode 100644 index 00000000..bc702aeb --- /dev/null +++ b/styles/less/ui/chat/downtime.less @@ -0,0 +1,87 @@ +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; +@import '../../utils/spacing.less'; + +.daggerheart.chat { + &.downtime { + display: flex; + flex-direction: column; + align-items: center; + + details[open] { + .fa-chevron-down { + transform: rotate(180deg); + transition: all 0.3s ease; + } + } + + .downtime-moves-list { + display: flex; + flex-direction: column; + gap: 5px; + width: 100%; + + .fa-chevron-down { + transition: all 0.3s ease; + margin-left: auto; + } + + .downtime-move { + width: 100%; + + .downtime-label { + display: flex; + align-items: center; + gap: 5px; + border-bottom: 1px solid @golden; + margin: 0 8px; + padding-bottom: 5px; + width: -webkit-fill-available; + + &:hover { + background: light-dark(@dark-blue-10, @golden-10); + cursor: pointer; + transition: all 0.3s ease; + } + + .downtime-image { + width: 40px; + height: 40px; + border-radius: 3px; + } + + .header-label { + padding: 8px; + .title { + font-size: 16px; + color: @golden; + font-family: @font-subtitle; + margin: 0; + } + .label { + font-size: 12px; + color: @beige; + font-family: @font-body; + margin: 0; + } + } + } + + .description { + padding: 8px; + color: beige; + font-family: @font-body; + font-size: 14px; + } + } + + .action-use-button { + width: -webkit-fill-available; + margin: 0 8px; + font-family: @font-body; + font-weight: 600; + height: 40px; + } + } + } +} diff --git a/styles/less/ui/chat/sheet.less b/styles/less/ui/chat/sheet.less index 1c41f97e..da66c12f 100644 --- a/styles/less/ui/chat/sheet.less +++ b/styles/less/ui/chat/sheet.less @@ -1,3 +1,12 @@ +@import '../../utils/colors.less'; +@import '../../utils/fonts.less'; + +.chat-message.dh-chat-message { + .message-content { + padding: 0; + } +} + .chat-message { .duality-modifiers, .duality-result, @@ -6,6 +15,66 @@ } .message-content { + padding: 0 8px; + font-family: @font-body; + color: light-dark(@dark, @beige); + + blockquote { + border-left: 5px solid light-dark(@dark-blue-40, @golden-40); + } + + a[href] { + color: light-dark(@dark-blue, @golden); + } + + a[href]:hover, + a[href].active { + font-weight: bold; + text-shadow: 0 0 8px light-dark(@dark-blue, @golden); + } + + button { + background: light-dark(transparent, @golden); + border: 1px solid light-dark(@dark-blue, @dark-blue); + color: light-dark(@dark-blue, @dark-blue); + outline: none; + box-shadow: none; + + &:hover { + background: light-dark(@light-black, @dark-blue); + color: light-dark(@dark-blue, @golden); + } + + &.glow { + animation: glow 0.75s infinite alternate; + } + + &:disabled { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + opacity: 0.6; + cursor: not-allowed; + + &:hover { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + } + } + + &.reverted { + background: light-dark(@dark-blue-10, @golden-10); + color: light-dark(@dark-blue, @golden); + border: 1px solid light-dark(@dark, transparent); + &:hover { + background: light-dark(transparent, @golden); + color: light-dark(@dark-blue, @dark-blue); + } + img { + border-radius: 3px; + } + } + } + .enriched-effect { display: flex; align-items: center; @@ -24,6 +93,24 @@ white-space: nowrap; } } + + .dice-roll .dice-formula, + .dice-roll .dice-total { + box-shadow: none; + border: none; + background: light-dark(@dark-blue-40, @golden-40); + color: light-dark(@dark-blue, @golden); + font-weight: 600; + align-content: center; + } + + .dice-roll .dice-formula { + height: 27px; + } + + .dice-roll .dice-total { + height: 34px; + } } } diff --git a/styles/less/ui/chat/theme-colorful.less b/styles/less/ui/chat/theme-colorful.less deleted file mode 100644 index 3de5b432..00000000 --- a/styles/less/ui/chat/theme-colorful.less +++ /dev/null @@ -1,195 +0,0 @@ -@import '../../utils/colors.less'; -@import '../../utils/spacing.less'; - -.theme-colorful { - .chat-message.duality { - border-color: black; - padding: 8px 0 0 0; - fieldset.daggerheart.chat { - border-top-width: 0; - display: contents; - legend { - &:before, - &:after { - display: none; - } - } - } - .message-header { - color: var(--color-light-3); - padding: 0 8px; - } - &.hope { - background: linear-gradient(0, rgba(165, 42, 42, 0.6) 40px, rgba(0, 0, 0, 0.6)); - } - &.fear { - background: linear-gradient(0, @fearBackgroundEnd, @fearBackgroundStart); - } - &.critical { - background: linear-gradient(0, @criticalBackgroundEnd, @criticalBackgroundStart); - } - .chat-message header { - color: var(--color-light-3); - } - > * { - padding: 0 8px; - } - .message-content { - .duality-modifiers, - .duality-result, - .dice-title { - display: flex; - } - .duality-modifiers { - display: flex; - gap: 2px; - margin-bottom: 4px; - flex-wrap: wrap; - .duality-modifier { - padding: 2px; - border-radius: 6px; - border: 1px solid; - background: var(--color-dark-6); - font-size: 12px; - white-space: nowrap; - } - } - .dice-flavor { - color: var(--color-light-1); - text-shadow: 0 0 1px black; - border-bottom: 1px solid; - display: flex; - align-items: end; - justify-content: space-between; - padding: 0 8px; - margin: 0 -8px 2px; - font-weight: unset; - } - .dice-result { - .duality-modifiers { - display: flex; // Default => display: none; - gap: 2px; - margin-bottom: 4px; - .duality-modifier { - padding: 2px; - border-radius: 6px; - border: 1px solid; - background: var(--color-dark-6); - font-size: 12px; - } - } - .dice-formula, - > .dice-total, - .part-header { - display: none; - } - .dice-tooltip { - grid-template-rows: 1fr; - .wrapper { - .tooltip-part { - display: flex; - align-items: end; - gap: 0.25rem; - .dice { - .dice-rolls { - margin-bottom: 0; - &.duality { - li { - display: flex; - align-items: center; - justify-content: center; - position: relative; - background: unset; - line-height: unset; - font-weight: unset; - } - } - } - } - .duality-modifier { - display: flex; - margin-bottom: 6px; - color: var(--color-light-1); - text-shadow: 0 0 1px black; - font-size: var(--font-size-16); - } - } - } - } - .target-selection { - label { - color: var(--color-light-1); - } - } - .target-section { - margin: 4px 0; - border: 2px solid; - margin-top: 5px; - .dice-total { - box-shadow: unset; - border: unset; - border-radius: unset; - font-size: var(--font-size-18); - } - } - .dice-actions { - justify-content: space-between; - &.duality-alone { - justify-content: end; - margin-top: -20px; - } - > * { - display: flex; - color: var(--color-light-1); - text-shadow: 0 0 1px black; - font-weight: bold; - background: var(--color-dark-1); - padding: 4px; - border-color: black; - min-height: unset; - height: 26px; - flex: unset; - margin: 0; - } - .duality-action { - border-radius: 0 6px 0 0; - margin-left: -8px; - &.duality-action-effect { - border-top-left-radius: 6px; - margin-left: initial; - } - } - .duality-result { - border-radius: 6px 0 0 0; - margin-right: -8px; - } - } - .duality-result { - display: flex; - color: var(--color-light-1); - text-shadow: 0 0 1px black; - font-weight: bold; - background: var(--color-dark-1); - padding: 4px; - border-color: black; - min-height: unset; - height: 26px; - flex: unset; - margin: 0; - margin-left: auto; - align-self: center; - border-radius: 6px; - } - } - } - button { - &.inner-button { - color: var(--color-light-1); - text-shadow: 0 0 1px black; - font-weight: bold; - background: var(--color-dark-1); - border-color: black; - } - } - } -} diff --git a/styles/less/ui/index.less b/styles/less/ui/index.less index 13e578b0..c2ad2b3b 100644 --- a/styles/less/ui/index.less +++ b/styles/less/ui/index.less @@ -1,6 +1,8 @@ +@import './chat/ability-use.less'; +@import './chat/action.less'; @import './chat/chat.less'; +@import './chat/downtime.less'; @import './chat/sheet.less'; -@import './chat/theme-colorful.less'; @import './combat-sidebar/combat-sidebar.less'; @import './combat-sidebar/combatant-controls.less'; @@ -15,4 +17,4 @@ @import './resources/resources.less'; -@import './settings/settings.less'; +@import './settings/settings.less'; \ No newline at end of file diff --git a/styles/less/utils/colors.less b/styles/less/utils/colors.less index ea4cdcb7..757fedfb 100755 --- a/styles/less/utils/colors.less +++ b/styles/less/utils/colors.less @@ -4,6 +4,21 @@ @golden: #f3c267; @golden-10: #f3c26710; @golden-40: #f3c26740; +@golden-bg: #f3c2671a; + +@chat-blue: #8f87ee; +@chat-blue-10: #8f87ee10; +@chat-blue-40: #8f87ee40; +@chat-blue-bg: #14142599; + +@chat-purple: #a778b1; +@chat-purple-10: #a778b110; +@chat-purple-40: #a778b140; +@chat-purple-bg: #2a152e99; + +@medium-red: #d04747; +@medium-red-10: #d0474710; +@medium-red-40: #d0474740; @dark-golden: #2b1d03; @dark-golden-80: #2b1d0380; diff --git a/templates/dialogs/dice-roll/costSelection.hbs b/templates/dialogs/dice-roll/costSelection.hbs index 3ece4cbf..12200989 100644 --- a/templates/dialogs/dice-roll/costSelection.hbs +++ b/templates/dialogs/dice-roll/costSelection.hbs @@ -8,7 +8,7 @@ - {{log @root}} + {{/if}} diff --git a/templates/ui/chat/ability-use.hbs b/templates/ui/chat/ability-use.hbs index 4ebaa293..30c5ebb9 100644 --- a/templates/ui/chat/ability-use.hbs +++ b/templates/ui/chat/ability-use.hbs @@ -1,9 +1,19 @@