From cc822856e5bd1ba23d8b076388aaa9fe9b5c193d Mon Sep 17 00:00:00 2001 From: Carlos Fernandez Date: Sun, 26 Apr 2026 04:43:10 -0400 Subject: [PATCH] [Feature] Redesign group roll dialog (#1824) * Redesign group roll dialog * Style and restore aid modifiers * Move successful buttons to inner result * Localize and finish dialog * Remove empty line * Fix error and remove old styles * Make icon pop a tiny bit better * Fix advantage/disadvantage --- gulpfile.js | 2 +- lang/en.json | 15 +- .../applications/dialogs/groupRollDialog.mjs | 182 +++++------- module/data/groupRollData.mjs | 2 +- .../dialog/group-roll-dialog/_common.less | 46 +++ .../less/dialog/group-roll-dialog/index.less | 8 + .../group-roll-dialog/initialization.less | 95 +++--- .../less/dialog/group-roll-dialog/leader.less | 35 --- .../less/dialog/group-roll-dialog/main.less | 273 ++++++++++++++++++ .../less/dialog/group-roll-dialog/sheet.less | 265 ----------------- styles/less/dialog/group-roll/group-roll.less | 50 ---- styles/less/dialog/index.less | 6 +- styles/less/global/elements.less | 2 +- templates/dialogs/group-roll/group-roll.hbs | 84 ------ .../dialogs/groupRollDialog/groupRoll.hbs | 20 -- .../groupRollDialog/groupRollMember.hbs | 85 ------ .../groupRollDialog/initialization.hbs | 47 +-- templates/dialogs/groupRollDialog/leader.hbs | 73 ----- templates/dialogs/groupRollDialog/main.hbs | 15 + .../groupRollDialog/{ => parts}/footer.hbs | 5 +- .../dialogs/groupRollDialog/parts/member.hbs | 95 ++++++ .../dialogs/groupRollDialog/parts/result.hbs | 30 ++ 22 files changed, 640 insertions(+), 795 deletions(-) create mode 100644 styles/less/dialog/group-roll-dialog/_common.less create mode 100644 styles/less/dialog/group-roll-dialog/index.less delete mode 100644 styles/less/dialog/group-roll-dialog/leader.less create mode 100644 styles/less/dialog/group-roll-dialog/main.less delete mode 100644 styles/less/dialog/group-roll-dialog/sheet.less delete mode 100644 styles/less/dialog/group-roll/group-roll.less delete mode 100644 templates/dialogs/group-roll/group-roll.hbs delete mode 100644 templates/dialogs/groupRollDialog/groupRoll.hbs delete mode 100644 templates/dialogs/groupRollDialog/groupRollMember.hbs delete mode 100644 templates/dialogs/groupRollDialog/leader.hbs create mode 100644 templates/dialogs/groupRollDialog/main.hbs rename templates/dialogs/groupRollDialog/{ => parts}/footer.hbs (62%) create mode 100644 templates/dialogs/groupRollDialog/parts/member.hbs create mode 100644 templates/dialogs/groupRollDialog/parts/result.hbs diff --git a/gulpfile.js b/gulpfile.js index 45479a5c..1a81f5ae 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -3,7 +3,7 @@ var gulp = require('gulp'); var less = require('gulp-less'); gulp.task('less', function (cb) { - gulp.src('styles/daggerheart.less').pipe(less()).pipe(gulp.dest('styles')); + gulp.src('styles/daggerheart.less').pipe(less()).on('error', console.error.bind(console)).pipe(gulp.dest('styles')); cb(); }); diff --git a/lang/en.json b/lang/en.json index 99a75f83..b4b1410e 100755 --- a/lang/en.json +++ b/lang/en.json @@ -758,15 +758,20 @@ } }, "GroupRollSelect": { - "title": "Group Roll", - "aidingCharacters": "Aiding Characters", + "cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too.", + "cancelConfirmTitle": "Cancel Group Roll", + "initializationTitle": "Character Selection", + "finishGroupRoll": "Finish Group Roll", "leader": "Leader", "leaderRoll": "Leader Roll", + "members": "Members", "openDialogForAll": "Open Dialog For All", + "removeRoll": "Remove Roll", + "resultsHint": "Results will appear when characters roll", + "selectLeaderHint": "Select one Character to be the leader", + "selectParticipantsHint": "Select one Character to be the leader", "startGroupRoll": "Start Group Roll", - "finishGroupRoll": "Finish Group Roll", - "cancelConfirmTitle": "Cancel Group Roll", - "cancelConfirmText": "Are you sure you want to cancel the Group Roll? This will close it for all other players too." + "title": "Group Roll" }, "TokenConfig": { "actorSizeUsed": "Actor size is set, determining the dimensions" diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index a47dd0a8..df03a061 100644 --- a/module/applications/dialogs/groupRollDialog.mjs +++ b/module/applications/dialogs/groupRollDialog.mjs @@ -37,17 +37,17 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat tag: 'form', id: 'GroupRollDialog', classes: ['daggerheart', 'views', 'dh-style', 'dialog', 'group-roll-dialog'], - position: { width: 550, height: 'auto' }, + position: { width: 390, height: 'auto' }, + window: { + icon: 'fa-solid fa-users' + }, actions: { toggleSelectMember: this.#toggleSelectMember, startGroupRoll: this.#startGroupRoll, makeRoll: this.#makeRoll, removeRoll: this.#removeRoll, rerollDice: this.#rerollDice, - makeLeaderRoll: this.#makeLeaderRoll, - removeLeaderRoll: this.#removeLeaderRoll, - rerollLeaderDice: this.#rerollLeaderDice, - markSuccessfull: this.#markSuccessfull, + markSuccessful: this.#markSuccessful, cancelRoll: this.#onCancelRoll, finishRoll: this.#finishRoll }, @@ -59,17 +59,21 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat id: 'initialization', template: 'systems/daggerheart/templates/dialogs/groupRollDialog/initialization.hbs' }, + main: { + id: 'main', + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/main.hbs' + }, leader: { id: 'leader', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/leader.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/member.hbs' }, - groupRoll: { - id: 'groupRoll', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRoll.hbs' + result: { + id: 'result', + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/result.hbs' }, footer: { id: 'footer', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/footer.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/footer.hbs' } }; @@ -89,40 +93,14 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } _configureRenderParts(options) { - const { initialization, leader, groupRoll, footer } = super._configureRenderParts(options); - const augmentedParts = { initialization }; + const parts = super._configureRenderParts(options); for (const memberKey of Object.keys(this.party.system.groupRoll.aidingCharacters)) { - augmentedParts[memberKey] = { + parts[memberKey] = { id: memberKey, - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRollMember.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/member.hbs' }; } - - augmentedParts.leader = leader; - augmentedParts.groupRoll = groupRoll; - augmentedParts.footer = footer; - - return augmentedParts; - } - - /**@inheritdoc */ - async _onRender(context, options) { - await super._onRender(context, options); - - if (this.element.querySelector('.team-container')) return; - - if (this.tabGroups.application !== this.constructor.PARTS.initialization.id) { - const initializationPart = this.element.querySelector('.initialization-container'); - initializationPart.insertAdjacentHTML('afterend', '
'); - initializationPart.insertAdjacentHTML( - 'afterend', - `
${game.i18n.localize('DAGGERHEART.APPLICATIONS.GroupRollSelect.aidingCharacters')}
` - ); - - const teamContainer = this.element.querySelector('.team-container'); - for (const memberContainer of this.element.querySelectorAll('.team-member-container')) - teamContainer.appendChild(memberContainer); - } + return parts; } async _prepareContext(_options) { @@ -134,6 +112,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat context.data = this.party.system.groupRoll; context.traitOptions = CONFIG.DH.ACTOR.abilities; context.members = {}; + context.aidKeys = Object.keys(this.party.system.groupRoll.aidingCharacters); context.allHaveRolled = Object.keys(context.data.participants).every(key => { const data = context.data.participants[key]; return Boolean(data.rollData); @@ -145,6 +124,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat async _preparePartContext(partId, context, options) { const partContext = await super._preparePartContext(partId, context, options); partContext.partId = partId; + partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader); switch (partId) { case 'initialization': @@ -162,19 +142,14 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat partContext.canStartGroupRoll = selectedMembers.length > 1 && this.leader?.memberId; partContext.openForAllPlayers = this.openForAllPlayers; break; - case 'leader': - partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader); - break; - case 'groupRoll': + case 'result': const leader = this.party.system.groupRoll.leader; partContext.hasRolled = leader?.rollData || - Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some( - x => x.successfull !== null - ); + Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some(x => x.successful !== null); const { modifierTotal, modifiers } = Object.values(this.party.system.groupRoll.aidingCharacters).reduce( (acc, curr) => { - const modifier = curr.successfull === true ? 1 : curr.successfull === false ? -1 : null; + const modifier = curr.successful === true ? 1 : curr.successful === false ? -1 : null; if (modifier) { acc.modifierTotal += modifier; acc.modifiers.push(modifier); @@ -200,7 +175,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat case 'footer': partContext.canFinishRoll = Boolean(this.party.system.groupRoll.leader?.rollData) && - Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successfull !== null); + Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successful !== null); break; } @@ -216,20 +191,42 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat if (!data) return {}; const actor = game.actors.get(data.id); + const isLeader = data === this.party.system.groupRoll.leader; + + const roll = data.roll; + const withTypeSuffix = !roll ? null : roll.isCritical ? 'criticalShort' : roll.withHope ? 'hope' : 'fear'; + const thing = withTypeSuffix ? _loc(`DAGGERHEART.GENERAL.${withTypeSuffix}`) : null; return { ...data, + type: isLeader ? 'leader' : 'aid', + basePath: isLeader ? 'system.groupRoll.leader' : `system.groupRoll.aidingCharacters.${data.id}`, + rollChoiceLabel: _loc(CONFIG.DH.ACTOR.abilities[data.rollChoice]?.label), roll: data.roll, - isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), + isEditable: actor?.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), key: partId, readyToRoll: Boolean(data.rollChoice), - hasRolled: Boolean(data.rollData) + hasRolled: Boolean(data.rollData), + modifier: data.successful ? 1 : data.successful === false ? -1 : 0, + withLabelShort: thing ? _loc('DAGGERHEART.GENERAL.withThing', { thing }) : null }; } + #getCharacterDataById(id) { + if (!id) return null; + + const groupRoll = this.party.system.groupRoll; + if (id === 'leader' || id === groupRoll.leader?.id) { + return { data: groupRoll.leader, basePath: 'system.groupRoll.leader' }; + } else if (id in groupRoll.aidingCharacters) { + return { data: groupRoll.aidingCharacters[id], basePath: `system.groupRoll.aidingCharacters.${id}` }; + } + + return null; + } + static async updateData(event, _, formData) { const partyData = foundry.utils.expandObject(formData.object); - this.updatePartyData(partyData, this.getUpdatingParts(event.target)); } @@ -256,16 +253,16 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } getUpdatingParts(target) { - const { initialization, leader, groupRoll, footer } = this.constructor.PARTS; + const { initialization, leader, result, footer } = this.constructor.PARTS; const isInitialization = this.tabGroups.application === initialization.id; - const updatingMember = target.closest('.team-member-container')?.dataset?.memberKey; - const updatingLeader = target.closest('.main-character-outer-container'); + const updatingMember = target.closest('.member-roll-container.aid')?.dataset?.memberKey; + const updatingLeader = target.closest('.member-roll-container.leader'); return [ ...(isInitialization ? [initialization.id] : []), ...(updatingMember ? [updatingMember] : []), ...(updatingLeader ? [leader.id] : []), - ...(!isInitialization ? [groupRoll.id, footer.id] : []) + ...(!isInitialization ? [result.id, footer.id] : []) ]; } @@ -304,6 +301,9 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat static #toggleSelectMember(_, button) { const member = this.partyMembers.find(x => x.id === button.dataset.id); member.selected = !member.selected; + if (this.leader?.memberId === member.id) { + this.leader = null; + } this.render(); } @@ -343,11 +343,14 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } //#endregion - async makeRoll(button, characterData, path) { - const actor = game.actors.find(x => x.id === characterData.id); + /** @this GroupRollDialog */ + static async #makeRoll(_event, button) { + const member = button.closest('[data-member-key]').dataset.memberKey; + const { data, basePath } = this.#getCharacterDataById(member); + const actor = game.actors.find(x => x.id === data.id); if (!actor) return; - const result = await actor.rollTrait(characterData.rollChoice, { + const result = await actor.rollTrait(data.rollChoice, { skips: { createMessage: true, resources: true, @@ -356,53 +359,40 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat }); if (!result) return; + // todo: move logic to actor.rollTrait() or actor.diceRoll() if (!game.modules.get('dice-so-nice')?.active) foundry.audio.AudioHelper.play({ src: CONFIG.sounds.dice }); const rollData = result.messageRoll.toJSON(); delete rollData.options.messageRoll; this.updatePartyData( { - [path]: rollData + [basePath]: { rollData, successful: null } }, this.getUpdatingParts(button) ); } - static async #makeRoll(_event, button) { - const { member } = button.dataset; - const character = this.party.system.groupRoll.aidingCharacters[member]; - this.makeRoll(button, character, `system.groupRoll.aidingCharacters.${member}.rollData`); - } - - static async #makeLeaderRoll(_event, button) { - const character = this.party.system.groupRoll.leader; - this.makeRoll(button, character, 'system.groupRoll.leader.rollData'); - } - - async removeRoll(button, path) { + /** @this GroupRollDialog */ + static async #removeRoll(_event, button) { + const member = button.closest('[data-member-key]').dataset.memberKey; + const { basePath } = this.#getCharacterDataById(member); this.updatePartyData( { - [path]: { + [basePath]: { rollData: null, rollChoice: null, selected: false, - successfull: null + successful: null } }, this.getUpdatingParts(button) ); } - static async #removeRoll(_event, button) { - this.removeRoll(button, `system.groupRoll.aidingCharacters.${button.dataset.member}`); - } - - static async #removeLeaderRoll(_event, button) { - this.removeRoll(button, 'system.groupRoll.leader'); - } - - async rerollDice(button, data, path) { + /** @this GroupRollDialog */ + static async #rerollDice(_, button) { const { diceType } = button.dataset; + const { data, basePath } = this.#getCharacterDataById(button.dataset.member); const dieIndex = diceType === 'hope' ? 0 : diceType === 'fear' ? 1 : 2; const newRoll = game.system.api.dice.DualityRoll.fromData(data.rollData); @@ -416,31 +406,19 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat const rollData = newRoll.toJSON(); this.updatePartyData( { - [path]: rollData + [`${basePath}.rollData`]: rollData }, this.getUpdatingParts(button) ); } - static async #rerollDice(_, button) { - const { member } = button.dataset; - this.rerollDice( - button, - this.party.system.groupRoll.aidingCharacters[member], - `system.groupRoll.aidingCharacters.${member}.rollData` - ); - } - - static async #rerollLeaderDice(_, button) { - this.rerollDice(button, this.party.system.groupRoll.leader, `system.groupRoll.leader.rollData`); - } - - static #markSuccessfull(_event, button) { - const previousValue = this.party.system.groupRoll.aidingCharacters[button.dataset.member].successfull; - const newValue = Boolean(button.dataset.successfull === 'true'); + static #markSuccessful(_event, button) { + const memberKey = button.closest('[data-member-key]').dataset.memberKey; + const previousValue = this.party.system.groupRoll.aidingCharacters[memberKey].successful; + const newValue = Boolean(button.dataset.success === 'true'); this.updatePartyData( { - [`system.groupRoll.aidingCharacters.${button.dataset.member}.successfull`]: + [`system.groupRoll.aidingCharacters.${memberKey}.successful`]: previousValue === newValue ? null : newValue }, this.getUpdatingParts(button) @@ -484,7 +462,7 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat static async #finishRoll() { const totalRoll = this.party.system.groupRoll.leader.roll; for (const character of Object.values(this.party.system.groupRoll.aidingCharacters)) { - totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successfull ? '+' : '-' })); + totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successful ? '+' : '-' })); totalRoll.terms.push(new foundry.dice.terms.NumericTerm({ number: 1 })); } diff --git a/module/data/groupRollData.mjs b/module/data/groupRollData.mjs index 78a06b13..10123152 100644 --- a/module/data/groupRollData.mjs +++ b/module/data/groupRollData.mjs @@ -30,7 +30,7 @@ export class CharacterData extends foundry.abstract.DataModel { }), rollData: new fields.JSONField({ nullable: true, initial: null }), selected: new fields.BooleanField({ initial: false }), - successfull: new fields.BooleanField({ nullable: true, initial: null }) + successful: new fields.BooleanField({ nullable: true, initial: null }) }; } diff --git a/styles/less/dialog/group-roll-dialog/_common.less b/styles/less/dialog/group-roll-dialog/_common.less new file mode 100644 index 00000000..41573718 --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/_common.less @@ -0,0 +1,46 @@ +h1 { + color: light-dark(@dark-blue, @golden); + font-family: var(--dh-font-subtitle); + font-size: var(--font-size-24); + text-align: center; + font-weight: 700; +} + +header { + --bar-color: light-dark(@dark-blue, @golden); + color: light-dark(@dark, @beige); + display: flex; + justify-content: center; + align-items: center; + + &:not(:first-child) { + margin-top: var(--spacer-8); + } + + span { + padding: 0 10px; + } + + &:before { + content: ' '; + flex: 1; + height: 1px; + background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, var(--bar-color) 100%); + } + + &:after { + content: ' '; + flex: 1; + height: 1px; + background: linear-gradient(90deg, var(--bar-color) 0%, rgba(0, 0, 0, 0) 100%); + } +} + +img.portrait { + border-radius: 50%; + border: none; + object-fit: cover; + object-position: center top; + width: 2.5rem; + height: 2.5rem; +} diff --git a/styles/less/dialog/group-roll-dialog/index.less b/styles/less/dialog/group-roll-dialog/index.less new file mode 100644 index 00000000..27925fa2 --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/index.less @@ -0,0 +1,8 @@ +.daggerheart.dialog.dh-style.views.group-roll-dialog { + .window-content { + @import "./_common.less"; + } +} + +@import "./initialization.less"; +@import "./main.less"; diff --git a/styles/less/dialog/group-roll-dialog/initialization.less b/styles/less/dialog/group-roll-dialog/initialization.less index b2e7e021..b32f4756 100644 --- a/styles/less/dialog/group-roll-dialog/initialization.less +++ b/styles/less/dialog/group-roll-dialog/initialization.less @@ -1,62 +1,59 @@ -.theme-light .daggerheart.dialog.dh-style.views.group-roll-dialog { - .initialization-container .members-container .member-container { - .member-name { - background-image: url('../assets/parchments/dh-parchment-light.png'); - } - } -} - .daggerheart.dialog.dh-style.views.group-roll-dialog { - .initialization-container { - h2 { - text-align: center; - } - - .members-container { - display: grid; - grid-template-columns: 1fr 1fr 1fr 1fr; - gap: 8px; - - .member-container { - position: relative; - display: flex; - justify-content: center; - - &.inactive { - opacity: 0.4; - } - - .member-name { - position: absolute; - padding: 0 2px; - border: 1px solid; - border-radius: 6px; - margin-top: 4px; - color: light-dark(@dark, @beige); - background-image: url('../assets/parchments/dh-parchment-dark.png'); - text-align: center; - } - - img { - border-radius: 6px; - border: 1px solid light-dark(@dark-blue, @golden); - } - } - } + .initialization-container.active { + display: flex; + flex-direction: column; + overflow: hidden; .main-roll { - margin-top: 8px; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; + display: flex; + flex-direction: column; + text-align: center; + padding-bottom: 4px; &.inactive { opacity: 0.4; } } + .hint { + color: var(--color-form-hint); + line-height: 1; + padding: var(--spacer-8) 0; + font-family: var(--dh-font-body); + font-size: var(--font-size-12); + font-weight: 300; + } + + .members-container { + display: flex; + flex-direction: column; + gap: 8px; + overflow-y: auto; + + .member-container { + display: flex; + position: relative; + justify-content: center; + height: unset; + padding: 4px 8px; + gap: var(--spacer-8); + flex: 0 0 auto; + + &:not(.inactive) { + background: @golden-bg; + } + + .name { + flex: 1; + color: light-dark(@dark, @beige); + font-weight: 500; + text-align: left; + } + } + } + footer { - margin-top: 8px; + margin-top: 12px; display: flex; gap: 8px; diff --git a/styles/less/dialog/group-roll-dialog/leader.less b/styles/less/dialog/group-roll-dialog/leader.less deleted file mode 100644 index b3fa3a3b..00000000 --- a/styles/less/dialog/group-roll-dialog/leader.less +++ /dev/null @@ -1,35 +0,0 @@ -.daggerheart.dialog.dh-style.views.group-roll-dialog { - .main-character-outer-container { - &.inactive { - opacity: 0.3; - pointer-events: none; - } - - .main-character-container { - .character-info { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - height: 64px; - - img { - height: 64px; - border-radius: 6px; - border: 1px solid light-dark(@dark-blue, @golden); - } - - .character-data { - padding-left: 0.75rem; - flex: 1; - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - text-align: left; - font-size: var(--font-size-18); - } - } - } - } -} diff --git a/styles/less/dialog/group-roll-dialog/main.less b/styles/less/dialog/group-roll-dialog/main.less new file mode 100644 index 00000000..f266dcc7 --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/main.less @@ -0,0 +1,273 @@ +.daggerheart.dialog.dh-style.views.group-roll-dialog { + .group-roll.active { + display: flex; + flex-direction: column; + overflow: hidden; + + a.roll-button { + &:hover { + text-shadow: none; + filter: drop-shadow(0 0 3px @golden-90); + } + } + + .aiding-members { + display: flex; + flex-direction: column; + gap: 6px; + overflow-y: auto; + } + + .item-tags { + gap: 6px; + .tag.failure, + .tag.success { + font-weight: 600; + justify-content: center; + min-width: 3ch; + } + + .tag.success { + border-color: @green; + background: @green-10; + color: @green; + } + + .tag.failure { + border-color: @red; + background: @red-10; + color: @red; + } + + .tag { + padding-top: 0; + padding-bottom: 0; + line-height: 1.1875rem; + } + } + + .with-result { + border-radius: 5px; + background: var(--duality-bg); + color: var(--color-light-2); + + &.hope { + --duality-text-color: @golden; + --duality-bg: url(../assets/parchments/dh-parchment-hope.png); + } + + &.fear { + --duality-text-color: @chat-blue; + --duality-bg: url(../assets/parchments/dh-parchment-fear.png); + } + + &.critical { + --duality-text-color: @chat-purple; + --duality-bg: url(../assets/parchments/dh-parchment-critical.png); + } + + .duality-label { + font-family: var(--dh-font-subtitle); + color: var(--duality-text-color); + font-weight: 700; + } + } + + .member-roll-container { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; + min-height: 3.375rem; + + &.inactive { + pointer-events: none; + } + + .name-area { + display: flex; + flex-direction: column; + flex: 1; + justify-content: center; + .name { + font-weight: 500; + } + .trait { + display: flex; + align-items: center; + gap: 6px; + select { + --input-height: 2em; + width: auto; + } + } + .item-tags { + align-items: stretch; + } + } + + .buttons { + display: flex; + flex-direction: row; + button { + --button-text-color: var(--color-text-primary); + --button-size: 1.5em; + padding: 0 var(--spacer-4); + img { + width: 100%; + height: 100%; + object-fit: contain; + } + } + } + + a.roll-button.initial-roll { + width: 1.875rem; + height: 1.875rem; + margin-right: 2px; /** makes hover look a bit nicer */ + } + + .with-result { + display: flex; + justify-content: end; + align-items: center; + gap: 6px; + + .roll-data { + display: flex; + flex-direction: column; + align-items: end; + justify-content: center; + padding: 0 4px; + min-height: 3rem; + + .duality-label { + font-size: var(--font-size-15); + + .unused-damage { + text-decoration: line-through; + } + + .with { + font-size: var(--font-size-10); + } + } + + .roll-dice-container { + display: flex; + align-items: center; + justify-content: center; + flex-wrap: wrap; + gap: 2px; + + .roll-dice { + position: relative; + display: flex; + align-items: center; + justify-content: center; + + .dice-label { + position: absolute; + color: white; + font-size: 1rem; + paint-order: stroke fill; + -webkit-text-stroke: 2px black; + } + + img { + height: 1.3125rem; + } + } + + .roll-operator { + font-size: var(--font-size-18); + padding: 0 1px; + } + + .roll-value { + font-size: var(--font-size-16); + padding: 0 1px; + } + } + } + + .buttons { + flex-direction: column; + button { + color: var(--medium-red); + &[data-success=true] { + color: var(--green); + } + &.active { + text-shadow: 0 0 1px light-dark(@dark-80, @beige-80); + } + &.inactive { + opacity: 0.35; + } + } + } + } + } + } + + .group-roll-results { + display: flex; + flex-direction: column; + align-items: stretch; + gap: 4px; + font-size: var(--font-size-12); + padding: 6px 12px; + margin-top: 8px; + + &.empty { + color: light-dark(@dark-blue-90, @beige-80); + border-radius: 3px; + justify-content: center; + border: 1px dashed light-dark(@dark-blue-90, @beige-80); + text-align: center; + height: 3.25rem; + font-family: @font-body; + } + + .row { + display: flex; + align-items: center; + justify-content: space-between; + } + + .divider { + height: 1px; + background-image: linear-gradient(90deg, transparent 0%, var(--duality-text-color) 50%, transparent 100%); + margin-block: var(--spacer-4); + } + + .modifiers .item-tags { + min-height: calc(2px + 1.1875rem); + } + + .total { + .label { + font-size: var(--font-size-14); + } + .duality-label { + display: flex; + align-items: center; + gap: var(--spacer-4); + .value { + font-size: 20px; + } + } + } + } + + .finish-container { + margin-top: 16px; + gap: 16px; + display: grid; + grid-template-columns: 1fr 1fr 1fr; + + .finish-button { + grid-column: span 2; + } + } +} diff --git a/styles/less/dialog/group-roll-dialog/sheet.less b/styles/less/dialog/group-roll-dialog/sheet.less deleted file mode 100644 index 70afc1fe..00000000 --- a/styles/less/dialog/group-roll-dialog/sheet.less +++ /dev/null @@ -1,265 +0,0 @@ -.daggerheart.dialog.dh-style.views.group-roll-dialog { - .team-container { - display: grid; - grid-template-columns: 1fr 1fr; - gap: 16px; - margin-bottom: 16px; - - .team-member-container { - display: flex; - flex-direction: column; - justify-content: space-between; - gap: 8px; - flex: 1; - - &.inactive { - opacity: 0.3; - pointer-events: none; - } - - .data-container { - display: flex; - flex-direction: column; - gap: 8px; - width: 100%; - } - - .member-info { - display: flex; - align-items: start; - width: 100%; - - img { - height: 64px; - border-radius: 6px; - border: 1px solid light-dark(@dark-blue, @golden); - } - - .member-data { - padding-left: 0.75rem; - flex: 1; - height: 100%; - display: flex; - flex-direction: column; - justify-content: space-between; - text-align: left; - font-size: var(--font-size-18); - } - } - } - } - - .roll-container { - display: flex; - flex-direction: column; - } - - .roll-title { - font-size: var(--font-size-20); - font-weight: bold; - color: light-dark(@dark-blue, @golden); - text-align: center; - display: flex; - align-items: center; - gap: 8px; - - &.hope, - &.fear, - &.critical { - color: var(--text-color); - } - - &.hope { - --text-color: @golden; - } - - &.fear { - --text-color: @chat-blue; - } - - &.critical { - --text-color: @chat-purple; - } - - &::before, - &::after { - color: var(--text-color); - content: ''; - flex: 1; - height: 2px; - } - - &::before { - background: linear-gradient(90deg, rgba(0, 0, 0, 0) 0%, light-dark(@dark-blue, @golden) 100%); - } - - &::after { - background: linear-gradient(90deg, light-dark(@dark-blue, @golden) 0%, rgba(0, 0, 0, 0) 100%); - } - } - - .roll-tools { - display: flex; - gap: 4px; - align-items: center; - - img { - height: 16px; - } - - a { - display: flex; - font-size: 16px; - - &:hover { - text-shadow: none; - filter: drop-shadow(0 0 8px var(--golden)); - } - } - } - - .roll-data { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - - &.hope { - --text-color: @golden; - --bg-color: @golden-40; - } - - &.fear { - --text-color: @chat-blue; - --bg-color: @chat-blue-40; - } - - &.critical { - --text-color: @chat-purple; - --bg-color: @chat-purple-40; - } - - .duality-label { - color: var(--text-color); - font-size: var(--font-size-20); - font-weight: bold; - text-align: center; - - .unused-damage { - text-decoration: line-through; - } - } - - .roll-dice-container { - display: flex; - align-items: center; - justify-content: center; - flex-wrap: wrap; - gap: 8px; - - .roll-dice { - position: relative; - display: flex; - align-items: center; - justify-content: center; - - .dice-label { - position: absolute; - color: white; - font-size: 1rem; - paint-order: stroke fill; - -webkit-text-stroke: 2px black; - } - - img { - height: 32px; - } - } - - .roll-operator { - font-size: var(--font-size-24); - } - - .roll-value { - font-size: 18px; - } - } - - .roll-total { - background: var(--bg-color); - color: var(--text-color); - border-radius: 4px; - padding: 3px; - } - } - - .roll-success-container { - display: flex; - align-items: center; - justify-content: space-around; - - .roll-success-tools { - display: flex; - align-items: center; - gap: 4px; - color: light-dark(@dark-blue, @golden); - - i { - font-size: 24px; - } - } - - .roll-success-modifier { - display: flex; - align-items: center; - justify-content: right; - gap: 2px; - font-size: var(--font-size-20); - padding: 0px 4px; - - &.success { - background: @green-10; - color: @green; - } - - &.failure { - background: @red-10; - color: @red; - } - } - } - - .section-title { - font-size: var(--font-size-18); - font-weight: bold; - } - - .group-roll-results { - display: flex; - flex-direction: column; - align-items: center; - gap: 4px; - font-size: var(--font-size-20); - - .group-roll-container { - display: flex; - align-items: center; - gap: 2px; - } - } - - .finish-container { - margin-top: 16px; - gap: 16px; - display: grid; - grid-template-columns: 1fr 1fr 1fr; - - .finish-button { - grid-column: span 2; - } - } - - .hint { - text-align: center; - } -} diff --git a/styles/less/dialog/group-roll/group-roll.less b/styles/less/dialog/group-roll/group-roll.less deleted file mode 100644 index f2895d31..00000000 --- a/styles/less/dialog/group-roll/group-roll.less +++ /dev/null @@ -1,50 +0,0 @@ -@import '../../utils/colors.less'; - -.application.daggerheart.group-roll { - fieldset.one-column { - min-width: 500px; - margin-bottom: 10px; - } - .actor-item { - display: flex; - align-items: center; - gap: 15px; - width: 100%; - - img { - height: 40px; - width: 40px; - border-radius: 50%; - object-fit: cover; - } - - .actor-info { - display: flex; - flex-direction: column; - gap: 10px; - - .actor-check-info { - display: flex; - gap: 10px; - - .form-fields { - display: flex; - gap: 5px; - align-items: center; - - input { - max-width: 40px; - text-align: center; - } - } - } - } - - .controls { - margin-left: auto; - } - } - .tooltip-container { - width: 100%; - } -} diff --git a/styles/less/dialog/index.less b/styles/less/dialog/index.less index 947142ff..eb882eeb 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -31,14 +31,10 @@ @import './reroll-dialog/sheet.less'; -@import './group-roll/group-roll.less'; - @import './tag-team-dialog/initialization.less'; @import './tag-team-dialog/sheet.less'; -@import './group-roll-dialog/initialization.less'; -@import './group-roll-dialog/leader.less'; -@import './group-roll-dialog/sheet.less'; +@import './group-roll-dialog/index.less'; @import './image-select/sheet.less'; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index c5bca1da..afd56057 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -100,7 +100,7 @@ scrollbar-color: light-dark(@dark-blue, @golden) transparent; } - button { + button:where(:not(.plain)) { background: light-dark(transparent, @golden); border: 1px solid light-dark(@dark-blue, @dark-blue); color: light-dark(@dark-blue, @dark-blue); diff --git a/templates/dialogs/group-roll/group-roll.hbs b/templates/dialogs/group-roll/group-roll.hbs deleted file mode 100644 index 9b23c0a5..00000000 --- a/templates/dialogs/group-roll/group-roll.hbs +++ /dev/null @@ -1,84 +0,0 @@ -
-
-

{{localize "DAGGERHEART.UI.Chat.groupRoll.title"}}

-
- -
- {{localize "DAGGERHEART.UI.Chat.groupRoll.leader"}} - {{#unless leader.actor}} - -
- {{localize "DAGGERHEART.UI.Chat.groupRoll.selectLeader"}} -
- {{else}} -
- {{leader.actor.name}} -
- {{leader.actor.name}} -
-
- - -
- {{!-- Not used yet --}} - {{!--
- - -
--}} -
-
-
- - - -
-
- {{/unless}} -
- -
- {{localize "DAGGERHEART.UI.Chat.groupRoll.partyTeam"}} - - - - {{#if (gt this.members.length 0)}} - {{#each members as |member index|}} -
- {{member.actor.name}} -
- {{member.actor.name}} -
-
- - -
- {{!-- Not used yet --}} - {{!--
- - -
--}} -
-
-
- - - -
-
- {{/each}} - {{/if}} - {{#unless allSelected}} -
- {{localize "DAGGERHEART.UI.Chat.groupRoll.selectMember"}} -
- {{/unless}} -
- -
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/groupRoll.hbs b/templates/dialogs/groupRollDialog/groupRoll.hbs deleted file mode 100644 index edf1c980..00000000 --- a/templates/dialogs/groupRollDialog/groupRoll.hbs +++ /dev/null @@ -1,20 +0,0 @@ -
-
- {{localize "DAGGERHEART.GENERAL.result.single"}} - -
- {{#if hasRolled}}{{groupRoll.total}} {{groupRoll.totalLabel}}{{/if}} -
- {{#if groupRoll.leaderTotal includeZero=true}}{{groupRoll.leaderTotal}}{{else}}{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}}{{/if}} - {{#each groupRoll.modifiers as |modifier|}} - {{#if (gte modifier 0)}}+{{else}}-{{/if}} - {{positive modifier}} - {{/each}} - {{#unless groupRoll.modifiers.length}} - + - {{localize "DAGGERHEART.GENERAL.Modifier.plural"}} - {{/unless}} -
-
-
-
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/groupRollMember.hbs b/templates/dialogs/groupRollDialog/groupRollMember.hbs deleted file mode 100644 index acf8e8f1..00000000 --- a/templates/dialogs/groupRollDialog/groupRollMember.hbs +++ /dev/null @@ -1,85 +0,0 @@ -{{#with (lookup members partId)}} -
-
-
- -
- {{name}} -
-
-
- {{!-- --}} - -
-
-
-
-
- {{#if readyToRoll}} -
- - {{localize "DAGGERHEART.GENERAL.roll"}} -
- - - - - {{#if hasRolled}} - - - - {{/if}} -
-
- - {{#if roll}} -
-
{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}
-
- - {{roll.dHope.total}} - - - + - - {{roll.dFear.total}} - - - {{#if roll.advantage.type}} - {{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}} - - {{roll.advantage.value}} - - - {{/if}} - {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} - {{positive roll.modifierTotal}} -
-
- {{else}} - {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}} - {{/if}} -
- {{/if}} - {{#if hasRolled}} -
- {{#if ../isGM}} - - {{/if}} -
- {{localize "DAGGERHEART.GENERAL.Modifier.single"}}{{#if successfull}} + 1{{else if (isNullish successfull)}} + ?{{else}} - 1{{/if}} -
-
- {{/if}} -
-
-{{/with}} \ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/initialization.hbs b/templates/dialogs/groupRollDialog/initialization.hbs index a520b8bd..a01a00bb 100644 --- a/templates/dialogs/groupRollDialog/initialization.hbs +++ b/templates/dialogs/groupRollDialog/initialization.hbs @@ -1,32 +1,43 @@
+

{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.initializationTitle"}}

+
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
+
+
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.selectLeaderHint"}}
+ +
+ +
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.members"}}
+
{{"DAGGERHEART.APPLICATIONS.GroupRollSelect.selectParticipantsHint"}}
{{#each memberSelection as |member|}} - - {{member.name}} - - + + + {{member.name}} + {{#if (eq @root.selectedLeader.memberId member.id)}} + + {{/if}} + + + {{/each}}
-
-
- -
- -
-
-
-
-
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.openDialogForAll"}}
+
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/leader.hbs b/templates/dialogs/groupRollDialog/leader.hbs deleted file mode 100644 index 3d5db3f7..00000000 --- a/templates/dialogs/groupRollDialog/leader.hbs +++ /dev/null @@ -1,73 +0,0 @@ -
- {{#with leader}} -
-
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
-
-
-
- -
- {{name}} -
-
-
- -
-
-
-
-
-
- - {{#if readyToRoll}} -
- - {{localize "DAGGERHEART.GENERAL.roll"}} -
- - - - - {{#if hasRolled}} - - - - {{/if}} -
-
- - {{#if roll}} -
-
{{roll.total}} {{localize "DAGGERHEART.GENERAL.withThing" thing=roll.totalLabel}}
-
- - {{roll.dHope.total}} - - - + - - {{roll.dFear.total}} - - - {{#if roll.advantage.type}} - {{#if (eq roll.advantage.type 1)}}+{{else}}-{{/if}} - - {{roll.advantage.value}} - - - {{/if}} - {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} - {{positive roll.modifierTotal}} -
-
- {{else}} - {{localize "DAGGERHEART.APPLICATIONS.TagTeamSelect.makeYourRoll"}} - {{/if}} -
- {{/if}} -
-
- {{/with}} -
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/main.hbs b/templates/dialogs/groupRollDialog/main.hbs new file mode 100644 index 00000000..6807a7e4 --- /dev/null +++ b/templates/dialogs/groupRollDialog/main.hbs @@ -0,0 +1,15 @@ +
+

{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.title"}}

+
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.members"}}
+
+ {{#each aidKeys as |key|}} +
+ {{/each}} +
+ +
{{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leader"}}
+
+
{{localize "DAGGERHEART.GENERAL.result.single"}}
+
+
+
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/footer.hbs b/templates/dialogs/groupRollDialog/parts/footer.hbs similarity index 62% rename from templates/dialogs/groupRollDialog/footer.hbs rename to templates/dialogs/groupRollDialog/parts/footer.hbs index e401966b..34b4efa1 100644 --- a/templates/dialogs/groupRollDialog/footer.hbs +++ b/templates/dialogs/groupRollDialog/parts/footer.hbs @@ -1,6 +1,9 @@
- +
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/parts/member.hbs b/templates/dialogs/groupRollDialog/parts/member.hbs new file mode 100644 index 00000000..ee857794 --- /dev/null +++ b/templates/dialogs/groupRollDialog/parts/member.hbs @@ -0,0 +1,95 @@ +{{#with (ifThen (eq partId "leader") leader (lookup members partId))}} +
+ +
+ {{name}} + {{#if hasRolled}} +
+
{{rollChoiceLabel}}
+ {{#if modifier}} + + {{numberFormat modifier sign=true}} + + {{/if}} + {{#if isEditable}} +
+ + +
+ {{/if}} +
+ {{else if readyToRoll}} +
+ {{localize "DAGGERHEART.CONFIG.RollTypes.trait.name" }} + +
+ {{/if}} +
+ {{#if roll}} +
+
+
+ {{roll.total}} + {{withLabelShort}} +
+
+ + {{roll.dHope.total}} + + + + {{roll.dFear.total}} + + + {{#if roll.hasAdvantage}} + + + + {{roll.dAdvantage.total}} + + + {{/if}} + {{#if roll.hasDisadvantage}} + - + + {{roll.dDisadvantage.total}} + + + {{/if}} + {{#if (gte roll.modifierTotal 0)}}+{{else}}-{{/if}} + {{positive roll.modifierTotal}} +
+
+ {{#if (and @root.isGM (ne ../partId "leader"))}} +
+ + +
+ {{/if}} +
+ {{else if (and readyToRoll isEditable)}} + + 2d12 + + {{/if}} +
+{{/with}} \ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/parts/result.hbs b/templates/dialogs/groupRollDialog/parts/result.hbs new file mode 100644 index 00000000..d90dfb5c --- /dev/null +++ b/templates/dialogs/groupRollDialog/parts/result.hbs @@ -0,0 +1,30 @@ +{{#if (and hasRolled leader.roll)}} +
+
+ {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.leaderRoll"}} + + {{leader.roll.total}} + {{localize "DAGGERHEART.GENERAL.withThing" thing=leader.roll.totalLabel}} + +
+
+ {{localize "DAGGERHEART.GENERAL.Modifier.plural"}} +
+ {{#each groupRoll.modifiers as |modifier|}} + + {{numberFormat modifier sign=true}} + + {{/each}} +
+
+
+
+ {{localize "DAGGERHEART.GENERAL.total"}} + {{groupRoll.total}} {{groupRoll.totalLabel}} +
+
+{{else}} +
+ {{localize "DAGGERHEART.APPLICATIONS.GroupRollSelect.resultsHint"}} +
+{{/if}} \ No newline at end of file