diff --git a/gulpfile.js b/gulpfile.js index 1a81f5ae..45479a5c 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()).on('error', console.error.bind(console)).pipe(gulp.dest('styles')); + gulp.src('styles/daggerheart.less').pipe(less()).pipe(gulp.dest('styles')); cb(); }); diff --git a/lang/en.json b/lang/en.json index b4b1410e..99a75f83 100755 --- a/lang/en.json +++ b/lang/en.json @@ -758,20 +758,15 @@ } }, "GroupRollSelect": { - "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", + "title": "Group Roll", + "aidingCharacters": "Aiding Characters", "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", - "title": "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." }, "TokenConfig": { "actorSizeUsed": "Actor size is set, determining the dimensions" diff --git a/module/applications/dialogs/groupRollDialog.mjs b/module/applications/dialogs/groupRollDialog.mjs index df03a061..a47dd0a8 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: 390, height: 'auto' }, - window: { - icon: 'fa-solid fa-users' - }, + position: { width: 550, height: 'auto' }, actions: { toggleSelectMember: this.#toggleSelectMember, startGroupRoll: this.#startGroupRoll, makeRoll: this.#makeRoll, removeRoll: this.#removeRoll, rerollDice: this.#rerollDice, - markSuccessful: this.#markSuccessful, + makeLeaderRoll: this.#makeLeaderRoll, + removeLeaderRoll: this.#removeLeaderRoll, + rerollLeaderDice: this.#rerollLeaderDice, + markSuccessfull: this.#markSuccessfull, cancelRoll: this.#onCancelRoll, finishRoll: this.#finishRoll }, @@ -59,21 +59,17 @@ 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/parts/member.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/leader.hbs' }, - result: { - id: 'result', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/result.hbs' + groupRoll: { + id: 'groupRoll', + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRoll.hbs' }, footer: { id: 'footer', - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/footer.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/footer.hbs' } }; @@ -93,14 +89,40 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } _configureRenderParts(options) { - const parts = super._configureRenderParts(options); + const { initialization, leader, groupRoll, footer } = super._configureRenderParts(options); + const augmentedParts = { initialization }; for (const memberKey of Object.keys(this.party.system.groupRoll.aidingCharacters)) { - parts[memberKey] = { + augmentedParts[memberKey] = { id: memberKey, - template: 'systems/daggerheart/templates/dialogs/groupRollDialog/parts/member.hbs' + template: 'systems/daggerheart/templates/dialogs/groupRollDialog/groupRollMember.hbs' }; } - return parts; + + 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); + } } async _prepareContext(_options) { @@ -112,7 +134,6 @@ 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); @@ -124,7 +145,6 @@ 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': @@ -142,14 +162,19 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat partContext.canStartGroupRoll = selectedMembers.length > 1 && this.leader?.memberId; partContext.openForAllPlayers = this.openForAllPlayers; break; - case 'result': + case 'leader': + partContext.leader = this.getRollCharacterData(this.party.system.groupRoll.leader); + break; + case 'groupRoll': const leader = this.party.system.groupRoll.leader; partContext.hasRolled = leader?.rollData || - Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some(x => x.successful !== null); + Object.values(this.party.system.groupRoll?.aidingCharacters ?? {}).some( + x => x.successfull !== null + ); const { modifierTotal, modifiers } = Object.values(this.party.system.groupRoll.aidingCharacters).reduce( (acc, curr) => { - const modifier = curr.successful === true ? 1 : curr.successful === false ? -1 : null; + const modifier = curr.successfull === true ? 1 : curr.successfull === false ? -1 : null; if (modifier) { acc.modifierTotal += modifier; acc.modifiers.push(modifier); @@ -175,7 +200,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.successful !== null); + Object.values(this.party.system.groupRoll.aidingCharacters).every(x => x.successfull !== null); break; } @@ -191,42 +216,20 @@ 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), - modifier: data.successful ? 1 : data.successful === false ? -1 : 0, - withLabelShort: thing ? _loc('DAGGERHEART.GENERAL.withThing', { thing }) : null + hasRolled: Boolean(data.rollData) }; } - #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)); } @@ -253,16 +256,16 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } getUpdatingParts(target) { - const { initialization, leader, result, footer } = this.constructor.PARTS; + const { initialization, leader, groupRoll, footer } = this.constructor.PARTS; const isInitialization = this.tabGroups.application === initialization.id; - const updatingMember = target.closest('.member-roll-container.aid')?.dataset?.memberKey; - const updatingLeader = target.closest('.member-roll-container.leader'); + const updatingMember = target.closest('.team-member-container')?.dataset?.memberKey; + const updatingLeader = target.closest('.main-character-outer-container'); return [ ...(isInitialization ? [initialization.id] : []), ...(updatingMember ? [updatingMember] : []), ...(updatingLeader ? [leader.id] : []), - ...(!isInitialization ? [result.id, footer.id] : []) + ...(!isInitialization ? [groupRoll.id, footer.id] : []) ]; } @@ -301,9 +304,6 @@ 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,14 +343,11 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat } //#endregion - /** @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); + async makeRoll(button, characterData, path) { + const actor = game.actors.find(x => x.id === characterData.id); if (!actor) return; - const result = await actor.rollTrait(data.rollChoice, { + const result = await actor.rollTrait(characterData.rollChoice, { skips: { createMessage: true, resources: true, @@ -359,40 +356,53 @@ 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( { - [basePath]: { rollData, successful: null } + [path]: rollData }, this.getUpdatingParts(button) ); } - /** @this GroupRollDialog */ - static async #removeRoll(_event, button) { - const member = button.closest('[data-member-key]').dataset.memberKey; - const { basePath } = this.#getCharacterDataById(member); + 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.updatePartyData( { - [basePath]: { + [path]: { rollData: null, rollChoice: null, selected: false, - successful: null + successfull: null } }, this.getUpdatingParts(button) ); } - /** @this GroupRollDialog */ - static async #rerollDice(_, 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) { 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); @@ -406,19 +416,31 @@ export default class GroupRollDialog extends HandlebarsApplicationMixin(Applicat const rollData = newRoll.toJSON(); this.updatePartyData( { - [`${basePath}.rollData`]: rollData + [path]: rollData }, this.getUpdatingParts(button) ); } - 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'); + 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'); this.updatePartyData( { - [`system.groupRoll.aidingCharacters.${memberKey}.successful`]: + [`system.groupRoll.aidingCharacters.${button.dataset.member}.successfull`]: previousValue === newValue ? null : newValue }, this.getUpdatingParts(button) @@ -462,7 +484,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.successful ? '+' : '-' })); + totalRoll.terms.push(new foundry.dice.terms.OperatorTerm({ operator: character.successfull ? '+' : '-' })); totalRoll.terms.push(new foundry.dice.terms.NumericTerm({ number: 1 })); } diff --git a/module/applications/sheets/actors/character.mjs b/module/applications/sheets/actors/character.mjs index 513ad3f3..c59dd64e 100644 --- a/module/applications/sheets/actors/character.mjs +++ b/module/applications/sheets/actors/character.mjs @@ -3,7 +3,7 @@ import DhDeathMove from '../../dialogs/deathMove.mjs'; import { CharacterLevelup, LevelupViewMode } from '../../levelup/_module.mjs'; import DhCharacterCreation from '../../characterCreation/characterCreation.mjs'; import FilterMenu from '../../ux/filter-menu.mjs'; -import { getArmorSources, getDocFromElement, getDocFromElementSync, sortBy } from '../../../helpers/utils.mjs'; +import { getArmorSources, getDocFromElement, getDocFromElementSync } from '../../../helpers/utils.mjs'; /**@typedef {import('@client/applications/_types.mjs').ApplicationClickAction} ApplicationClickAction */ @@ -226,11 +226,6 @@ export default class CharacterSheet extends DHBaseActorSheet { context.resources.stress.emptyPips = context.resources.stress.max < maxResource ? maxResource - context.resources.stress.max : 0; - context.equippedItems = sortBy( - this.document.items.filter(i => i.system.equipped), - i => (i.type === 'weapon' ? (i.system.secondary ? 1 : 0) : 2) - ); - context.beastformActive = this.document.effects.find(x => x.type === 'beastform'); return context; diff --git a/module/config/resourceConfig.mjs b/module/config/resourceConfig.mjs index d33d7ab3..56ef6cd5 100644 --- a/module/config/resourceConfig.mjs +++ b/module/config/resourceConfig.mjs @@ -57,9 +57,15 @@ const companionBaseResources = Object.freeze({ stress: { id: 'stress', initial: 0, - max: 3, + max: 0, reverse: true, label: 'DAGGERHEART.GENERAL.stress' + }, + hope: { + id: 'hope', + initial: 0, + reverse: false, + label: 'DAGGERHEART.GENERAL.hope' } }); diff --git a/module/data/actor/adversary.mjs b/module/data/actor/adversary.mjs index d69e17ad..d30e090a 100644 --- a/module/data/actor/adversary.mjs +++ b/module/data/actor/adversary.mjs @@ -189,9 +189,6 @@ export default class DhpAdversary extends DhCreature { prepareDerivedData() { super.prepareDerivedData(); this.attack.roll.isStandardAttack = true; - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } _getTags() { diff --git a/module/data/actor/character.mjs b/module/data/actor/character.mjs index d42f2f64..6f60356e 100644 --- a/module/data/actor/character.mjs +++ b/module/data/actor/character.mjs @@ -778,8 +778,6 @@ export default class DhCharacter extends DhCreature { prepareDerivedData() { super.prepareDerivedData(); - - this.resources.hope.max -= this.scars; if (this.companion) { for (let levelKey in this.companion.system.levelData.levelups) { const level = this.companion.system.levelData.levelups[levelKey]; @@ -793,6 +791,7 @@ export default class DhCharacter extends DhCreature { } } + this.resources.hope.max -= this.scars; this.attack.roll.trait = this.rules.attack.roll.trait ?? this.attack.roll.trait; this.resources.armor = { @@ -802,9 +801,6 @@ export default class DhCharacter extends DhCreature { }; this.attack.damage.parts.hitPoints.value.custom.formula = `@prof${this.basicAttackDamageDice}${this.rules.attack.damage.bonus ? ` + ${this.rules.attack.damage.bonus}` : ''}`; - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } getRollData() { diff --git a/module/data/actor/companion.mjs b/module/data/actor/companion.mjs index 300bd698..538031fb 100644 --- a/module/data/actor/companion.mjs +++ b/module/data/actor/companion.mjs @@ -144,6 +144,9 @@ export default class DhCompanion extends DhCreature { const level = this.levelData.levelups[levelKey]; for (let selection of level.selections) { switch (selection.type) { + case 'hope': + this.resources.hope += selection.value; + break; case 'vicious': if (selection.data[0] === 'damage') { this.attack.damage.parts.hitPoints.value.dice = adjustDice( @@ -180,9 +183,6 @@ export default class DhCompanion extends DhCreature { return acc; }, this.partner.system.companionData.levelupChoices); } - - // Clamp resources (must be done last to ensure all updates occur) - this.resources.clamp(); } async _preUpdate(changes, options, userId) { diff --git a/module/data/actor/creature.mjs b/module/data/actor/creature.mjs index 601068ad..88646301 100644 --- a/module/data/actor/creature.mjs +++ b/module/data/actor/creature.mjs @@ -60,4 +60,14 @@ export default class DhCreature extends BaseDataActor { } } } + + prepareDerivedData() { + const minLimitResource = resource => { + if (resource) resource.value = Math.min(resource.value, resource.max); + }; + + minLimitResource(this.resources.stress); + minLimitResource(this.resources.hitPoints); + minLimitResource(this.resources.hope); + } } diff --git a/module/data/fields/actorField.mjs b/module/data/fields/actorField.mjs index a5f6f379..d6b58675 100644 --- a/module/data/fields/actorField.mjs +++ b/module/data/fields/actorField.mjs @@ -80,18 +80,6 @@ class ResourcesField extends fields.TypedObjectField { value.isReversed = resources[key].reverse; value.max = typeof resource.max === 'number' ? (value.max ?? resource.max) : null; } - Object.defineProperty(data, 'clamp', { - value: function () { - for (const key of Object.keys(this)) { - const resource = this[key]; - if (typeof resource?.max === 'number') { - resource.value = Math.clamp(resource.value, 0, resource.max); - } - } - }, - enumerable: false - }); - return data; } diff --git a/module/data/groupRollData.mjs b/module/data/groupRollData.mjs index 10123152..78a06b13 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 }), - successful: new fields.BooleanField({ nullable: true, initial: null }) + successfull: 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 deleted file mode 100644 index 41573718..00000000 --- a/styles/less/dialog/group-roll-dialog/_common.less +++ /dev/null @@ -1,46 +0,0 @@ -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 deleted file mode 100644 index 27925fa2..00000000 --- a/styles/less/dialog/group-roll-dialog/index.less +++ /dev/null @@ -1,8 +0,0 @@ -.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 b32f4756..b2e7e021 100644 --- a/styles/less/dialog/group-roll-dialog/initialization.less +++ b/styles/less/dialog/group-roll-dialog/initialization.less @@ -1,59 +1,62 @@ +.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.active { - display: flex; - flex-direction: column; - overflow: hidden; + .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); + } + } + } .main-roll { - display: flex; - flex-direction: column; - text-align: center; - padding-bottom: 4px; + margin-top: 8px; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; &.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: 12px; + margin-top: 8px; display: flex; gap: 8px; diff --git a/styles/less/dialog/group-roll-dialog/leader.less b/styles/less/dialog/group-roll-dialog/leader.less new file mode 100644 index 00000000..b3fa3a3b --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/leader.less @@ -0,0 +1,35 @@ +.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 deleted file mode 100644 index f266dcc7..00000000 --- a/styles/less/dialog/group-roll-dialog/main.less +++ /dev/null @@ -1,273 +0,0 @@ -.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 new file mode 100644 index 00000000..70afc1fe --- /dev/null +++ b/styles/less/dialog/group-roll-dialog/sheet.less @@ -0,0 +1,265 @@ +.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 new file mode 100644 index 00000000..f2895d31 --- /dev/null +++ b/styles/less/dialog/group-roll/group-roll.less @@ -0,0 +1,50 @@ +@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 eb882eeb..947142ff 100644 --- a/styles/less/dialog/index.less +++ b/styles/less/dialog/index.less @@ -31,10 +31,14 @@ @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/index.less'; +@import './group-roll-dialog/initialization.less'; +@import './group-roll-dialog/leader.less'; +@import './group-roll-dialog/sheet.less'; @import './image-select/sheet.less'; diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index afd56057..c5bca1da 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:where(:not(.plain)) { + button { 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 new file mode 100644 index 00000000..9b23c0a5 --- /dev/null +++ b/templates/dialogs/group-roll/group-roll.hbs @@ -0,0 +1,84 @@ +
+
+

{{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/parts/footer.hbs b/templates/dialogs/groupRollDialog/footer.hbs similarity index 62% rename from templates/dialogs/groupRollDialog/parts/footer.hbs rename to templates/dialogs/groupRollDialog/footer.hbs index 34b4efa1..e401966b 100644 --- a/templates/dialogs/groupRollDialog/parts/footer.hbs +++ b/templates/dialogs/groupRollDialog/footer.hbs @@ -1,9 +1,6 @@
- +
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/groupRoll.hbs b/templates/dialogs/groupRollDialog/groupRoll.hbs new file mode 100644 index 00000000..edf1c980 --- /dev/null +++ b/templates/dialogs/groupRollDialog/groupRoll.hbs @@ -0,0 +1,20 @@ +
+
+ {{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 new file mode 100644 index 00000000..acf8e8f1 --- /dev/null +++ b/templates/dialogs/groupRollDialog/groupRollMember.hbs @@ -0,0 +1,85 @@ +{{#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 a01a00bb..a520b8bd 100644 --- a/templates/dialogs/groupRollDialog/initialization.hbs +++ b/templates/dialogs/groupRollDialog/initialization.hbs @@ -1,43 +1,32 @@
-

{{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}} + + {{/each}}
+
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/templates/dialogs/groupRollDialog/leader.hbs b/templates/dialogs/groupRollDialog/leader.hbs new file mode 100644 index 00000000..3d5db3f7 --- /dev/null +++ b/templates/dialogs/groupRollDialog/leader.hbs @@ -0,0 +1,73 @@ +
+ {{#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 deleted file mode 100644 index 6807a7e4..00000000 --- a/templates/dialogs/groupRollDialog/main.hbs +++ /dev/null @@ -1,15 +0,0 @@ -
-

{{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/parts/member.hbs b/templates/dialogs/groupRollDialog/parts/member.hbs deleted file mode 100644 index ee857794..00000000 --- a/templates/dialogs/groupRollDialog/parts/member.hbs +++ /dev/null @@ -1,95 +0,0 @@ -{{#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 deleted file mode 100644 index d90dfb5c..00000000 --- a/templates/dialogs/groupRollDialog/parts/result.hbs +++ /dev/null @@ -1,30 +0,0 @@ -{{#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 diff --git a/templates/sheets/actors/character/sidebar.hbs b/templates/sheets/actors/character/sidebar.hbs index a0f93121..0142ac1d 100644 --- a/templates/sheets/actors/character/sidebar.hbs +++ b/templates/sheets/actors/character/sidebar.hbs @@ -108,16 +108,18 @@