diff --git a/daggerheart.mjs b/daggerheart.mjs index 77dad7e8..240d8704 100644 --- a/daggerheart.mjs +++ b/daggerheart.mjs @@ -32,6 +32,8 @@ CONFIG.Dice.daggerheart = { FateRoll: FateRoll }; +Object.assign(CONFIG.Dice.termTypes, dice.diceTypes); + CONFIG.Actor.documentClass = documents.DhpActor; CONFIG.Actor.dataModels = models.actors.config; CONFIG.Actor.collection = collections.DhActorCollection; diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 5fdefcbd..2d363471 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -200,6 +200,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio partContext.members[partId] = { ...data, + roll: data.roll, isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), key: partId, readyToRoll: Boolean(data.rollChoice), @@ -448,24 +449,19 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const { member, diceType } = button.dataset; const memberData = this.party.system.tagTeam.members[member]; - const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 2 : 4; - - const { parsedRoll, newRoll } = await game.system.api.dice.DualityRoll.reroll( - memberData.rollData, - dieIndex, - diceType, - false - ); - const rollData = parsedRoll.toJSON(); + const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 1 : 2; + const newRoll = game.system.api.dice.DualityRoll.fromData(memberData.rollData); + const dice = newRoll.dice[dieIndex]; + await dice.reroll(`/r1=${dice.total}`, { + liveRoll: { + roll: newRoll, + isReaction: true + } + }); + const rollData = newRoll.toJSON(); this.updatePartyData( { - [`system.tagTeam.members.${member}.rollData`]: { - ...rollData, - options: { - ...rollData.options, - roll: newRoll - } - } + [`system.tagTeam.members.${member}.rollData`]: rollData }, this.getUpdatingParts(button) ); @@ -700,7 +696,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const error = this.checkInitiatorHopeError(this.party.system.tagTeam.initiator); if (error) return error; - const mainRoll = (await this.getJoinedRoll()).rollData; + const joinedRoll = await this.getJoinedRoll(); + const mainRoll = joinedRoll.rollData; + const finalRoll = foundry.utils.deepClone(joinedRoll.roll); const mainActor = this.party.system.partyMembers.find(x => x.uuid === mainRoll.options.source.actor); mainRoll.options.title = game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.chatMessageRollTitle'); @@ -711,7 +709,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio title: game.i18n.localize('DAGGERHEART.APPLICATIONS.TagTeamSelect.title'), speaker: cls.getSpeaker({ actor: mainActor }), system: mainRoll.options, - rolls: [mainRoll], + rolls: [JSON.stringify(joinedRoll.roll)], sound: null, flags: { core: { RollTable: true } } }; @@ -723,7 +721,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const fearUpdate = { key: 'fear', value: null, total: null, enabled: true }; for (let memberId in tagTeamData.members) { const resourceUpdates = []; - const rollGivesHope = mainRoll.options.roll.isCritical || mainRoll.options.roll.result.duality === 1; + const rollGivesHope = finalRoll.isCritical || finalRoll.withHope; if (memberId === tagTeamData.initiator.memberId) { const value = tagTeamData.initiator.cost ? rollGivesHope @@ -734,9 +732,8 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } else if (rollGivesHope) { resourceUpdates.push({ key: 'hope', value: 1, total: -1, enabled: true }); } - if (mainRoll.options.roll.isCritical) - resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true }); - if (mainRoll.options.roll.result.duality === -1) { + if (finalRoll.isCritical) resourceUpdates.push({ key: 'stress', value: -1, total: 1, enabled: true }); + if (finalRoll.withFear) { fearUpdate.value = fearUpdate.value === null ? 1 : fearUpdate.value + 1; fearUpdate.total = fearUpdate.total === null ? -1 : fearUpdate.total - 1; } diff --git a/module/applications/ui/chatLog.mjs b/module/applications/ui/chatLog.mjs index 82300d03..8cbacb09 100644 --- a/module/applications/ui/chatLog.mjs +++ b/module/applications/ui/chatLog.mjs @@ -256,7 +256,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo action.use(event); } - async rerollEvent(event, message) { + async rerollEvent(event, messageData) { event.stopPropagation(); if (!event.shiftKey) { const confirmed = await foundry.applications.api.DialogV2.confirm({ @@ -268,6 +268,7 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo if (!confirmed) return; } + const message = game.messages.get(messageData._id); const target = event.target.closest('[data-die-index]'); if (target.dataset.type === 'damage') { @@ -290,27 +291,16 @@ export default class DhpChatLog extends foundry.applications.sidebar.tabs.ChatLo } }); } else { - 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' - ]; - - if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); - - const { newRoll, parsedRoll } = await rollClass.reroll( - originalRoll_parsed, - target.dataset.dieIndex, - target.dataset.type - ); - - await game.messages.get(message._id).update({ - 'system.roll': newRoll, - 'rolls': [parsedRoll] + const rerollDice = message.system.roll.dice[target.dataset.dieIndex]; + await rerollDice.reroll(`/r1=${rerollDice.total}`, { + liveRoll: { + roll: message.system.roll, + actor: message.system.actionActor, + isReaction: message.system.roll.options.actionType === 'reaction' + } + }); + await message.update({ + rolls: [message.system.roll.toJSON()] }); } } diff --git a/module/data/chat-message/actorRoll.mjs b/module/data/chat-message/actorRoll.mjs index 1ea7ff93..e601f86d 100644 --- a/module/data/chat-message/actorRoll.mjs +++ b/module/data/chat-message/actorRoll.mjs @@ -32,7 +32,6 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { return { title: new fields.StringField(), actionDescription: new fields.HTMLField(), - roll: new fields.ObjectField(), targets: targetsField(), hasRoll: new fields.BooleanField({ initial: false }), hasDamage: new fields.BooleanField({ initial: false }), @@ -55,6 +54,16 @@ export default class DHActorRoll extends foundry.abstract.TypeDataModel { }; } + get roll() { + if (this.parent.type === 'dualityRoll') + return this.parent.rolls.find(x => x instanceof game.system.api.dice.DualityRoll); + + if (this.parent.type === 'fateRoll') + return this.parent.rolls.find(x => x instanceof game.system.api.dice.FateRoll); + + return null; + } + get actionActor() { if (!this.source.actor) return null; return fromUuidSync(this.source.actor); diff --git a/module/dice/_module.mjs b/module/dice/_module.mjs index b9339d87..e1206f82 100644 --- a/module/dice/_module.mjs +++ b/module/dice/_module.mjs @@ -4,3 +4,4 @@ export { default as DamageRoll } from './damageRoll.mjs'; export { default as DHRoll } from './dhRoll.mjs'; export { default as DualityRoll } from './dualityRoll.mjs'; export { default as FateRoll } from './fateRoll.mjs'; +export { diceTypes } from './die/_module.mjs'; diff --git a/module/dice/d20Roll.mjs b/module/dice/d20Roll.mjs index f117ff65..49db18cb 100644 --- a/module/dice/d20Roll.mjs +++ b/module/dice/d20Roll.mjs @@ -217,49 +217,11 @@ export default class D20Roll extends DHRoll { results: d.results }; }); - data.modifierTotal = this.calculateTotalModifiers(roll); + data.modifierTotal = roll.modifierTotal; return data; } resetFormula() { return (this._formula = this.constructor.getFormula(this.terms)); } - - static async reroll(rollString, _target, message) { - let parsedRoll = game.system.api.dice.D20Roll.fromData(rollString); - parsedRoll = await parsedRoll.reroll(); - const newRoll = game.system.api.dice.D20Roll.postEvaluate(parsedRoll, { - targets: message.system.targets, - roll: { - advantage: message.system.roll.advantage?.type, - difficulty: message.system.roll.difficulty ? Number(message.system.roll.difficulty) : null - } - }); - - if (game.modules.get('dice-so-nice')?.active) { - await game.dice3d.showForRoll(parsedRoll, game.user, true); - } - - const rerolled = { - any: true, - rerolls: [ - ...(message.system.roll.dice[0].rerolled?.rerolls?.length > 0 - ? [message.system.roll.dice[0].rerolled?.rerolls] - : []), - rollString.terms[0].results - ] - }; - return { - newRoll: { - ...newRoll, - dice: [ - { - ...newRoll.dice[0], - rerolled: rerolled - } - ] - }, - parsedRoll - }; - } } diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index 3310b9ca..e4a34bd4 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -12,6 +12,10 @@ export default class DHRoll extends Roll { return game.i18n.localize('DAGGERHEART.GENERAL.Roll.basic'); } + get modifierTotal() { + return this.constructor.calculateTotalModifiers(this); + } + static messageType = 'adversaryRoll'; static CHAT_TEMPLATE = 'systems/daggerheart/templates/ui/chat/roll.hbs'; @@ -138,6 +142,7 @@ export default class DHRoll extends Roll { const chatData = await this._prepareChatRenderContext({ flavor, isPrivate, ...options }); return foundry.applications.handlebars.renderTemplate(template, { ...chatData, + roll: this, parent: chatData.parent, targetMode: chatData.targetMode, metagamingSettings @@ -241,16 +246,21 @@ export default class DHRoll extends Roll { return (this._formula = this.constructor.getFormula(this.terms)); } + /** + * Calculate total modifiers of any rolls, including non-dh rolls. + * This exists because damage rolls still may receive base roll classes + */ static calculateTotalModifiers(roll) { let modifierTotal = 0; for (let i = 0; i < roll.terms.length; i++) { - if ( - roll.terms[i] instanceof foundry.dice.terms.NumericTerm && - !!roll.terms[i - 1] && - roll.terms[i - 1] instanceof foundry.dice.terms.OperatorTerm - ) - modifierTotal += Number(`${roll.terms[i - 1].operator}${roll.terms[i].total}`); + if (!roll.terms[i].isDeterministic) continue; + const termTotal = roll.terms[i].total; + if (typeof termTotal === 'number') { + const multiplier = roll.terms[i - 1]?.operator === " - " ? -1 : 1; + modifierTotal += multiplier * termTotal; + } } + return modifierTotal; } diff --git a/module/dice/die/_module.mjs b/module/dice/die/_module.mjs new file mode 100644 index 00000000..ed892f6a --- /dev/null +++ b/module/dice/die/_module.mjs @@ -0,0 +1,9 @@ +import DualityDie from './dualityDie.mjs'; +import AdvantageDie from './advantageDie.mjs'; +import DisadvantageDie from './disadvantageDie.mjs'; + +export const diceTypes = { + DualityDie, + AdvantageDie, + DisadvantageDie +}; diff --git a/module/dice/die/advantageDie.mjs b/module/dice/die/advantageDie.mjs new file mode 100644 index 00000000..9c2f0b03 --- /dev/null +++ b/module/dice/die/advantageDie.mjs @@ -0,0 +1,7 @@ +export default class AdvantageDie extends foundry.dice.terms.Die { + constructor(options) { + super(options); + + this.modifiers = []; + } +} diff --git a/module/dice/die/disadvantageDie.mjs b/module/dice/die/disadvantageDie.mjs new file mode 100644 index 00000000..f56ebe96 --- /dev/null +++ b/module/dice/die/disadvantageDie.mjs @@ -0,0 +1,7 @@ +export default class DisadvantageDie extends foundry.dice.terms.Die { + constructor(options) { + super(options); + + this.modifiers = []; + } +} diff --git a/module/dice/die/dualityDie.mjs b/module/dice/die/dualityDie.mjs new file mode 100644 index 00000000..e9deb77f --- /dev/null +++ b/module/dice/die/dualityDie.mjs @@ -0,0 +1,62 @@ +import { ResourceUpdateMap } from '../../data/action/baseAction.mjs'; + +export default class DualityDie extends foundry.dice.terms.Die { + constructor(options) { + super(options); + + this.modifiers = []; + } + + #getDualityState(roll) { + if (!roll) return null; + return roll.withHope ? 1 : roll.withFear ? -1 : 0; + } + + #updateResources(oldDuality, newDuality, actor) { + const { hopeFear } = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.Automation); + if (game.user.isGM ? !hopeFear.gm : !hopeFear.players) return; + + const updates = []; + const hope = (newDuality >= 0 ? 1 : 0) - (oldDuality >= 0 ? 1 : 0); + const stress = (newDuality === 0 ? 1 : 0) - (oldDuality === 0 ? 1 : 0); + const fear = (newDuality === -1 ? 1 : 0) - (oldDuality === -1 ? 1 : 0); + + if (hope !== 0) updates.push({ key: 'hope', value: hope, total: -1 * hope, enabled: true }); + if (stress !== 0) updates.push({ key: 'stress', value: -1 * stress, total: stress, enabled: true }); + if (fear !== 0) updates.push({ key: 'fear', value: fear, total: -1 * fear, enabled: true }); + + const resourceUpdates = new ResourceUpdateMap(actor); + resourceUpdates.addResources(updates); + resourceUpdates.updateResources(); + } + + async reroll(modifier, options) { + const oldDuality = this.#getDualityState(options.liveRoll.roll); + await super.reroll(modifier, options); + + if (options?.liveRoll) { + /* Can't currently test since DiceSoNice is not v14. Might need to set the appearance earlier if a roll is triggered by super.reroll */ + if (game.modules.get('dice-so-nice')?.active) { + const diceSoNiceRoll = { + _evaluated: true, + dice: [this], + options: { appearance: {} } + }; + + const preset = await getDiceSoNicePreset(diceSoNice[key], faces); + diceSoNiceRoll.dice[0].options.appearance = preset.appearance; + diceSoNiceRoll.dice[0].options.modelFile = preset.modelFile; + + await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); + } else { + foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); + } + + await options.liveRoll.roll._evaluate(); + if (options.liveRoll.isReaction) return; + + const newDuality = this.#getDualityState(options.liveRoll.roll); + this.#updateResources(oldDuality, newDuality, options.liveRoll.actor); + } + } +} diff --git a/module/dice/dualityRoll.mjs b/module/dice/dualityRoll.mjs index 84e0b493..bc381f07 100644 --- a/module/dice/dualityRoll.mjs +++ b/module/dice/dualityRoll.mjs @@ -1,8 +1,6 @@ import D20RollDialog from '../applications/dialogs/d20RollDialog.mjs'; import D20Roll from './d20Roll.mjs'; import { parseRallyDice, setDiceSoNiceForDualityRoll } from '../helpers/utils.mjs'; -import { getDiceSoNicePresets } from '../config/generalConfig.mjs'; -import { ResourceUpdateMap } from '../data/action/baseAction.mjs'; export default class DualityRoll extends D20Roll { _advantageFaces = 6; @@ -26,27 +24,31 @@ export default class DualityRoll extends D20Roll { } get dHope() { - if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); + if (!(this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); return this.dice[0]; } set dHope(faces) { - if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - this.dice[0].faces = this.getFaces(faces); + // TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dHope.faces + this.dHope.faces = this.getFaces(faces); } get dFear() { - if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice(); + if (!(this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie)) this.createBaseDice(); return this.dice[1]; } set dFear(faces) { - if (!(this.dice[1] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - this.dice[1].faces = this.getFaces(faces); + // TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dFear.faces + this.dFear.faces = this.getFaces(faces); } get dAdvantage() { - return this.dice[2]; + return this.dice[2] instanceof game.system.api.dice.diceTypes.AdvantageDie ? this.dice[2] : null; + } + + get dDisadvantage() { + return this.dice[2] instanceof game.system.api.dice.diceTypes.DisadvantageDie ? this.dice[2] : null; } get advantageFaces() { @@ -65,6 +67,11 @@ export default class DualityRoll extends D20Roll { this._advantageNumber = Number(value); } + get extraDice() { + const { DualityDie, AdvantageDie, DisadvantageDie } = game.system.api.dice.diceTypes; + return this.dice.filter(x => ![DualityDie, AdvantageDie, DisadvantageDie].some(die => x instanceof die)); + } + setRallyChoices() { return this.data?.parent?.appliedEffects.reduce((a, c) => { const change = c.system.changes.find(ch => ch.key === 'system.bonuses.rally'); @@ -118,22 +125,28 @@ export default class DualityRoll extends D20Roll { /** @inheritDoc */ static fromData(data) { - data.terms[0].class = foundry.dice.terms.Die.name; - data.terms[2].class = foundry.dice.terms.Die.name; + data.terms[0].class = 'DualityDie'; + data.terms[2].class = 'DualityDie'; + if (data.options.roll.advantage?.type && data.terms[4]?.faces) { + data.terms[4].class = data.options.roll.advantage.type === 1 ? 'AdvantageDie' : 'DisadvantageDie'; + } return super.fromData(data); } createBaseDice() { - if (this.dice[0] instanceof foundry.dice.terms.Die && this.dice[1] instanceof foundry.dice.terms.Die) { + if ( + this.dice[0] instanceof game.system.api.dice.diceTypes.DualityDie && + this.dice[1] instanceof game.system.api.dice.diceTypes.DualityDie + ) { this.terms = [this.terms[0], this.terms[1], this.terms[2]]; return; } - this.terms[0] = new foundry.dice.terms.Die({ + this.terms[0] = new game.system.api.dice.diceTypes.DualityDie({ faces: this.data.rules.dualityRoll?.defaultHopeDice ?? 12 }); this.terms[1] = new foundry.dice.terms.OperatorTerm({ operator: '+' }); - this.terms[2] = new foundry.dice.terms.Die({ + this.terms[2] = new game.system.api.dice.diceTypes.DualityDie({ faces: this.data.rules.dualityRoll?.defaultFearDice ?? 12 }); } @@ -371,63 +384,4 @@ export default class DualityRoll extends D20Roll { if (currentCombatant?.actorId == config.data.id) ui.combat.setCombatantSpotlight(currentCombatant.id); } } - - static async reroll(rollBase, dieIndex, diceType, updateResources = true) { - let parsedRoll = game.system.api.dice.DualityRoll.fromData({ ...rollBase, evaluated: false }); - const term = parsedRoll.terms[dieIndex]; - await term.reroll(`/r1=${term.total}`); - const result = await parsedRoll.evaluate(); - - 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 = await getDiceSoNicePresets(`d${term._faces}`, `d${term._faces}`); - if (diceSoNicePresets[diceType]) { - diceSoNiceRoll.dice[0].options = diceSoNicePresets[diceType]; - } - - await game.dice3d.showForRoll(diceSoNiceRoll, game.user, true); - } else { - foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); - } - - const newRoll = game.system.api.dice.DualityRoll.postEvaluate(parsedRoll, { - targets: parsedRoll.options.targets ?? [], - roll: { - advantage: parsedRoll.options.roll.advantage?.type, - difficulty: parsedRoll.options.roll.difficulty ? Number(parsedRoll.options.roll.difficulty) : null - } - }); - - const extraIndex = newRoll.advantage ? 3 : 2; - newRoll.extra = newRoll.extra.slice(extraIndex); - - const actor = parsedRoll.options.source.actor - ? await foundry.utils.fromUuid(parsedRoll.options.source.actor) - : null; - const config = { - source: { actor: parsedRoll.options.source.actor ?? '' }, - targets: parsedRoll.targets, - roll: newRoll, - rerolledRoll: parsedRoll.options.roll, - resourceUpdates: new ResourceUpdateMap(actor) - }; - - if (updateResources) { - await DualityRoll.addDualityResourceUpdates(config); - await config.resourceUpdates.updateResources(); - } - - return { newRoll, parsedRoll }; - } } diff --git a/module/dice/fateRoll.mjs b/module/dice/fateRoll.mjs index 418c8465..ec03715a 100644 --- a/module/dice/fateRoll.mjs +++ b/module/dice/fateRoll.mjs @@ -21,8 +21,8 @@ export default class FateRoll extends D20Roll { } set dHope(faces) { - if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - this.dice[0].faces = this.getFaces(faces); + // TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dHope.faces + this.dHope.faces = this.getFaces(faces); } get dFear() { @@ -31,8 +31,8 @@ export default class FateRoll extends D20Roll { } set dFear(faces) { - if (!(this.dice[0] instanceof foundry.dice.terms.Die)) this.createBaseDice(); - this.dice[0].faces = this.getFaces(faces); + // TODO this should not be asymmetrical with the getter. updateRollConfiguration() should use dFear.faces + this.dFear.faces = this.getFaces(faces); } get isCritical() { @@ -43,6 +43,22 @@ export default class FateRoll extends D20Roll { return this.data.fateType; } + get withHope() { + if (!this._evaluatedl) return; + return this.dHope.total >= this.dFear.total; + } + + get withFear() { + if (!this._evaluated) return; + return this.dHope.total < this.dFear.total; + } + + get totalLabel() { + const label = this.withHope ? 'DAGGERHEART.GENERAL.hope' : 'DAGGERHEART.GENERAL.fear'; + + return game.i18n.localize(label); + } + static getHooks(hooks) { return [...(hooks ?? []), 'Fate']; } diff --git a/module/documents/chatMessage.mjs b/module/documents/chatMessage.mjs index 8b094678..307677bb 100644 --- a/module/documents/chatMessage.mjs +++ b/module/documents/chatMessage.mjs @@ -1,4 +1,4 @@ -import { emitAsGM, GMUpdateEvent, RefreshType, socketEvent } from '../systemRegistration/socket.mjs'; +import { emitAsGM, GMUpdateEvent } from '../systemRegistration/socket.mjs'; export default class DhpChatMessage extends foundry.documents.ChatMessage { targetHook = null; @@ -78,25 +78,14 @@ export default class DhpChatMessage extends foundry.documents.ChatMessage { if (this.isContentVisible) { if (this.type === 'dualityRoll') { html.classList.add('duality'); - switch (this.system.roll?.result?.duality) { - case 1: - html.classList.add('hope'); - break; - case -1: - html.classList.add('fear'); - break; - default: - html.classList.add('critical'); - break; - } + if (this.system.roll.withHope) html.classList.add('hope'); + else if (this.system.roll.withFear) html.classList.add('fear'); + else html.classList.add('critical'); } if (this.type === 'fateRoll') { html.classList.add('fate'); - if (this.system.roll?.fate.fateDie == 'Hope') { - html.classList.add('hope'); - } - if (this.system.roll?.fate.fateDie == 'Fear') { - html.classList.add('fear'); + if (this.system.roll?.fateDie) { + html.classList.add(this.system.roll.fateDie.toLowerCase()); } } diff --git a/styles/less/ui/chat/chat.less b/styles/less/ui/chat/chat.less index e9ef9147..db6dceb9 100644 --- a/styles/less/ui/chat/chat.less +++ b/styles/less/ui/chat/chat.less @@ -384,6 +384,15 @@ justify-content: center; width: 15px; } + &.has-minus:before { + content: '-'; + font-size: var(--font-size-20); + grid-area: c; + display: flex; + align-items: center; + justify-content: center; + width: 15px; + } } } diff --git a/templates/dialogs/dice-roll/rollSelection.hbs b/templates/dialogs/dice-roll/rollSelection.hbs index 4451160b..64a3cdcb 100644 --- a/templates/dialogs/dice-roll/rollSelection.hbs +++ b/templates/dialogs/dice-roll/rollSelection.hbs @@ -53,14 +53,14 @@ {{#if @root.advantage}} {{#if (eq @root.advantage 1)}}