diff --git a/lang/en.json b/lang/en.json index 85d5f997..aa379c6f 100755 --- a/lang/en.json +++ b/lang/en.json @@ -156,8 +156,7 @@ }, "conditional": { "title": "Conditional Application" - }, - "stacking": { "title": "Stacking" } + } }, "RangeDependance": { "hint": "Settings for an optional distance at which this effect should activate", @@ -2542,7 +2541,8 @@ "featuresLabel": "Community Feature" }, "Consumable": { - "consumeOnUse": "Consume On Use" + "consumeOnUse": "Consume On Use", + "destroyOnEmpty": "Destroy On Empty" }, "DomainCard": { "type": "Type", @@ -3008,8 +3008,6 @@ }, "EffectsDisplay": { "removeThing": "[Right Click] Remove {thing}", - "increaseStacks": "[Left Click] Increment Stacks", - "decreaseStacks": "[Right Click] Decrement Stacks", "appliedBy": "Applied By: {by}" }, "ItemBrowser": { diff --git a/module/applications/dialogs/d20RollDialog.mjs b/module/applications/dialogs/d20RollDialog.mjs index 64fa168a..0fdb1896 100644 --- a/module/applications/dialogs/d20RollDialog.mjs +++ b/module/applications/dialogs/d20RollDialog.mjs @@ -70,8 +70,8 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio context.rollConfig = this.config; context.hasRoll = !!this.config.roll; context.canRoll = true; - context.selectedMessageMode = this.config.selectedMessageMode ?? game.settings.get('core', 'messageMode'); - context.rollModes = Object.entries(CONFIG.ChatMessage.modes).map(([action, { label, icon }]) => ({ + context.selectedRollMode = this.config.selectedRollMode ?? game.settings.get('core', 'rollMode'); + context.rollModes = Object.entries(CONFIG.Dice.rollModes).map(([action, { label, icon }]) => ({ action, label, icon @@ -142,10 +142,10 @@ export default class D20RollDialog extends HandlebarsApplicationMixin(Applicatio })); } - static updateRollConfiguration(_event, _, formData) { + static updateRollConfiguration(event, _, formData) { const { ...rest } = foundry.utils.expandObject(formData.object); - this.config.selectedMessageMode = rest.selectedMessageMode; + this.config.selectedRollMode = rest.selectedRollMode; if (this.config.costs) { this.config.costs = foundry.utils.mergeObject(this.config.costs, rest.costs); diff --git a/module/applications/dialogs/damageDialog.mjs b/module/applications/dialogs/damageDialog.mjs index d00a744d..b24570cc 100644 --- a/module/applications/dialogs/damageDialog.mjs +++ b/module/applications/dialogs/damageDialog.mjs @@ -52,8 +52,8 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application context.formula = this.roll.constructFormula(this.config); context.hasHealing = this.config.hasHealing; context.directDamage = this.config.directDamage; - context.selectedMessageMode = this.config.selectedMessageMode; - context.rollModes = Object.entries(CONFIG.ChatMessage.modes).map(([action, { label, icon }]) => ({ + context.selectedRollMode = this.config.selectedRollMode; + context.rollModes = Object.entries(CONFIG.Dice.rollModes).map(([action, { label, icon }]) => ({ action, label, icon @@ -69,7 +69,7 @@ export default class DamageDialog extends HandlebarsApplicationMixin(Application const { ...rest } = foundry.utils.expandObject(formData.object); foundry.utils.mergeObject(this.config.roll, rest.roll); foundry.utils.mergeObject(this.config.modifiers, rest.modifiers); - this.config.selectedMessageMode = rest.selectedMessageMode; + this.config.selectedRollMode = rest.selectedRollMode; this.render(); } diff --git a/module/applications/dialogs/tagTeamDialog.mjs b/module/applications/dialogs/tagTeamDialog.mjs index 27003162..ddaabcb4 100644 --- a/module/applications/dialogs/tagTeamDialog.mjs +++ b/module/applications/dialogs/tagTeamDialog.mjs @@ -58,10 +58,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio id: 'initialization', template: 'systems/daggerheart/templates/dialogs/tagTeamDialog/initialization.hbs' }, - rollSelection: { - id: 'rollSelection', - template: 'systems/daggerheart/templates/dialogs/tagTeamDialog/rollSelection.hbs' - }, tagTeamRoll: { id: 'tagTeamRoll', template: 'systems/daggerheart/templates/dialogs/tagTeamDialog/tagTeamRoll.hbs' @@ -82,52 +78,15 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio element.addEventListener('change', this.updateRollType.bind(this)); } - _configureRenderParts(options) { - const { initialization, rollSelection, tagTeamRoll } = super._configureRenderParts(options); - const augmentedParts = { initialization }; - for (const memberKey of Object.keys(this.party.system.tagTeam.members)) { - augmentedParts[memberKey] = { - id: memberKey, - template: 'systems/daggerheart/templates/dialogs/tagTeamDialog/tagTeamMember.hbs' - }; - } - augmentedParts.rollSelection = rollSelection; - augmentedParts.tagTeamRoll = tagTeamRoll; - - return augmentedParts; - } - - /**@inheritdoc */ - async _onRender(context, options) { - await super._onRender(context, options); - - if (this.element.querySelector('.team-container')) return; - const initializationPart = this.element.querySelector('.initialization-container'); - initializationPart.insertAdjacentHTML('afterend', '
'); - const teamContainer = this.element.querySelector('.team-container'); - for (const memberContainer of this.element.querySelectorAll('.team-member-container')) - teamContainer.appendChild(memberContainer); - } - async _prepareContext(_options) { const context = await super._prepareContext(_options); context.isEditable = this.getIsEditable(); - context.fields = this.party.system.schema.fields.tagTeam.fields; - context.data = this.party.system.tagTeam; - context.rollTypes = CONFIG.DH.GENERAL.tagTeamRollTypes; - context.traitOptions = CONFIG.DH.ACTOR.abilities; - context.members = {}; - context.allHaveRolled = Object.keys(this.party.system.tagTeam.members).every(key => { - const data = this.party.system.tagTeam.members[key]; - return Boolean(data.rollData); - }); return context; } async _preparePartContext(partId, context, options) { const partContext = await super._preparePartContext(partId, context, options); - partContext.partId = partId; switch (partId) { case 'initialization': partContext.tagTeamFields = this.party.system.schema.fields.tagTeam.fields; @@ -141,20 +100,66 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio partContext.initiatorDisabled = !selectedMembers.length; partContext.openForAllPlayers = this.openForAllPlayers; - break; - case 'rollSelection': - partContext.members = Object.keys(this.party.system.tagTeam.members).reduce((acc, key) => { - const member = this.party.system.tagTeam.members[key]; - acc[key] = { selected: member.selected }; - return acc; - }, {}); break; case 'tagTeamRoll': + partContext.fields = this.party.system.schema.fields.tagTeam.fields; + partContext.data = this.party.system.tagTeam; + partContext.rollTypes = CONFIG.DH.GENERAL.tagTeamRollTypes; + partContext.traitOptions = CONFIG.DH.ACTOR.abilities; + const selectedRoll = Object.values(this.party.system.tagTeam.members).find(member => member.selected); const critSelected = !selectedRoll ? undefined : (selectedRoll?.rollData?.options?.roll?.isCritical ?? false); + partContext.members = {}; + for (const actorId in this.party.system.tagTeam.members) { + const data = this.party.system.tagTeam.members[actorId]; + const actor = game.actors.get(actorId); + + const rollOptions = []; + const damageRollOptions = []; + for (const item of actor.items) { + if (item.system.metadata.hasActions) { + const actions = [ + ...item.system.actions, + ...(item.system.attack ? [item.system.attack] : []) + ]; + for (const action of actions) { + if (action.hasRoll) { + const actionItem = { + value: action.uuid, + label: action.name, + group: item.name, + baseAction: action.baseAction + }; + + if (action.hasDamage) damageRollOptions.push(actionItem); + else rollOptions.push(actionItem); + } + } + } + } + + const damage = data.rollData?.options?.damage; + partContext.hasDamage |= Boolean(damage); + const critHitPointsDamage = await this.getCriticalDamage(damage); + + partContext.members[actorId] = { + ...data, + isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), + key: actorId, + readyToRoll: Boolean(data.rollChoice), + hasRolled: Boolean(data.rollData), + rollOptions, + damageRollOptions, + damage: damage, + critDamage: critHitPointsDamage, + useCritDamage: + critSelected || (critSelected === undefined && data.rollData?.options?.roll?.isCritical) + }; + } + partContext.hintText = await this.getInfoTexts(this.party.system.tagTeam.members); partContext.joinedRoll = await this.getJoinedRoll({ overrideIsCritical: critSelected, @@ -164,85 +169,24 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio break; } - if (Object.keys(this.party.system.tagTeam.members).includes(partId)) { - const data = this.party.system.tagTeam.members[partId]; - const actor = game.actors.get(partId); - - const rollOptions = []; - const damageRollOptions = []; - for (const item of actor.items) { - if (item.system.metadata.hasActions) { - const actions = [...item.system.actions, ...(item.system.attack ? [item.system.attack] : [])]; - for (const action of actions) { - if (action.hasRoll) { - const actionItem = { - value: action.uuid, - label: action.name, - group: item.name, - baseAction: action.baseAction - }; - - if (action.hasDamage) damageRollOptions.push(actionItem); - else rollOptions.push(actionItem); - } - } - } - } - - const selectedRoll = Object.values(this.party.system.tagTeam.members).find(member => member.selected); - const critSelected = !selectedRoll - ? undefined - : (selectedRoll?.rollData?.options?.roll?.isCritical ?? false); - - const damage = data.rollData?.options?.damage; - partContext.hasDamage |= Boolean(damage); - const critHitPointsDamage = await this.getCriticalDamage(damage); - - partContext.members[partId] = { - ...data, - isEditable: actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER), - key: partId, - readyToRoll: Boolean(data.rollChoice), - hasRolled: Boolean(data.rollData), - rollOptions, - damageRollOptions, - damage: damage, - critDamage: critHitPointsDamage, - useCritDamage: critSelected || (critSelected === undefined && data.rollData?.options?.roll?.isCritical) - }; - } - return partContext; } - getUpdatingParts(target) { - const { initialization, rollSelection, tagTeamRoll } = this.constructor.PARTS; - const isInitialization = this.tabGroups.application === initialization.id; - const updatingMember = target.closest('.team-member-container')?.dataset?.memberKey; - - return [ - ...(isInitialization ? [initialization.id] : []), - ...(updatingMember ? [updatingMember] : []), - ...(!isInitialization ? [rollSelection.id] : []), - ...(!isInitialization ? [tagTeamRoll.id] : []) - ]; - } - - static async updateData(event, _, formData) { + static async updateData(_event, _, formData) { const { initiator, openForAllPlayers, ...partyData } = foundry.utils.expandObject(formData.object); this.initiator = initiator; this.openForAllPlayers = openForAllPlayers !== undefined ? openForAllPlayers : this.openForAllPlayers; - this.updatePartyData(partyData, this.getUpdatingParts(event.target)); + this.updatePartyData(partyData); } - async updatePartyData(update, updatingParts, options = { render: true }) { + async updatePartyData(update, options = { render: true }) { const gmUpdate = async update => { await this.party.update(update); - this.render({ parts: updatingParts }); + this.render(); game.socket.emit(`system.${CONFIG.DH.id}`, { action: socketEvent.Refresh, - data: { refreshType: RefreshType.TagTeamRoll, action: 'refresh', parts: updatingParts } + data: { refreshType: RefreshType.TagTeamRoll, action: 'refresh' } }); }; @@ -251,9 +195,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio gmUpdate, update, this.party.uuid, - options.render - ? { refreshType: RefreshType.TagTeamRoll, action: 'refresh', parts: updatingParts } - : undefined + options.render ? { refreshType: RefreshType.TagTeamRoll, action: 'refresh' } : undefined ); } @@ -264,7 +206,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio }); } - tagTeamRefresh = ({ refreshType, action, parts }) => { + tagTeamRefresh = ({ refreshType, action }) => { if (refreshType !== RefreshType.TagTeamRoll) return; switch (action) { @@ -272,7 +214,7 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio this.tabGroups.application = 'tagTeamRoll'; break; case 'refresh': - this.render({ parts }); + this.render(); break; case 'close': this.close(); @@ -362,28 +304,22 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio } async updateRollType(event) { - this.updatePartyData( - { - [`system.tagTeam.members.${event.target.dataset.member}`]: { - rollType: event.target.value, - rollChoice: null - } - }, - this.getUpdatingParts(event.target) - ); + this.updatePartyData({ + [`system.tagTeam.members.${event.target.dataset.member}`]: { + rollType: event.target.value, + rollChoice: null + } + }); } static async #removeRoll(_, button) { - this.updatePartyData( - { - [`system.tagTeam.members.${button.dataset.member}`]: { - rollData: null, - rollChoice: null, - selected: false - } - }, - this.getUpdatingParts(button) - ); + this.updatePartyData({ + [`system.tagTeam.members.${button.dataset.member}`]: { + rollData: null, + rollChoice: null, + selected: false + } + }); } static async #makeRoll(event, button) { @@ -406,12 +342,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio const rollData = result.messageRoll.toJSON(); delete rollData.options.messageRoll; - this.updatePartyData( - { - [`system.tagTeam.members.${member}.rollData`]: rollData - }, - this.getUpdatingParts(button) - ); + this.updatePartyData({ + [`system.tagTeam.members.${member}.rollData`]: rollData + }); } async makeTraitRoll(memberKey) { @@ -456,18 +389,15 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio diceType ); const rollData = parsedRoll.toJSON(); - this.updatePartyData( - { - [`system.tagTeam.members.${member}.rollData`]: { - ...rollData, - options: { - ...rollData.options, - roll: newRoll - } + this.updatePartyData({ + [`system.tagTeam.members.${member}.rollData`]: { + ...rollData, + options: { + ...rollData.options, + roll: newRoll } - }, - this.getUpdatingParts(button) - ); + } + }); } static async #makeDamageRoll(event, button) { @@ -493,35 +423,29 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio if (!config.damage) return; const current = this.party.system.tagTeam.members[memberKey].rollData; - await this.updatePartyData( - { - [`system.tagTeam.members.${memberKey}.rollData`]: { - ...current, - options: { - ...current.options, - damage: config.damage - } + await this.updatePartyData({ + [`system.tagTeam.members.${memberKey}.rollData`]: { + ...current, + options: { + ...current.options, + damage: config.damage } - }, - this.getUpdatingParts(button) - ); + } + }); } static async #removeDamageRoll(_, button) { const { memberKey } = button.dataset; const current = this.party.system.tagTeam.members[memberKey].rollData; - this.updatePartyData( - { - [`system.tagTeam.members.${memberKey}.rollData`]: { - ...current, - options: { - ...current.options, - damage: null - } + this.updatePartyData({ + [`system.tagTeam.members.${memberKey}.rollData`]: { + ...current, + options: { + ...current.options, + damage: null } - }, - this.getUpdatingParts(button) - ); + } + }); } static async #rerollDamageDice(_, button) { @@ -552,12 +476,9 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio return acc; }, 0); - this.updatePartyData( - { - [`system.tagTeam.members.${memberKey}.rollData`]: rollData - }, - this.getUpdatingParts(button) - ); + this.updatePartyData({ + [`system.tagTeam.members.${memberKey}.rollData`]: rollData + }); } async getCriticalDamage(damage) { @@ -608,18 +529,15 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio static async #selectRoll(_, button) { const { memberKey } = button.dataset; - this.updatePartyData( - { - [`system.tagTeam.members`]: Object.entries(this.party.system.tagTeam.members).reduce( - (acc, [key, member]) => { - acc[key] = { selected: key === memberKey ? !member.selected : false }; - return acc; - }, - {} - ) - }, - this.getUpdatingParts(button) - ); + this.updatePartyData({ + [`system.tagTeam.members`]: Object.entries(this.party.system.tagTeam.members).reduce( + (acc, [key, member]) => { + acc[key] = { selected: key === memberKey ? !member.selected : false }; + return acc; + }, + {} + ) + }); } async getJoinedRoll({ overrideIsCritical, displayVersion } = {}) { @@ -684,7 +602,6 @@ export default class TagTeamDialog extends HandlebarsApplicationMixin(Applicatio members: _replace({}) } }, - [], { render: false } ); diff --git a/module/applications/sheets-configs/action-base-config.mjs b/module/applications/sheets-configs/action-base-config.mjs index 05a3177d..53c57ec5 100644 --- a/module/applications/sheets-configs/action-base-config.mjs +++ b/module/applications/sheets-configs/action-base-config.mjs @@ -154,13 +154,8 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) context.openSection = this.openSection; context.tabs = this._getTabs(this.constructor.TABS); context.config = CONFIG.DH; - if (this.action.hasDamage) { - context.allDamageTypesUsed = !getUnusedDamageTypes(this.action.damage.parts).length; - - if (this.action.damage.hasOwnProperty('includeBase') && this.action.type === 'attack') - context.hasBaseDamage = !!this.action.parent.attack; - } - + if (this.action.damage?.hasOwnProperty('includeBase') && this.action.type === 'attack') + context.hasBaseDamage = !!this.action.parent.attack; context.costOptions = this.getCostOptions(); context.getRollTypeOptions = this.getRollTypeOptions(); context.disableOption = this.disableOption.bind(this); @@ -178,6 +173,7 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) revealed: this.openTrigger === index }; }); + context.allDamageTypesUsed = !getUnusedDamageTypes(this.action.damage.parts).length; const settingsTiers = game.settings.get(CONFIG.DH.id, CONFIG.DH.SETTINGS.gameSettings.LevelTiers).tiers; context.tierOptions = [ @@ -316,11 +312,8 @@ export default class DHActionBaseConfig extends DaggerheartSheet(ApplicationV2) const callback = (_, button) => { const data = this.action.toObject(); const type = choices[button.form.elements.type.value].value; - const part = this.action.schema.fields.damage.fields.parts.element.getInitialValue(); - part.applyTo = type; - if (type === CONFIG.DH.GENERAL.healingTypes.hitPoints.id) - part.type = this.action.schema.fields.damage.fields.parts.element.fields.type.element.initial; - + const part = { applyTo: type }; + if (this.action.actor?.isNPC) part.value = { multiplier: 'flat' }; data.damage.parts[type] = part; this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); }; diff --git a/module/applications/sheets-configs/action-config.mjs b/module/applications/sheets-configs/action-config.mjs index e15b0391..e75e16ab 100644 --- a/module/applications/sheets-configs/action-config.mjs +++ b/module/applications/sheets-configs/action-config.mjs @@ -24,13 +24,15 @@ export default class DHActionConfig extends DHActionBaseConfig { const effectData = this._addEffectData.bind(this)(); const data = this.action.toObject(); - const created = await this.action.item.createEmbeddedDocuments('ActiveEffect', [ - game.system.api.data.activeEffects.BaseEffect.getDefaultObject() - ]); + const created = await game.system.api.documents.DhActiveEffect.createDialog(effectData, { + parent: this.action.item, + render: false + }); + if (!created) return; - data.effects.push({ _id: created[0]._id }); + data.effects.push({ _id: created._id }); this.constructor.updateForm.bind(this)(null, null, { object: foundry.utils.flattenObject(data) }); - this.action.item.effects.get(created[0]._id).sheet.render(true); + this.action.item.effects.get(created._id).sheet.render(true); } /** diff --git a/module/applications/sheets-configs/activeEffectConfig.mjs b/module/applications/sheets-configs/activeEffectConfig.mjs index 1c738bdb..3a993da0 100644 --- a/module/applications/sheets-configs/activeEffectConfig.mjs +++ b/module/applications/sheets-configs/activeEffectConfig.mjs @@ -172,10 +172,6 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac }); }); - htmlElement - .querySelector('.stacking-change-checkbox') - ?.addEventListener('change', this.stackingChangeToggle.bind(this)); - htmlElement .querySelector('.armor-change-checkbox') ?.addEventListener('change', this.armorChangeToggle.bind(this)); @@ -248,16 +244,6 @@ export default class DhActiveEffectConfig extends foundry.applications.sheets.Ac return partContext; } - stackingChangeToggle(event) { - const stackingFields = this.document.system.schema.fields.stacking.fields; - const systemData = { - stacking: event.target.checked - ? { value: stackingFields.value.initial, max: stackingFields.max.initial } - : null - }; - return this.submit({ updateData: { system: systemData } }); - } - armorChangeToggle(event) { if (event.target.checked) { this.addArmorChange(); diff --git a/module/applications/ui/effectsDisplay.mjs b/module/applications/ui/effectsDisplay.mjs index 035041e1..3bc5e716 100644 --- a/module/applications/ui/effectsDisplay.mjs +++ b/module/applications/ui/effectsDisplay.mjs @@ -49,9 +49,11 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica _attachPartListeners(partId, htmlElement, options) { super._attachPartListeners(partId, htmlElement, options); - for (const element of this.element?.querySelectorAll('.effect-container a') ?? []) { - element.addEventListener('click', e => this.#onClickEffect(e)); - element.addEventListener('contextmenu', e => this.#onClickEffect(e, -1)); + + if (this.element) { + this.element.querySelectorAll('.effect-container a').forEach(element => { + element.addEventListener('contextmenu', this.removeEffect.bind(this)); + }); } } @@ -85,21 +87,11 @@ export default class DhEffectsDisplay extends HandlebarsApplicationMixin(Applica this.render(); } - async #onClickEffect(event, delta = 1) { + async removeEffect(event) { const element = event.target.closest('.effect-container'); const effects = DhEffectsDisplay.getTokenEffects(); const effect = effects.find(x => x.id === element.dataset.effectId); - if (!effect || (delta >= 0 && !effect.system.stacking)) { - return; - } - - const maxValue = effect.system.stacking?.max ?? Infinity; - const newValue = Math.clamp((effect.system.stacking?.value ?? 1) + delta, 0, maxValue); - if (newValue > 0) { - await effect.update({ 'system.stacking.value': newValue }); - } else { - await effect.delete(); - } + await effect.delete(); this.render(); } diff --git a/module/applications/ux/contextMenu.mjs b/module/applications/ux/contextMenu.mjs index 4e4ec6a4..9a308667 100644 --- a/module/applications/ux/contextMenu.mjs +++ b/module/applications/ux/contextMenu.mjs @@ -1,3 +1,56 @@ +/** + * @typedef ContextMenuEntry + * @property {string} name The context menu label. Can be localized. + * @property {string} [icon] A string containing an HTML icon element for the menu item. + * @property {string} [classes] Additional CSS classes to apply to this menu item. + * @property {string} [group] An identifier for a group this entry belongs to. + * @property {ContextMenuJQueryCallback} callback The function to call when the menu item is clicked. + * @property {ContextMenuCondition|boolean} [condition] A function to call or boolean value to determine if this entry + * appears in the menu. + */ + +/** + * @callback ContextMenuCondition + * @param {jQuery|HTMLElement} html The element of the context menu entry. + * @returns {boolean} Whether the entry should be rendered in the context menu. + */ + +/** + * @callback ContextMenuCallback + * @param {HTMLElement} target The element that the context menu has been triggered for. + * @returns {unknown} + */ + +/** + * @callback ContextMenuJQueryCallback + * @param {HTMLElement|jQuery} target The element that the context menu has been triggered for. Will + * either be a jQuery object or an HTMLElement instance, depending + * on how the ContextMenu was configured. + * @returns {unknown} + */ + +/** + * @typedef ContextMenuOptions + * @property {string} [eventName="contextmenu"] Optionally override the triggering event which can spawn the menu. If + * the menu is using fixed positioning, this event must be a MouseEvent. + * @property {ContextMenuCallback} [onOpen] A function to call when the context menu is opened. + * @property {ContextMenuCallback} [onClose] A function to call when the context menu is closed. + * @property {boolean} [fixed=false] If true, the context menu is given a fixed position rather than being + * injected into the target. + * @property {boolean} [jQuery=true] If true, callbacks will be passed jQuery objects instead of HTMLElement + * instances. + */ + +/** + * @typedef ContextMenuRenderOptions + * @property {Event} [event] The event that triggered the context menu opening. + * @property {boolean} [animate=true] Animate the context menu opening. + */ + +/** + * A subclass of ContextMenu. + * @extends {foundry.applications.ux.ContextMenu} + */ export default class DHContextMenu extends foundry.applications.ux.ContextMenu { /** * Trigger a context menu event in response to a normal click on a additional options button. diff --git a/module/canvas/placeables/token.mjs b/module/canvas/placeables/token.mjs index 83fe3f41..58157a85 100644 --- a/module/canvas/placeables/token.mjs +++ b/module/canvas/placeables/token.mjs @@ -30,8 +30,8 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { if (!effect.img) continue; const promise = effect === overlayEffect - ? this._drawOverlay(effect.img, effect.tint, effect) - : this._drawEffect(effect.img, effect.tint, effect); + ? this._drawOverlay(effect.img, effect.tint) + : this._drawEffect(effect.img, effect.tint); promises.push( promise.then(e => { if (e) e.zIndex = i; @@ -45,39 +45,6 @@ export default class DhTokenPlaceable extends foundry.canvas.placeables.Token { this.renderFlags.set({ refreshEffects: true }); } - /**@inheritdoc */ - async _drawEffect(src, tint, effect) { - if (!src) return; - const tex = await foundry.canvas.loadTexture(src, { fallback: 'icons/svg/hazard.svg' }); - const icon = new PIXI.Sprite(tex); - icon.tint = tint ?? 0xffffff; - - if (effect.system.stacking?.value > 1) { - const stackOverlay = new PIXI.Text(effect.system.stacking.value, { - fill: '#f3c267', - stroke: '#000000', - fontSize: 96, - strokeThickness: 4 - }); - const nrDigits = Math.floor(Math.log10(effect.system.stacking.value)) + 1; - stackOverlay.y = -8; - /* This does not account for 1:s being much less wide than other digits. I don't think it's desired however as it makes it look jumpy */ - stackOverlay.x = icon.width - 8 - nrDigits * 56; - stackOverlay.anchor.set(0, 0); - - icon.addChild(stackOverlay); - } - - return this.effects.addChild(icon); - } - - async _drawOverlay(src, tint, effect) { - const icon = await this._drawEffect(src, tint, effect); - if (icon) icon.alpha = 0.8; - this.effects.overlay = icon ?? null; - return icon; - } - /** * Returns the distance from this token to another token object. * This value is corrected to handle alternate token sizes and other grid types diff --git a/module/data/action/baseAction.mjs b/module/data/action/baseAction.mjs index 1f75d382..01139b30 100644 --- a/module/data/action/baseAction.mjs +++ b/module/data/action/baseAction.mjs @@ -264,20 +264,12 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel hasSave: this.hasSave, onSave: this.save?.damageMod, isDirect: !!this.damage?.direct, - selectedMessageMode: game.settings.get('core', 'messageMode'), + selectedRollMode: game.settings.get('core', 'rollMode'), data: this.getRollData(), evaluate: this.hasRoll, resourceUpdates: new ResourceUpdateMap(this.actor), targetUuid: this.targetUuid, - ...configOptions, - skips: { - resources: false, - triggers: false, - createMessage: false, - updateCountdowns: false, - reaction: false, - ...(configOptions.skips ?? {}) - } + ...configOptions }; DHBaseAction.applyKeybindings(config); @@ -337,7 +329,6 @@ export default class DHBaseAction extends ActionMixin(foundry.abstract.DataModel * @param {boolean} successCost */ async consume(config, successCost = false) { - config.resourceUpdates = new ResourceUpdateMap(config.actionActor); await this.workflow.get('cost')?.execute(config, successCost); await this.workflow.get('uses')?.execute(config, successCost); diff --git a/module/data/activeEffect/baseEffect.mjs b/module/data/activeEffect/baseEffect.mjs index 4296874c..82e96776 100644 --- a/module/data/activeEffect/baseEffect.mjs +++ b/module/data/activeEffect/baseEffect.mjs @@ -83,20 +83,7 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { initial: CONFIG.DH.GENERAL.range.melee.id, label: 'DAGGERHEART.GENERAL.range' }) - }), - stacking: new fields.SchemaField( - { - value: new fields.NumberField({ - initial: 1, - min: 1, - integer: true, - nullable: false, - label: 'DAGGERHEART.GENERAL.value' - }), - max: new fields.NumberField({ integer: true, label: 'DAGGERHEART.GENERAL.max' }) - }, - { nullable: true, initial: null } - ) + }) }; } @@ -171,10 +158,8 @@ export default class BaseEffect extends foundry.data.ActiveEffectTypeDataModel { return acc; }, this.parent.actor.system.armor?.system?.armor?.current ?? 0); - if (newArmorTotal !== this.parent.actor.system.armorScore.value) { - const armorData = getScrollTextData(this.parent.actor, { value: newArmorTotal }, 'armor'); - options.scrollingTextData = [armorData]; - } + const armorData = getScrollTextData(this.parent.actor, { value: newArmorTotal }, 'armor'); + options.scrollingTextData = [armorData]; } } diff --git a/module/data/fields/action/effectsField.mjs b/module/data/fields/action/effectsField.mjs index 9a4ffc31..1a003e2b 100644 --- a/module/data/fields/action/effectsField.mjs +++ b/module/data/fields/action/effectsField.mjs @@ -106,11 +106,22 @@ export default class EffectsField extends fields.ArrayField { } /** - * Apply an Effect to a target + * Apply an Effect to a target or enable it if already on it * @param {object} effect Effect object containing ActiveEffect UUID * @param {object} actor Actor Document */ static async applyEffect(effect, actor) { + const existingEffect = actor.effects.find(e => e.origin === effect.uuid); + if (existingEffect) { + return effect.update( + foundry.utils.mergeObject({ + ...effect.constructor.getInitialDuration(), + disabled: false + }) + ); + } + + // Otherwise, create a new effect on the target const effectData = foundry.utils.mergeObject({ ...(effect.toObject?.() ?? effect), disabled: false, diff --git a/module/data/fields/actionField.mjs b/module/data/fields/actionField.mjs index ffdc25cd..20e4d6f0 100644 --- a/module/data/fields/actionField.mjs +++ b/module/data/fields/actionField.mjs @@ -89,7 +89,6 @@ export class ActionField extends foundry.data.fields.ObjectField { /** @override */ _cleanType(value, options, _state) { if (!(typeof value === 'object')) value = {}; - value = super._cleanType(value, options, _state); const cls = this.getModel(value); if (cls) return cls.cleanData(value, options, _state); return value; @@ -310,7 +309,7 @@ export function ActionMixin(Base) { } }; - ChatMessage.applyMode(msg, game.settings.get('core', 'messageMode')); + ChatMessage.applyRollMode(msg, game.settings.get('core', 'rollMode')); cls.create(msg); } } diff --git a/module/data/item/consumable.mjs b/module/data/item/consumable.mjs index ab527967..5a50525a 100644 --- a/module/data/item/consumable.mjs +++ b/module/data/item/consumable.mjs @@ -18,7 +18,8 @@ export default class DHConsumable extends BaseDataItem { const fields = foundry.data.fields; return { ...super.defineSchema(), - consumeOnUse: new fields.BooleanField({ initial: true }) + consumeOnUse: new fields.BooleanField({ initial: true }), + destroyOnEmpty: new fields.BooleanField({ initial: true }) }; } diff --git a/module/dice/damageRoll.mjs b/module/dice/damageRoll.mjs index 58c0cd02..8cd3caac 100644 --- a/module/dice/damageRoll.mjs +++ b/module/dice/damageRoll.mjs @@ -33,7 +33,7 @@ export default class DamageRoll extends DHRoll { static async buildPost(roll, config, message) { const chatMessage = config.source?.message ? ui.chat.collection.get(config.source.message) - : getDocumentClass('ChatMessage').applyMode({}, config.rollMode ?? 'public'); + : getDocumentClass('ChatMessage').applyRollMode({}, config.rollMode ?? CONST.DICE_ROLL_MODES.PUBLIC); if (game.modules.get('dice-so-nice')?.active) { const pool = foundry.dice.terms.PoolTerm.fromRolls( Object.values(config.damage).flatMap(r => r.parts.map(p => p.roll)) diff --git a/module/dice/dhRoll.mjs b/module/dice/dhRoll.mjs index a5d95cd1..b74adaf3 100644 --- a/module/dice/dhRoll.mjs +++ b/module/dice/dhRoll.mjs @@ -117,10 +117,10 @@ export default class DHRoll extends Roll { rolls: [roll] }; - config.selectedMessageMode ??= game.settings.get('core', 'messageMode'); + config.selectedRollMode ??= game.settings.get('core', 'rollMode'); if (roll._evaluated) { - const message = await cls.create(msgData, { messageMode: config.selectedMessageMode }); + const message = await cls.create(msgData, { rollMode: config.selectedRollMode }); if (config.tagTeamSelected) { game.system.api.applications.dialogs.TagTeamDialog.assignRoll(message.speakerActor, message); diff --git a/module/documents/activeEffect.mjs b/module/documents/activeEffect.mjs index c52e4cc0..355dcf32 100644 --- a/module/documents/activeEffect.mjs +++ b/module/documents/activeEffect.mjs @@ -111,18 +111,6 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { update.img = 'icons/magic/life/heart-cross-blue.webp'; } - const existingEffect = this.actor.effects.find(x => x.origin === data.origin); - const stacks = Boolean(data.system?.stacking); - if (existingEffect && !stacks) return false; - - if (existingEffect && stacks) { - const incrementedValue = existingEffect.system.stacking.value + 1; - await existingEffect.update({ - 'system.stacking.value': Math.min(incrementedValue, existingEffect.system.stacking.max ?? Infinity) - }); - return false; - } - const statuses = Object.keys(data.statuses ?? {}); const immuneStatuses = statuses.filter( @@ -199,10 +187,7 @@ export default class DhActiveEffect extends foundry.documents.ActiveEffect { } catch (_) {} } - const stackingParsedValue = effect.system.stacking - ? Roll.replaceFormulaData(key, { stacks: effect.system.stacking.value }) - : key; - const evalValue = itemAbleRollParse(stackingParsedValue, parseModel, effect.parent); + const evalValue = this.effectSafeEval(itemAbleRollParse(key, parseModel, effect.parent)); return evalValue ?? key; } diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs index 8105471b..023beaa0 100644 --- a/module/documents/actor.mjs +++ b/module/documents/actor.mjs @@ -122,14 +122,6 @@ export default class DhpActor extends Actor { } } - _onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId) { - if (collection === 'effects') { - ui.effectsDisplay.render(); - } - - super._onUpdateDescendantDocuments(parent, collection, documents, changes, options, userId); - } - async updateLevel(newLevel) { if (!['character', 'companion'].includes(this.type) || newLevel === this.system.levelData.level.changed) return; @@ -779,10 +771,20 @@ export default class DhpActor extends Actor { resources.forEach(r => { if (r.itemId) { const { path, value } = game.system.api.fields.ActionFields.CostField.getItemIdCostUpdate(r); - updates.items[r.key] = { - target: r.target, - resources: { [path]: value } - }; + + if ( + r.key === 'quantity' && + r.target.type === 'consumable' && + value === 0 && + r.target.system.destroyOnEmpty + ) { + r.target.delete(); + } else { + updates.items[r.key] = { + target: r.target, + resources: { [path]: value } + }; + } } else { const valueFunc = (base, resource, baseMax) => { if (resource.clear) return baseMax && base.inverted ? baseMax : 0; diff --git a/module/documents/rollTable.mjs b/module/documents/rollTable.mjs index 59652f44..50b8fe63 100644 --- a/module/documents/rollTable.mjs +++ b/module/documents/rollTable.mjs @@ -76,7 +76,7 @@ export default class DhRollTable extends foundry.documents.RollTable { } async toMessage(results, { roll, messageData = {}, messageOptions = {} } = {}) { - messageOptions.rollMode ??= game.settings.get('core', 'messageMode'); + messageOptions.rollMode ??= game.settings.get('core', 'rollMode'); // Construct chat data messageData = foundry.utils.mergeObject( diff --git a/module/documents/tooltipManager.mjs b/module/documents/tooltipManager.mjs index bf107a42..64e136ee 100644 --- a/module/documents/tooltipManager.mjs +++ b/module/documents/tooltipManager.mjs @@ -169,19 +169,70 @@ export default class DhTooltipManager extends foundry.helpers.interaction.Toolti } } - this.noOffset = options.noOffset; - super.activate(element, { ...options, html: html }); + this.baseActivate(element, { ...options, html: html }); } - _setAnchor(direction) { + /* Need to pass more options to _setAnchor, so have to copy whole foundry method >_< */ + async baseActivate(element, options) { + let { text, direction, cssClass, locked = false, html, content } = options; + if (content && !html) { + foundry.utils.logCompatibilityWarning( + 'The content option has been deprecated in favor of the html option', + { since: 13, until: 15, once: true } + ); + html = content; + } + + // Deactivate currently active element + this.deactivate(); + // Check if the element still exists in the DOM. + if (!document.body.contains(element)) return; + // Mark the new element as active + this.#active = true; + this.element = element; + element.setAttribute('aria-describedby', 'tooltip'); + html ||= element.dataset.tooltipHtml; + if (html) { + if (typeof html === 'string') this.tooltip.innerHTML = foundry.utils.cleanHTML(html); + else { + this.tooltip.innerHTML = ''; // Clear existing HTML + this.tooltip.appendChild(html); + } + } else { + text ||= element.dataset.tooltipText; + if (text) this.tooltip.textContent = text; + else { + text = element.dataset.tooltip; + // Localized message should be safe + if (game.i18n.has(text)) this.tooltip.innerHTML = game.i18n.localize(text); + else this.tooltip.innerHTML = foundry.utils.cleanHTML(text); + } + } + + // Activate display of the tooltip + this.tooltip.removeAttribute('class'); + this.tooltip.classList.add('active', 'themed', 'theme-dark'); + this.tooltip.showPopover(); + cssClass ??= element.closest('[data-tooltip-class]')?.dataset.tooltipClass; + if (cssClass) this.tooltip.classList.add(...cssClass.split(' ')); + + // Set tooltip position + direction ??= element.closest('[data-tooltip-direction]')?.dataset.tooltipDirection; + if (!direction) direction = this._determineDirection(); + this._setAnchor(direction, options); + + if (locked || element.dataset.hasOwnProperty('locked')) this.lockTooltip(); + } + + _setAnchor(direction, options = {}) { const directions = this.constructor.TOOLTIP_DIRECTIONS; const pad = this.constructor.TOOLTIP_MARGIN_PX; const pos = this.element.getBoundingClientRect(); const { innerHeight, innerWidth } = this.tooltip.ownerDocument.defaultView; const tooltipPadding = 16; - const horizontalOffset = this.noOffset ? tooltipPadding : this.tooltip.offsetWidth / 2 - pos.width / 2; - const verticalOffset = this.noOffset ? tooltipPadding : this.tooltip.offsetHeight / 2 - pos.height / 2; + const horizontalOffset = options.noOffset ? tooltipPadding : this.tooltip.offsetWidth / 2 - pos.width / 2; + const verticalOffset = options.noOffset ? tooltipPadding : this.tooltip.offsetHeight / 2 - pos.height / 2; const style = {}; switch (direction) { diff --git a/module/helpers/utils.mjs b/module/helpers/utils.mjs index 37293863..8b9be60c 100644 --- a/module/helpers/utils.mjs +++ b/module/helpers/utils.mjs @@ -771,7 +771,8 @@ export function getArmorSources(actor) { const data = rawArmorSources.map(doc => { // Get the origin item. Since the actor is already loaded, it should already be cached // Consider the relative function versions if this causes an issue - const origin = doc.origin ? foundry.utils.fromUuidSync(doc.origin) : doc; + const isItem = doc instanceof Item; + const origin = isItem ? doc : doc.origin ? foundry.utils.fromUuidSync(doc.origin) : doc.parent; return { origin, name: origin.name, diff --git a/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json b/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json index bd9bfffb..71018bc9 100644 --- a/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json +++ b/src/packs/beastforms/beastform_Agile_Scout_a9UoCwtrbgKk02mK.json @@ -29,7 +29,8 @@ "Compendium.daggerheart.beastforms.Item.QFg1hNCEoKVDd9Zo" ], "evolved": { - "mainTraitBonus": 0 + "mainTraitBonus": 0, + "maximumTier": 1 }, "hybrid": { "beastformOptions": 2, diff --git a/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json b/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json index 5b770e5d..b5239242 100644 --- a/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json +++ b/src/packs/classes/feature_No_Mercy_njj2C3tMDeCHHOoh.json @@ -71,17 +71,13 @@ "changes": [ { "key": "system.bonuses.roll.attack.bonus", - "type": "add", - "value": "@stacks", + "value": 1, "priority": null, - "phase": "initial" + "type": "add" } ], "duration": { "type": "shortRest" - }, - "stacking": { - "max": null } }, "disabled": false, diff --git a/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json b/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json index b886b079..0f31f491 100644 --- a/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json +++ b/src/packs/classes/feature_Rogue_s_Dodge_hVaaPIjxoextIgSL.json @@ -69,18 +69,14 @@ "changes": [ { "key": "system.evasion", - "type": "add", - "value": "2 * @stacks", + "value": 2, "priority": null, - "phase": "initial" + "type": "add" } ], "duration": { "type": "temporary", "description": "Until the next time an attack succeeds against you.
" - }, - "stacking": { - "max": null } }, "disabled": false, diff --git a/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json b/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json index 6a039bbf..01d88111 100644 --- a/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json +++ b/src/packs/domains/domainCard_Corrosive_Projectile_qJaSNTuDfbPVr8Lb.json @@ -127,7 +127,7 @@ "sort": 3400000, "effects": [ { - "name": "Corroded", + "name": "Corroded (1 stack)", "img": "icons/magic/acid/dissolve-bone-white.webp", "origin": "Compendium.daggerheart.domains.Item.qJaSNTuDfbPVr8Lb", "transfer": false, @@ -139,31 +139,27 @@ "type": "withinRange", "target": "hostile", "range": "melee" - }, - "changes": [ - { - "key": "system.difficulty", - "type": "add", - "value": "-@stack", - "priority": null, - "phase": "initial" - } - ], - "stacking": { - "max": null - }, - "duration": { - "type": "" } }, + "changes": [ + { + "key": "system.difficulty", + "mode": 2, + "value": "-1", + "priority": null + } + ], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, - "description": "While a target is Corroded, they gain a −1 penalty to their Difficulty for every 2 Stress you spent. This condition can stack.
", + "description": "While a target is Corroded, they gain a −1 penalty to their Difficulty for every 2 Stress you spent. This condition can stack.
", "tint": "#ffffff", "statuses": [ "corrode" @@ -173,16 +169,6 @@ "_stats": { "compendiumSource": null }, - "start": { - "time": 0, - "combat": null, - "combatant": null, - "initiative": null, - "round": null, - "turn": null - }, - "showIcon": 1, - "folder": null, "_key": "!items.effects!qJaSNTuDfbPVr8Lb.zB95bjSSdVlApQnR" } ], diff --git a/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json b/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json index c3493aea..6f8b481d 100644 --- a/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json +++ b/src/packs/domains/domainCard_Rage_Up_GRL0cvs96vrTDckZ.json @@ -42,8 +42,44 @@ "type": "self", "amount": null }, - "name": "Mark Stress", - "img": "icons/skills/wounds/injury-face-impact-orange.webp", + "name": "Mark 1 Stress", + "img": "icons/magic/control/silhouette-aura-energy.webp", + "range": "self" + }, + "fKY9NcYBwCFwMsgV": { + "type": "effect", + "_id": "fKY9NcYBwCFwMsgV", + "systemPath": "actions", + "description": "You can mark a Stress to gain a bonus to your damage roll equal to twice your Strength.
", + "chatDisplay": true, + "actionType": "action", + "cost": [ + { + "scalable": false, + "key": "stress", + "value": 2, + "step": null, + "consumeOnSuccess": false + } + ], + "uses": { + "value": null, + "max": "", + "recovery": null, + "consumeOnSuccess": false + }, + "effects": [ + { + "_id": "t6SIjQxB6UBUJ98f", + "onSave": false + } + ], + "target": { + "type": "self", + "amount": null + }, + "name": "Mark 2 Stress", + "img": "icons/magic/control/silhouette-aura-energy.webp", "range": "self" } }, @@ -58,8 +94,8 @@ "sort": 3400000, "effects": [ { - "name": "Rage Up", - "img": "icons/skills/wounds/injury-face-impact-orange.webp", + "name": "Rage Up (1)", + "img": "systems/daggerheart/assets/icons/domains/domain-card/blade.png", "origin": "Compendium.daggerheart.domains.Item.GRL0cvs96vrTDckZ", "transfer": false, "_id": "bq1MhcmoP6Wo5CXF", @@ -70,38 +106,33 @@ "type": "withinRange", "target": "hostile", "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "type": "add", - "value": "2*@system.traits.strength.value*@stacks", - "priority": 21, - "phase": "initial" - }, - { - "key": "system.bonuses.damage.physical.bonus", - "type": "add", - "value": "2*@system.traits.strength.value*@stacks", - "priority": 21, - "phase": "initial" - } - ], - "stacking": { - "max": 2 - }, - "duration": { - "type": "" } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "2*@system.traits.strength.value", + "priority": 21 + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "2*@system.traits.strength.value", + "priority": 21 + } + ], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, - "description": "For your next attack you have a bonus to your damage roll equal to twice your Strength.
", + "description": "", "tint": "#ffffff", "statuses": [], "sort": 0, @@ -109,16 +140,6 @@ "_stats": { "compendiumSource": null }, - "start": { - "time": 0, - "combat": null, - "combatant": null, - "initiative": null, - "round": null, - "turn": null - }, - "showIcon": 1, - "folder": null, "_key": "!items.effects!GRL0cvs96vrTDckZ.bq1MhcmoP6Wo5CXF" }, { @@ -134,28 +155,31 @@ "type": "withinRange", "target": "hostile", "range": "melee" - }, - "changes": [ - { - "key": "system.bonuses.damage.magical.bonus", - "value": "4*@system.traits.strength.value", - "priority": 21, - "type": "add" - }, - { - "key": "system.bonuses.damage.physical.bonus", - "value": "4*@system.traits.strength.value", - "priority": 21, - "type": "add" - } - ] + } }, + "changes": [ + { + "key": "system.bonuses.damage.magical.bonus", + "mode": 2, + "value": "4*@system.traits.strength.value", + "priority": 21 + }, + { + "key": "system.bonuses.damage.physical.bonus", + "mode": 2, + "value": "4*@system.traits.strength.value", + "priority": 21 + } + ], "disabled": false, "duration": { - "value": null, - "units": "seconds", - "expiry": null, - "expired": false + "startTime": null, + "combat": null, + "seconds": null, + "rounds": null, + "turns": null, + "startRound": null, + "startTurn": null }, "description": "", "tint": "#ffffff", @@ -165,9 +189,6 @@ "_stats": { "compendiumSource": null }, - "start": null, - "showIcon": 1, - "folder": null, "_key": "!items.effects!GRL0cvs96vrTDckZ.t6SIjQxB6UBUJ98f" } ], diff --git a/src/packs/items/consumables/consumable_Acidpaste_cfVFmS8vT9dbq9s1.json b/src/packs/items/consumables/consumable_Acidpaste_cfVFmS8vT9dbq9s1.json index c1833e87..7c2d113d 100644 --- a/src/packs/items/consumables/consumable_Acidpaste_cfVFmS8vT9dbq9s1.json +++ b/src/packs/items/consumables/consumable_Acidpaste_cfVFmS8vT9dbq9s1.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Armor_Stitcher_VlbsCjvvLNfTzNXb.json b/src/packs/items/consumables/consumable_Armor_Stitcher_VlbsCjvvLNfTzNXb.json index d78986cf..58efc3cc 100644 --- a/src/packs/items/consumables/consumable_Armor_Stitcher_VlbsCjvvLNfTzNXb.json +++ b/src/packs/items/consumables/consumable_Armor_Stitcher_VlbsCjvvLNfTzNXb.json @@ -48,6 +48,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json b/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json index e034976a..f19c55c3 100644 --- a/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json +++ b/src/packs/items/consumables/consumable_Attune_Potion_JGD3M9hBHtVAA8XP.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Blinding_Orb_eAXHdzA5qNPldOpn.json b/src/packs/items/consumables/consumable_Blinding_Orb_eAXHdzA5qNPldOpn.json index 1282ceeb..9c6403e1 100644 --- a/src/packs/items/consumables/consumable_Blinding_Orb_eAXHdzA5qNPldOpn.json +++ b/src/packs/items/consumables/consumable_Blinding_Orb_eAXHdzA5qNPldOpn.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Blood_of_the_Yorgi_pDGzmczoTlKGmKgd.json b/src/packs/items/consumables/consumable_Blood_of_the_Yorgi_pDGzmczoTlKGmKgd.json index df40e563..6a84b89b 100644 --- a/src/packs/items/consumables/consumable_Blood_of_the_Yorgi_pDGzmczoTlKGmKgd.json +++ b/src/packs/items/consumables/consumable_Blood_of_the_Yorgi_pDGzmczoTlKGmKgd.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json b/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json index 421acdc3..c6241a9c 100644 --- a/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json +++ b/src/packs/items/consumables/consumable_Bolster_Potion_FOPQNqXbiVO0ilYL.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Bonding_Honey_PfQvqopXgvroBklL.json b/src/packs/items/consumables/consumable_Bonding_Honey_PfQvqopXgvroBklL.json index 04532b27..4240ae2e 100644 --- a/src/packs/items/consumables/consumable_Bonding_Honey_PfQvqopXgvroBklL.json +++ b/src/packs/items/consumables/consumable_Bonding_Honey_PfQvqopXgvroBklL.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Bridge_Seed_RrIasiMCt6mqVTps.json b/src/packs/items/consumables/consumable_Bridge_Seed_RrIasiMCt6mqVTps.json index b81e7f36..a80481d5 100644 --- a/src/packs/items/consumables/consumable_Bridge_Seed_RrIasiMCt6mqVTps.json +++ b/src/packs/items/consumables/consumable_Bridge_Seed_RrIasiMCt6mqVTps.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Channelstone_IKMVQ6VwtapwoUim.json b/src/packs/items/consumables/consumable_Channelstone_IKMVQ6VwtapwoUim.json index 28a13044..f4ec4476 100644 --- a/src/packs/items/consumables/consumable_Channelstone_IKMVQ6VwtapwoUim.json +++ b/src/packs/items/consumables/consumable_Channelstone_IKMVQ6VwtapwoUim.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json b/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json index f1d7b058..48303854 100644 --- a/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json +++ b/src/packs/items/consumables/consumable_Charm_Potion_CVBbFfOY75YwyQsp.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Circle_of_the_Void_elsyP6VhHw1JjGSl.json b/src/packs/items/consumables/consumable_Circle_of_the_Void_elsyP6VhHw1JjGSl.json index 7c93342e..159a1381 100644 --- a/src/packs/items/consumables/consumable_Circle_of_the_Void_elsyP6VhHw1JjGSl.json +++ b/src/packs/items/consumables/consumable_Circle_of_the_Void_elsyP6VhHw1JjGSl.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json b/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json index 2c6b9a93..9523cdce 100644 --- a/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json +++ b/src/packs/items/consumables/consumable_Control_Potion_eeBhZSGLjuNZuJuI.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json b/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json index 5fbae976..1a7ae1a5 100644 --- a/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json +++ b/src/packs/items/consumables/consumable_Death_Tea_xDnJeF1grkmKck8Q.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Dragonbloom_Tea_wM18PWWW2Ami4fBG.json b/src/packs/items/consumables/consumable_Dragonbloom_Tea_wM18PWWW2Ami4fBG.json index 5e877f6d..2a4c6ac9 100644 --- a/src/packs/items/consumables/consumable_Dragonbloom_Tea_wM18PWWW2Ami4fBG.json +++ b/src/packs/items/consumables/consumable_Dragonbloom_Tea_wM18PWWW2Ami4fBG.json @@ -89,6 +89,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Dripfang_Poison_eU8VpbWB2NHIL47n.json b/src/packs/items/consumables/consumable_Dripfang_Poison_eU8VpbWB2NHIL47n.json index cb2c7997..c37b8bb4 100644 --- a/src/packs/items/consumables/consumable_Dripfang_Poison_eU8VpbWB2NHIL47n.json +++ b/src/packs/items/consumables/consumable_Dripfang_Poison_eU8VpbWB2NHIL47n.json @@ -71,6 +71,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json b/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json index bff70126..02ffa6d9 100644 --- a/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json +++ b/src/packs/items/consumables/consumable_Enlighten_Potion_aWHSO2AqDufi7nL4.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Feast_of_Xuria_aX6NyxkNzu0LcJpt.json b/src/packs/items/consumables/consumable_Feast_of_Xuria_aX6NyxkNzu0LcJpt.json index 159e0442..b23f091b 100644 --- a/src/packs/items/consumables/consumable_Feast_of_Xuria_aX6NyxkNzu0LcJpt.json +++ b/src/packs/items/consumables/consumable_Feast_of_Xuria_aX6NyxkNzu0LcJpt.json @@ -134,6 +134,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json b/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json index 9b5bd0df..dbf5b19a 100644 --- a/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json +++ b/src/packs/items/consumables/consumable_Featherbone_DpxEMpwfasEBpORU.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json b/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json index 890c61e4..e69c440c 100644 --- a/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json +++ b/src/packs/items/consumables/consumable_Gill_Salve_Nvbb9mze6o5D0AEg.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json b/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json index 70291404..75d19c32 100644 --- a/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json +++ b/src/packs/items/consumables/consumable_Grindletooth_Venom_8WkhvSzeOmLdnoLJ.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Growing_Potion_fl2f3ees8RFMze9t.json b/src/packs/items/consumables/consumable_Growing_Potion_fl2f3ees8RFMze9t.json index 833e7055..44114455 100644 --- a/src/packs/items/consumables/consumable_Growing_Potion_fl2f3ees8RFMze9t.json +++ b/src/packs/items/consumables/consumable_Growing_Potion_fl2f3ees8RFMze9t.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Health_Potion_Aruc2NLutWuVIjP1.json b/src/packs/items/consumables/consumable_Health_Potion_Aruc2NLutWuVIjP1.json index 7365b375..bc82daa2 100644 --- a/src/packs/items/consumables/consumable_Health_Potion_Aruc2NLutWuVIjP1.json +++ b/src/packs/items/consumables/consumable_Health_Potion_Aruc2NLutWuVIjP1.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json b/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json index 00eb03f1..8ee6f171 100644 --- a/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json +++ b/src/packs/items/consumables/consumable_Homet_s_Secret_Potion_VSwa1LpQ9PjZKsWF.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Hopehold_Flare_EhaQCPJ8oiqpRIwB.json b/src/packs/items/consumables/consumable_Hopehold_Flare_EhaQCPJ8oiqpRIwB.json index 2d83ed52..809ad08e 100644 --- a/src/packs/items/consumables/consumable_Hopehold_Flare_EhaQCPJ8oiqpRIwB.json +++ b/src/packs/items/consumables/consumable_Hopehold_Flare_EhaQCPJ8oiqpRIwB.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Improved_Arcane_Shard_nQTo6mNoPTEVBtkm.json b/src/packs/items/consumables/consumable_Improved_Arcane_Shard_nQTo6mNoPTEVBtkm.json index 707a395f..b39db9b5 100644 --- a/src/packs/items/consumables/consumable_Improved_Arcane_Shard_nQTo6mNoPTEVBtkm.json +++ b/src/packs/items/consumables/consumable_Improved_Arcane_Shard_nQTo6mNoPTEVBtkm.json @@ -91,6 +91,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json b/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json index 560644b3..904c4675 100644 --- a/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json +++ b/src/packs/items/consumables/consumable_Improved_Grindletooth_Venom_BqBWXXe9T07AMV4u.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Jar_of_Lost_Voices_yUol6M5b8jsbk9za.json b/src/packs/items/consumables/consumable_Jar_of_Lost_Voices_yUol6M5b8jsbk9za.json index c8e6e75b..3e716230 100644 --- a/src/packs/items/consumables/consumable_Jar_of_Lost_Voices_yUol6M5b8jsbk9za.json +++ b/src/packs/items/consumables/consumable_Jar_of_Lost_Voices_yUol6M5b8jsbk9za.json @@ -71,6 +71,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Jumping_Root_c2putn9apuurJhWX.json b/src/packs/items/consumables/consumable_Jumping_Root_c2putn9apuurJhWX.json index c1b5eee1..dec72da8 100644 --- a/src/packs/items/consumables/consumable_Jumping_Root_c2putn9apuurJhWX.json +++ b/src/packs/items/consumables/consumable_Jumping_Root_c2putn9apuurJhWX.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Knowledge_Stone_nL9IALzm9BNi5oSt.json b/src/packs/items/consumables/consumable_Knowledge_Stone_nL9IALzm9BNi5oSt.json index 9685a44f..19f273ed 100644 --- a/src/packs/items/consumables/consumable_Knowledge_Stone_nL9IALzm9BNi5oSt.json +++ b/src/packs/items/consumables/consumable_Knowledge_Stone_nL9IALzm9BNi5oSt.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Major_Arcane_Shard_AA7bmiwv00lshPrC.json b/src/packs/items/consumables/consumable_Major_Arcane_Shard_AA7bmiwv00lshPrC.json index 5e95fe66..25cb8fb3 100644 --- a/src/packs/items/consumables/consumable_Major_Arcane_Shard_AA7bmiwv00lshPrC.json +++ b/src/packs/items/consumables/consumable_Major_Arcane_Shard_AA7bmiwv00lshPrC.json @@ -89,6 +89,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json b/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json index b27fee91..6090c631 100644 --- a/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json +++ b/src/packs/items/consumables/consumable_Major_Attune_Potion_CCPFm5iXXwvyYYwR.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json b/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json index 95cd6c92..98329c78 100644 --- a/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json +++ b/src/packs/items/consumables/consumable_Major_Bolster_Potion_mnyQDRtngWWQeRXF.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json b/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json index c7e22aeb..aebb9435 100644 --- a/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json +++ b/src/packs/items/consumables/consumable_Major_Charm_Potion_IJLAUlQymbSjzsri.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json b/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json index 1dabf6c6..76d4ea3c 100644 --- a/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json +++ b/src/packs/items/consumables/consumable_Major_Control_Potion_80s1FLmTLtohZ5GH.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json b/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json index 5a9a2d28..9bbd4290 100644 --- a/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json +++ b/src/packs/items/consumables/consumable_Major_Enlighten_Potion_SDdv1G2veMLKrxcJ.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Health_Potion_cM7pHe8bBAxSZ2xR.json b/src/packs/items/consumables/consumable_Major_Health_Potion_cM7pHe8bBAxSZ2xR.json index 67be0b08..843249de 100644 --- a/src/packs/items/consumables/consumable_Major_Health_Potion_cM7pHe8bBAxSZ2xR.json +++ b/src/packs/items/consumables/consumable_Major_Health_Potion_cM7pHe8bBAxSZ2xR.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Stamina_Potion_I4cQ03xbxnc81EGa.json b/src/packs/items/consumables/consumable_Major_Stamina_Potion_I4cQ03xbxnc81EGa.json index 703c2cbe..ebe07a1f 100644 --- a/src/packs/items/consumables/consumable_Major_Stamina_Potion_I4cQ03xbxnc81EGa.json +++ b/src/packs/items/consumables/consumable_Major_Stamina_Potion_I4cQ03xbxnc81EGa.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Major_Stride_Potion_yK6eEDUrsPbZA8G0.json b/src/packs/items/consumables/consumable_Major_Stride_Potion_yK6eEDUrsPbZA8G0.json index dbfe2dcc..cfcee96b 100644 --- a/src/packs/items/consumables/consumable_Major_Stride_Potion_yK6eEDUrsPbZA8G0.json +++ b/src/packs/items/consumables/consumable_Major_Stride_Potion_yK6eEDUrsPbZA8G0.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Minor_Health_Potion_tPfKtKRRjv8qdSqy.json b/src/packs/items/consumables/consumable_Minor_Health_Potion_tPfKtKRRjv8qdSqy.json index fe86bf95..bac0f425 100644 --- a/src/packs/items/consumables/consumable_Minor_Health_Potion_tPfKtKRRjv8qdSqy.json +++ b/src/packs/items/consumables/consumable_Minor_Health_Potion_tPfKtKRRjv8qdSqy.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Minor_Stamina_Potion_b6vGSPFWOlzZZDLO.json b/src/packs/items/consumables/consumable_Minor_Stamina_Potion_b6vGSPFWOlzZZDLO.json index 625167e1..79a29e8b 100644 --- a/src/packs/items/consumables/consumable_Minor_Stamina_Potion_b6vGSPFWOlzZZDLO.json +++ b/src/packs/items/consumables/consumable_Minor_Stamina_Potion_b6vGSPFWOlzZZDLO.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Mirror_of_Marigold_UFQVwgYOUZ88UxcH.json b/src/packs/items/consumables/consumable_Mirror_of_Marigold_UFQVwgYOUZ88UxcH.json index 7adaf3e6..ba3a3f17 100644 --- a/src/packs/items/consumables/consumable_Mirror_of_Marigold_UFQVwgYOUZ88UxcH.json +++ b/src/packs/items/consumables/consumable_Mirror_of_Marigold_UFQVwgYOUZ88UxcH.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json b/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json index 90dd4fdc..68965de6 100644 --- a/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json +++ b/src/packs/items/consumables/consumable_Morphing_Clay_f1NHVSIHJJCIOaBl.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json b/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json index 342bf60b..e281399e 100644 --- a/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json +++ b/src/packs/items/consumables/consumable_Mythic_Dust_Zsh2AvZr8EkGtLyw.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json b/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json index 59e51e80..fdd98249 100644 --- a/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json +++ b/src/packs/items/consumables/consumable_Ogre_Musk_qr1bosjFcUfuwq4B.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json b/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json index ddff33f0..ba2f2b30 100644 --- a/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json +++ b/src/packs/items/consumables/consumable_Potion_of_Stability_dvL8oaxpEF6jKvYN.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json b/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json index 69edf2df..654470db 100644 --- a/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json +++ b/src/packs/items/consumables/consumable_Redthorn_Saliva_s2Exl2XFuoOhtIov.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Replication_Parchment_yJkwz4AP6yhGo8Vj.json b/src/packs/items/consumables/consumable_Replication_Parchment_yJkwz4AP6yhGo8Vj.json index 702d10ca..c2176ca0 100644 --- a/src/packs/items/consumables/consumable_Replication_Parchment_yJkwz4AP6yhGo8Vj.json +++ b/src/packs/items/consumables/consumable_Replication_Parchment_yJkwz4AP6yhGo8Vj.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Shrinking_Potion_HGixKenQwhyRAYNk.json b/src/packs/items/consumables/consumable_Shrinking_Potion_HGixKenQwhyRAYNk.json index a31a13f1..ed0e233e 100644 --- a/src/packs/items/consumables/consumable_Shrinking_Potion_HGixKenQwhyRAYNk.json +++ b/src/packs/items/consumables/consumable_Shrinking_Potion_HGixKenQwhyRAYNk.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Sleeping_Sap_XZavUVlHEvE2srEt.json b/src/packs/items/consumables/consumable_Sleeping_Sap_XZavUVlHEvE2srEt.json index d66ff42b..942f449e 100644 --- a/src/packs/items/consumables/consumable_Sleeping_Sap_XZavUVlHEvE2srEt.json +++ b/src/packs/items/consumables/consumable_Sleeping_Sap_XZavUVlHEvE2srEt.json @@ -85,6 +85,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Snap_Powder_cg6VtQ0eVZjDdcK0.json b/src/packs/items/consumables/consumable_Snap_Powder_cg6VtQ0eVZjDdcK0.json index 506cb1cf..1ae34797 100644 --- a/src/packs/items/consumables/consumable_Snap_Powder_cg6VtQ0eVZjDdcK0.json +++ b/src/packs/items/consumables/consumable_Snap_Powder_cg6VtQ0eVZjDdcK0.json @@ -85,6 +85,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Stamina_Potion_hf3k1POoVSooJyN2.json b/src/packs/items/consumables/consumable_Stamina_Potion_hf3k1POoVSooJyN2.json index f464ee61..3affdb8e 100644 --- a/src/packs/items/consumables/consumable_Stamina_Potion_hf3k1POoVSooJyN2.json +++ b/src/packs/items/consumables/consumable_Stamina_Potion_hf3k1POoVSooJyN2.json @@ -84,6 +84,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Stardrop_y4c1jrlHrf0wBWOq.json b/src/packs/items/consumables/consumable_Stardrop_y4c1jrlHrf0wBWOq.json index 3351c24f..be977305 100644 --- a/src/packs/items/consumables/consumable_Stardrop_y4c1jrlHrf0wBWOq.json +++ b/src/packs/items/consumables/consumable_Stardrop_y4c1jrlHrf0wBWOq.json @@ -71,6 +71,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json b/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json index 76d43d33..94baa901 100644 --- a/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json +++ b/src/packs/items/consumables/consumable_Stride_Potion_lNtcrkgFGOJNaroE.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Sun_Tree_Sap_kwexUzdM9wm1Qums.json b/src/packs/items/consumables/consumable_Sun_Tree_Sap_kwexUzdM9wm1Qums.json index cfe0a63c..2669a49b 100644 --- a/src/packs/items/consumables/consumable_Sun_Tree_Sap_kwexUzdM9wm1Qums.json +++ b/src/packs/items/consumables/consumable_Sun_Tree_Sap_kwexUzdM9wm1Qums.json @@ -64,6 +64,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Sweet_Moss_GrDrRqWgv7gvl9vn.json b/src/packs/items/consumables/consumable_Sweet_Moss_GrDrRqWgv7gvl9vn.json index 84663fb4..c17d6514 100644 --- a/src/packs/items/consumables/consumable_Sweet_Moss_GrDrRqWgv7gvl9vn.json +++ b/src/packs/items/consumables/consumable_Sweet_Moss_GrDrRqWgv7gvl9vn.json @@ -159,6 +159,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 62, diff --git a/src/packs/items/consumables/consumable_Unstable_Arcane_Shard_mUepnLbkvFk0ha4Z.json b/src/packs/items/consumables/consumable_Unstable_Arcane_Shard_mUepnLbkvFk0ha4Z.json index b6f18539..a5890ab0 100644 --- a/src/packs/items/consumables/consumable_Unstable_Arcane_Shard_mUepnLbkvFk0ha4Z.json +++ b/src/packs/items/consumables/consumable_Unstable_Arcane_Shard_mUepnLbkvFk0ha4Z.json @@ -91,6 +91,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Varik_Leaves_hvy5BkG3F6iOIXTx.json b/src/packs/items/consumables/consumable_Varik_Leaves_hvy5BkG3F6iOIXTx.json index 7e2f0c08..27e83aa4 100644 --- a/src/packs/items/consumables/consumable_Varik_Leaves_hvy5BkG3F6iOIXTx.json +++ b/src/packs/items/consumables/consumable_Varik_Leaves_hvy5BkG3F6iOIXTx.json @@ -85,6 +85,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Vial_of_Darksmoke_Nwv5ydGf0MWnzq1n.json b/src/packs/items/consumables/consumable_Vial_of_Darksmoke_Nwv5ydGf0MWnzq1n.json index b956477d..9de41467 100644 --- a/src/packs/items/consumables/consumable_Vial_of_Darksmoke_Nwv5ydGf0MWnzq1n.json +++ b/src/packs/items/consumables/consumable_Vial_of_Darksmoke_Nwv5ydGf0MWnzq1n.json @@ -40,6 +40,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json b/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json index 3fc572fd..195a46de 100644 --- a/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json +++ b/src/packs/items/consumables/consumable_Vial_of_Moondrip_VqEX5YwK5oL3r1t6.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 60, diff --git a/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json b/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json index 1bdd4bc0..7196b296 100644 --- a/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json +++ b/src/packs/items/consumables/consumable_Wingsprout_n10vozlmosVR6lo4.json @@ -45,6 +45,7 @@ } }, "consumeOnUse": true, + "destroyOnEmpty": true, "attribution": { "source": "Daggerheart SRD", "page": 61, diff --git a/styles/less/dialog/tag-team-dialog/sheet.less b/styles/less/dialog/tag-team-dialog/sheet.less index dc8f16dc..e72b4956 100644 --- a/styles/less/dialog/tag-team-dialog/sheet.less +++ b/styles/less/dialog/tag-team-dialog/sheet.less @@ -1,212 +1,4 @@ .daggerheart.dialog.dh-style.views.tag-team-dialog { - .team-container { - display: flex; - gap: 16px; - margin-bottom: 16px; - - .team-member-container { - display: flex; - flex-direction: column; - justify-content: space-between; - gap: 8px; - flex: 1; - - &.select-padding { - padding-bottom: 64px; - } - - &.inactive { - opacity: 0.4; - pointer-events: none; - } - - .data-container { - display: flex; - flex-direction: column; - gap: 8px; - width: 100%; - } - - .member-info { - display: flex; - align-items: center; - justify-content: space-between; - width: 100%; - - img { - height: 64px; - border-radius: 6px; - border: 1px solid light-dark(@dark-blue, @golden); - } - - .member-name { - flex: 1; - text-align: center; - font-size: var(--font-size-18); - } - } - - .roll-setup { - width: 100%; - } - - .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; - - &::before, - &::after { - color: light-dark(@dark-blue, @golden); - 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-selection { - position: relative; - top: -80px; - - &.rendered { - margin-bottom: -56px; - } - - .roll-selection-container { - display: flex; - - .select-roll-button { - margin-top: 8px; - flex: 1; - display: flex; - justify-content: center; - - i { - color: light-dark(@dark-blue, @golden); - font-size: 48px; - - &.inactive { - opacity: 0.4; - } - } - } - } - } - .tag-team-roll-container { display: flex; flex-direction: column; @@ -217,6 +9,193 @@ pointer-events: none; } + .team-container { + display: flex; + gap: 16px; + + .member-container { + display: flex; + flex-direction: column; + justify-content: space-between; + gap: 8px; + flex: 1; + + &.inactive { + opacity: 0.4; + pointer-events: none; + } + + .data-container { + display: flex; + flex-direction: column; + gap: 8px; + width: 100%; + } + + .member-info { + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + + img { + height: 64px; + border-radius: 6px; + border: 1px solid light-dark(@dark-blue, @golden); + } + + .member-name { + flex: 1; + text-align: center; + font-size: var(--font-size-18); + } + } + + .roll-setup { + width: 100%; + } + + .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; + + &::before, + &::after { + color: light-dark(@dark-blue, @golden); + 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; + } + } + + .select-roll-button { + margin-top: 8px; + + i { + color: light-dark(@dark-blue, @golden); + font-size: 48px; + + &.inactive { + opacity: 0.4; + } + } + } + } + } + .results-container { display: flex; flex-direction: column; @@ -264,9 +243,9 @@ grid-column: span 2; } } - } - .hint { - text-align: center; + .hint { + text-align: center; + } } } diff --git a/styles/less/global/elements.less b/styles/less/global/elements.less index 793c8164..c33557b1 100755 --- a/styles/less/global/elements.less +++ b/styles/less/global/elements.less @@ -293,20 +293,6 @@ } } - &.optional, - &.one-column.optional { - padding-top: 0; - padding-bottom: 4px; - min-height: auto; - row-gap: 0; - - legend { - display: flex; - align-items: center; - padding-left: 3px; - } - } - .list-w-img { padding: 5px; label { @@ -483,10 +469,6 @@ &.even { grid-template-columns: 1fr 1fr; } - - &.full-width { - width: 100%; - } } .three-columns { diff --git a/styles/less/sheets/activeEffects/activeEffects.less b/styles/less/sheets/activeEffects/activeEffects.less index afa23b72..b6fa98db 100644 --- a/styles/less/sheets/activeEffects/activeEffects.less +++ b/styles/less/sheets/activeEffects/activeEffects.less @@ -46,6 +46,16 @@ } .armor-change-container { + padding-top: 0; + padding-bottom: 4px; + row-gap: 0; + + legend { + display: flex; + align-items: center; + padding-left: 3px; + } + header { padding: 0; left: -0.25rem; // TODO: Find why this header is offset 0.25rem to the right so this can be removed. diff --git a/styles/less/ui/effects-display/sheet.less b/styles/less/ui/effects-display/sheet.less index 17d9889f..1331b094 100644 --- a/styles/less/ui/effects-display/sheet.less +++ b/styles/less/ui/effects-display/sheet.less @@ -35,21 +35,6 @@ color: @golden; filter: drop-shadow(0 0 3px black); } - - .stacking-value { - position: absolute; - top: 4px; - right: 4px; - font-size: 16px; - font-weight: bold; - font-variant-numeric: tabular-nums; - color: @golden; - background: black; - padding: 1px; - border-radius: 6px; - border: 1px solid @golden; - pointer-events: none; - } } } } diff --git a/styles/less/ux/tooltip/bordered-tooltip.less b/styles/less/ux/tooltip/bordered-tooltip.less index abec93b7..b3a5ed29 100644 --- a/styles/less/ux/tooltip/bordered-tooltip.less +++ b/styles/less/ux/tooltip/bordered-tooltip.less @@ -6,7 +6,6 @@ .daggerheart.dh-style.tooltip { display: flex; flex-direction: column; - align-items: start; text-align: start; width: 100%; gap: 5px; @@ -14,7 +13,6 @@ border-radius: 3px; .tooltip-header { - width: 100%; display: flex; flex-direction: column; align-items: center; @@ -37,48 +35,12 @@ } } - .effect-stacks-outer-container { - display: flex; - flex-direction: column; - gap: 4px; - width: 100%; - - .effect-stacks-title { - font-size: var(--font-size-20); - font-weight: bold; - text-align: center; - } - - .effect-stacks-container { - display: flex; - justify-content: space-between; - - .effect-stacks-inner-container { - display: flex; - flex-direction: column; - gap: 2px; - - .effect-stack-title { - font-weight: bold; - } - } - } - } - - .close-hints { - margin-top: 0.5rem; - display: flex; - flex-direction: column; - gap: 4px; - - .close-hint { - border-radius: 3px; - padding: 3px; - background: @rustic-brown-80; - color: @golden; - font-size: 12px; - margin: 0; - } + .close-hint { + border-radius: 3px; + padding: 3px; + background: @rustic-brown-80; + color: @golden; + font-size: 12px; } .duration-container { diff --git a/templates/actionTypes/damage.hbs b/templates/actionTypes/damage.hbs index 9e7c2884..6f159a2d 100644 --- a/templates/actionTypes/damage.hbs +++ b/templates/actionTypes/damage.hbs @@ -16,52 +16,50 @@ {{formField directField value=source.direct name=(concat path "damage.direct") localize=true classes="checkbox"}} {{/unless}} - - {{!-- Handlebars uses Symbol.Iterator to produce index|key. This isn't compatible with our parts object, so we instead use applyTo, which is the same value --}} - {{#each source.parts as |dmg|}} + {{#each source.parts as |dmg key|}}