diff --git a/module.json b/module.json index 855fdb0..1dc1fb7 100644 --- a/module.json +++ b/module.json @@ -100,9 +100,9 @@ "type": "module", "compatibility": [ { - "minimum": "1.3.0", - "maximum": "1.3", - "verified": "1.3.0" + "minimum": "1.4.0", + "maximum": "1.4", + "verified": "1.4.0" } ] } diff --git a/scripts/action-handler.js b/scripts/action-handler.js index 8d66606..563ad43 100644 --- a/scripts/action-handler.js +++ b/scripts/action-handler.js @@ -1,5 +1,5 @@ // System Module Imports -import { ACTIVATION_TYPE_ICON, ACTION_TYPE, PREPARED_ICON, PROFICIENCY_LEVEL_ICON, SUBCATEGORY } from './constants.js' +import { ACTIVATION_TYPE_ICON, ACTION_TYPE, PREPARED_ICON, PROFICIENCY_LEVEL_ICON, GROUP } from './constants.js' import { Utils } from './utils.js' export let ActionHandler = null @@ -22,11 +22,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { showUnequippedItems = null showUnpreparedSpells = null - // Initialize subcategoryIds variables - activationSubcategoryIds = null - featureSubcategoryIds = null - inventorySubcategoryIds = null - spellSubcategoryIds = null + // Initialize groupIds variables + activationgroupIds = null + featuregroupIds = null + inventorygroupIds = null + spellgroupIds = null // Initialize action variables featureActions = null @@ -36,10 +36,10 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { /** * Build System Actions * @override - * @param {array} subcategoryIds + * @param {array} groupIds * @returns {object} */ - async buildSystemActions (subcategoryIds) { + async buildSystemActions (groupIds) { // Set actor and token variables this.actors = (!this.actor) ? this._getActors() : [this.actor] this.tokens = (!this.token) ? this._getTokens() : [this.token] @@ -49,7 +49,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { if (this.actor) { let items = this.actor.items items = this._discardSlowItems(items) - items = this.sortItemsByName(items) + items = coreModule.api.Utils.sortItemsByName(items) this.items = items } @@ -61,7 +61,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { this.showUnequippedItems = Utils.getSetting('showUnequippedItems') this.showUnpreparedSpells = Utils.getSetting('showUnpreparedSpells') - this.activationSubcategoryIds = [ + this.activationgroupIds = [ 'actions', 'bonus-actions', 'crew-actions', @@ -71,7 +71,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { 'other-actions' ] - this.featureSubcategoryIds = [ + this.featuregroupIds = [ 'active-features', 'passive-features', 'background-features', @@ -96,7 +96,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { 'superior-hunters-defense' ] - this.spellSubcategoryIds = [ + this.spellgroupIds = [ 'cantrips', '1st-level-spells', '2nd-level-spells', @@ -113,7 +113,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { ] if (this.actorType === 'character' || this.actorType === 'npc') { - this.inventorySubcategoryIds = [ + this.inventorygroupIds = [ 'equipped', 'consumables', 'containers', @@ -127,7 +127,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { this._buildCharacterActions() } if (this.actorType === 'vehicle') { - this.inventorySubcategoryIds = [ + this.inventorygroupIds = [ 'consumables', 'equipment', 'tools', @@ -198,9 +198,9 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * Build Abilities * @private * @param {string} actionType - * @param {string} subcategoryId + * @param {string} groupId */ - _buildAbilities (actionType, subcategoryId) { + _buildAbilities (actionType, groupId) { // Get abilities const abilities = (!this.actor) ? game.dnd5e.config.abilities : this.actor.system.abilities @@ -219,29 +219,29 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { const actionTypeName = `${coreModule.api.Utils.i18n(ACTION_TYPE[actionType])}: ` ?? '' const listName = `${actionTypeName}${game.dnd5e.config.abilities[abilityId]}` const encodedValue = [actionType, abilityId].join(this.delimiter) - const icon = (subcategoryId !== 'checks') ? this._getProficiencyIcon(abilities[abilityId].proficient) : '' + const icon1 = (groupId !== 'checks') ? this._getProficiencyIcon(abilities[abilityId].proficient) : '' return { id, name, encodedValue, - icon, + icon1, listName } }) - // Create subcategory data - const subcategoryData = { id: subcategoryId, type: 'system' } + // Create group data + const groupData = { id: groupId, type: 'system' } // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + this.addActions(actions, groupData) } - async buildActivations (items, subcategoryData, actionType = 'item') { + async buildActivations (items, groupData, actionType = 'item') { // Create map of items according to activation type const activationItems = new Map() - // Create subcategory mappings - const subcategoryMappings = { + // Create group mappings + const groupMappings = { actions: 'action', 'bonus-actions': 'bonus', 'crew-actions': 'crew', @@ -261,27 +261,27 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { activationItems.get(activationTypeOther).set(key, value) } - // Loop through action subcategory ids - for (const subcategoryId of this.activationSubcategoryIds) { - const activationType = subcategoryMappings[subcategoryId] + // Loop through action group ids + for (const groupId of this.activationgroupIds) { + const activationType = groupMappings[groupId] // Skip if no items exist if (!activationItems.has(activationType)) continue - // Clone and add to subcategory data - const subcategoryDataClone = { ...subcategoryData, id: `${subcategoryId}+${subcategoryData.id}`, type: 'system-derived' } + // Clone and add to group data + const groupDataClone = { ...groupData, id: `${groupId}+${groupData.id}`, type: 'system-derived' } - // Create parent subcategory data - const parentSubcategoryData = { id: subcategoryId, type: 'system' } + // Create parent group data + const parentgroupData = { id: groupId, type: 'system' } - // Add subcategory to action list - await this.addSubcategoryToActionList(parentSubcategoryData, subcategoryDataClone) + // Add group to HUD + await this.addGroup(groupDataClone, parentgroupData) - // Add spell slot info to subcategory - this.addSubcategoryInfo(subcategoryData) + // Add spell slot info to group + this.addGroupInfo(groupData) // Build actions - this._buildActions(activationItems.get(activationType), subcategoryDataClone, actionType) + this._buildActions(activationItems.get(activationType), groupDataClone, actionType) } } @@ -334,11 +334,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } }) - // Create subcategory data - const subcategoryData = { id: 'combat', type: 'system' } + // Create group data + const groupData = { id: 'combat', type: 'system' } - // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + // Add actions to HUD + this.addActions(actions, groupData) } /** @@ -383,11 +383,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } }) - // Create subcategory data - const subcategoryData = { id: 'conditions', type: 'system' } + // Create group data + const groupData = { id: 'conditions', type: 'system' } - // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + // Add actions to HUD + this.addActions(actions, groupData) } /** @@ -446,29 +446,29 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { const featuresMap = new Map() const featureTypes = [ - { type: 'background', subcategoryId: 'background-features' }, - { type: 'class', subcategoryId: 'class-features' }, - { type: 'monster', subcategoryId: 'monster-features' }, - { type: 'race', subcategoryId: 'race-features' }, - { type: 'feats', subcategoryId: 'feats' } + { type: 'background', groupId: 'background-features' }, + { type: 'class', groupId: 'class-features' }, + { type: 'monster', groupId: 'monster-features' }, + { type: 'race', groupId: 'race-features' }, + { type: 'feats', groupId: 'feats' } ] const classFeatureTypes = [ - { type: 'artificerInfusion', subcategoryId: 'artificer-infusions' }, - { type: 'channelDivinity', subcategoryId: 'channel-divinity' }, - { type: 'defensiveTactic', subcategoryId: 'defensive-tactics' }, - { type: 'eldritchInvocation', subcategoryId: 'eldritch-invocations' }, - { type: 'elementalDiscipline', subcategoryId: 'elemental-disciplines' }, - { type: 'fightingStyle', subcategoryId: 'fighting-styles' }, - { type: 'huntersPrey', subcategoryId: 'hunters-prey' }, - { type: 'ki', subcategoryId: 'ki-abilities' }, - { type: 'maneuver', subcategoryId: 'maneuvers' }, - { type: 'metamagic', subcategoryId: 'metamagic-options' }, - { type: 'multiattack', subcategoryId: 'multiattacks' }, - { type: 'pact', subcategoryId: 'pact-boons' }, - { type: 'psionicPower', subcategoryId: 'psionic-powers' }, - { type: 'rune', subcategoryId: 'runes' }, - { type: 'superiorHuntersDefense', subcategoryId: 'superior-hunters-defense' } + { type: 'artificerInfusion', groupId: 'artificer-infusions' }, + { type: 'channelDivinity', groupId: 'channel-divinity' }, + { type: 'defensiveTactic', groupId: 'defensive-tactics' }, + { type: 'eldritchInvocation', groupId: 'eldritch-invocations' }, + { type: 'elementalDiscipline', groupId: 'elemental-disciplines' }, + { type: 'fightingStyle', groupId: 'fighting-styles' }, + { type: 'huntersPrey', groupId: 'hunters-prey' }, + { type: 'ki', groupId: 'ki-abilities' }, + { type: 'maneuver', groupId: 'maneuvers' }, + { type: 'metamagic', groupId: 'metamagic-options' }, + { type: 'multiattack', groupId: 'multiattacks' }, + { type: 'pact', groupId: 'pact-boons' }, + { type: 'psionicPower', groupId: 'psionic-powers' }, + { type: 'rune', groupId: 'runes' }, + { type: 'superiorHuntersDefense', groupId: 'superior-hunters-defense' } ] for (const [key, value] of feats) { @@ -485,45 +485,45 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { featuresMap.get('passive-features').set(key, value) } for (const featureType of featureTypes) { - const subcategoryId = featureType.subcategoryId + const groupId = featureType.groupId if (featureType.type === type) { - if (!featuresMap.has(subcategoryId)) featuresMap.set(subcategoryId, new Map()) - featuresMap.get(subcategoryId).set(key, value) + if (!featuresMap.has(groupId)) featuresMap.set(groupId, new Map()) + featuresMap.get(groupId).set(key, value) } } for (const featureType of classFeatureTypes) { - const subcategoryId = featureType.subcategoryId + const groupId = featureType.groupId if (subType && featureType.type === subType) { - if (!featuresMap.has(subcategoryId)) featuresMap.set(subcategoryId, new Map()) - featuresMap.get(subcategoryId).set(key, value) + if (!featuresMap.has(groupId)) featuresMap.set(groupId, new Map()) + featuresMap.get(groupId).set(key, value) } } } - // Create subcategory name mappings - const subcategoryNameMappings = { + // Create group name mappings + const groupNameMappings = { 'active-features': coreModule.api.Utils.i18n('tokenActionHud.dnd5e.activeFeatures'), 'passive-features': coreModule.api.Utils.i18n('tokenActionHud.dnd5e.passiveFeatures') } - // Loop through inventory subcateogry ids - for (const subcategoryId of this.featureSubcategoryIds) { - if (!featuresMap.has(subcategoryId)) continue + // Loop through inventory groups ids + for (const groupId of this.featuregroupIds) { + if (!featuresMap.has(groupId)) continue - // Create subcategory data - const subcategoryData = { - id: subcategoryId, - name: subcategoryNameMappings[subcategoryId] ?? '', + // Create group data + const groupData = { + id: groupId, + name: groupNameMappings[groupId] ?? '', type: 'system' } - const features = featuresMap.get(subcategoryId) + const features = featuresMap.get(groupId) // Build actions - this._buildActions(features, subcategoryData, actionType) + this._buildActions(features, groupData, actionType) // Build activations - if (subcategoryNameMappings[subcategoryId]) this.buildActivations(features, subcategoryData, actionType) + if (groupNameMappings[groupId]) this.buildActivations(features, groupData, actionType) } } @@ -585,8 +585,8 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } } - // Create subcategory name mappings - const subcategoryNameMappings = { + // Create group name mappings + const groupNameMappings = { equipped: coreModule.api.Utils.i18n('DND5E.Equipped'), unequipped: coreModule.api.Utils.i18n('DND5E.Unequipped'), consumables: coreModule.api.Utils.i18n('ITEM.TypeConsumablePl'), @@ -598,23 +598,23 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } // Loop through inventory subcateogry ids - for (const subcategoryId of this.inventorySubcategoryIds) { - if (!inventoryMap.has(subcategoryId)) continue + for (const groupId of this.inventorygroupIds) { + if (!inventoryMap.has(groupId)) continue - // Create subcategory data - const subcategoryData = { - id: subcategoryId, - name: subcategoryNameMappings[subcategoryId], + // Create group data + const groupData = { + id: groupId, + name: groupNameMappings[groupId], type: 'system' } - const inventory = inventoryMap.get(subcategoryId) + const inventory = inventoryMap.get(groupId) // Build actions - this._buildActions(inventory, subcategoryData) + this._buildActions(inventory, groupData) // Build activations - if (this.activationSubcategoryIds) this.buildActivations(inventory, subcategoryData) + if (this.activationgroupIds) this.buildActivations(inventory, groupData) } } @@ -651,11 +651,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } }) - // Create subcategory data - const subcategoryData = { id: 'rests', type: 'system' } + // Create group data + const groupData = { id: 'rests', type: 'system' } - // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + // Add actions to HUD + this.addActions(actions, groupData) } /** @@ -681,12 +681,15 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { const actionTypeName = `${coreModule.api.Utils.i18n(ACTION_TYPE[actionType])}: ` ?? '' const listName = `${actionTypeName}${game.dnd5e.config.skills[id].label}` const encodedValue = [actionType, id].join(this.delimiter) - const icon = this._getProficiencyIcon(skills[id].value) + const icon1 = this._getProficiencyIcon(skills[id].value) + const mod = skills[id].mod + const info1 = (this.actor) ? { text: (mod || mod === 0) ? `${(mod >= 0) ? '+' : ''}${mod}` : '' } : '' return { id, name, encodedValue, - icon, + icon1, + info1, listName } } catch (error) { @@ -696,11 +699,11 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { }) .filter((skill) => !!skill) - // Create subcategory data - const subcategoryData = { id: 'skills', type: 'system' } + // Create group data + const groupData = { id: 'skills', type: 'system' } - // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + // Add actions to HUD + this.addActions(actions, groupData) } /** @@ -818,7 +821,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { spellSlots[pactSpellEquivalent][1].slotsAvailable = true } - const subcategoryMappings = { + const groupMappings = { '1st-level-spells': { spellMode: 1, name: coreModule.api.Utils.i18n('tokenActionHud.dnd5e.1stLevelSpells') }, '2nd-level-spells': { spellMode: 2, name: coreModule.api.Utils.i18n('tokenActionHud.dnd5e.2ndLevelSpells') }, '3rd-level-spells': { spellMode: 3, name: coreModule.api.Utils.i18n('tokenActionHud.dnd5e.3rdLevelSpells') }, @@ -836,12 +839,12 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { const spellSlotModes = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'pact'] - for (const subcategoryId of this.spellSubcategoryIds) { - const spellMode = subcategoryMappings[subcategoryId].spellMode - const subcategoryName = subcategoryMappings[subcategoryId].name + for (const groupId of this.spellgroupIds) { + const spellMode = groupMappings[groupId].spellMode + const groupName = groupMappings[groupId].name // Skip if no spells exist - if (!spellsMap.has(subcategoryId)) continue + if (!spellsMap.has(groupId)) continue const levelInfo = (spellMode === 'pact') ? pactSlot[1] : spellSlots.find(spellSlot => spellSlot[0] === `spell${spellMode}`)?.[1] const slots = levelInfo?.value @@ -851,26 +854,26 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { // Skip if spells require spell slots and none are available if (!slotsAvailable && spellSlotModes.includes(spellMode)) continue - // Create subcategory data= - const subcategoryInfo = {} - subcategoryInfo.info1 = { class: 'tah-spotlight', text: (max >= 0) ? `${slots}/${max}` : '' } - const subcategoryData = { - id: subcategoryId, - name: subcategoryName, + // Create group data= + const groupInfo = {} + groupInfo.info1 = { class: 'tah-spotlight', text: (max >= 0) ? `${slots}/${max}` : '' } + const groupData = { + id: groupId, + name: groupName, type: 'system', - info: subcategoryInfo + info: groupInfo } - // Add spell slot info to subcategory - this.addSubcategoryInfo(subcategoryData) + // Add spell slot info to group + this.addGroupInfo(groupData) - const spells = spellsMap.get(subcategoryId) + const spells = spellsMap.get(groupId) // Build actions - this._buildActions(spells, subcategoryData, actionType) + this._buildActions(spells, groupData, actionType) // Build activations - if (this.activationSubcategoryIds) { this.buildActivations(spells, subcategoryData, actionType) } + if (this.activationgroupIds) { this.buildActivations(spells, groupData, actionType) } } } @@ -918,33 +921,33 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } }) - // Crreate subcategory data - const subcategoryData = { id: 'utility', type: 'system' } + // Crreate group data + const groupData = { id: 'utility', type: 'system' } - // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + // Add actions to HUD + this.addActions(actions, groupData) } /** * Get Actions * @private * @param {object} items - * @param {object} subcategoryData + * @param {object} groupData * @param {string} actionType */ - _buildActions (items, subcategoryData, actionType = 'item') { + _buildActions (items, groupData, actionType = 'item') { // Exit if there are no items if (items.size === 0) return - // Exit if there is no subcategoryId - const subcategoryId = (typeof subcategoryData === 'string' ? subcategoryData : subcategoryData?.id) - if (!subcategoryId) return + // Exit if there is no groupId + const groupId = (typeof groupData === 'string' ? groupData : groupData?.id) + if (!groupId) return // Get actions const actions = [...items].map(item => this._getAction(actionType, item[1])) // Add actions to action list - this.addActionsToActionList(actions, subcategoryData) + this.addActions(actions, groupData) } /** diff --git a/scripts/constants.js b/scripts/constants.js index d5f849f..09fa569 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -15,7 +15,7 @@ export const CORE_MODULE = { /** * Core module version required by the system module */ -export const REQUIRED_CORE_MODULE_VERSION = '1.3' +export const REQUIRED_CORE_MODULE_VERSION = '1.4' /** * Action type @@ -72,66 +72,66 @@ export const PROFICIENCY_LEVEL_ICON = { 2: 'fas fa-check-double' } -export const SUBCATEGORY = { - _1stLevelSpells: { id: '1st-level-spells', name: 'tokenActionHud.dnd5e.1stLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _2ndLevelSpells: { id: '2nd-level-spells', name: 'tokenActionHud.dnd5e.2ndLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _3rdLevelSpells: { id: '3rd-level-spells', name: 'tokenActionHud.dnd5e.3rdLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _4thLevelSpells: { id: '4th-level-spells', name: 'tokenActionHud.dnd5e.4thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _5thLevelSpells: { id: '5th-level-spells', name: 'tokenActionHud.dnd5e.5thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _6thLevelSpells: { id: '6th-level-spells', name: 'tokenActionHud.dnd5e.6thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _7thLevelSpells: { id: '7th-level-spells', name: 'tokenActionHud.dnd5e.7thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _8thLevelSpells: { id: '8th-level-spells', name: 'tokenActionHud.dnd5e.8thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - _9thLevelSpells: { id: '9th-level-spells', name: 'tokenActionHud.dnd5e.9thLevelSpells', type: 'system', hasDerivedSubcategories: false }, - abilities: { id: 'abilities', name: 'tokenActionHud.dnd5e.abilities', type: 'system', hasDerivedSubcategories: false }, - actions: { id: 'actions', name: 'DND5E.ActionPl', type: 'system', hasDerivedSubcategories: true }, - activeFeatures: { id: 'active-features', name: 'tokenActionHud.dnd5e.activeFeatures', type: 'system', hasDerivedSubcategories: false }, - artificerInfusions: { id: 'artificer-infusions', name: 'tokenActionHud.dnd5e.artificerInfusions', type: 'system', hasDerivedSubcategories: false }, - atWillSpells: { id: 'at-will-spells', name: 'tokenActionHud.dnd5e.atWillSpells', type: 'system', hasDerivedSubcategories: false }, - backgroundFeatures: { id: 'background-features', name: 'tokenActionHud.dnd5e.backgroundFeatures', type: 'system', hasDerivedSubcategories: false }, - bonusActions: { id: 'bonus-actions', name: 'tokenActionHud.dnd5e.bonusActions', type: 'system', hasDerivedSubcategories: true }, - cantrips: { id: 'cantrips', name: 'tokenActionHud.dnd5e.cantrips', type: 'system', hasDerivedSubcategories: false }, - channelDivinity: { id: 'channel-divinity', name: 'tokenActionHud.dnd5e.channelDivinity', type: 'system', hasDerivedSubcategories: false }, - checks: { id: 'checks', name: 'tokenActionHud.dnd5e.checks', type: 'system', hasDerivedSubcategories: false }, - classFeatures: { id: 'class-features', name: 'tokenActionHud.dnd5e.classFeatures', type: 'system', hasDerivedSubcategories: false }, - combat: { id: 'combat', name: 'tokenActionHud.combat', type: 'system', hasDerivedSubcategories: false }, - conditions: { id: 'conditions', name: 'tokenActionHud.dnd5e.conditions', type: 'system', hasDerivedSubcategories: false }, - consumables: { id: 'consumables', name: 'ITEM.TypeConsumablePl', type: 'system', hasDerivedSubcategories: false }, - containers: { id: 'containers', name: 'ITEM.TypeContainerPl', type: 'system', hasDerivedSubcategories: false }, - crewActions: { id: 'crew-actions', name: 'tokenActionHud.dnd5e.crewActions', type: 'system', hasDerivedSubcategories: true }, - defensiveTactics: { id: 'defensive-tactics', name: 'tokenActionHud.dnd5e.defensiveTactics', type: 'system', hasDerivedSubcategories: false }, - eldritchInvocations: { id: 'eldritch-invocations', name: 'tokenActionHud.dnd5e.eldritchInvocations', type: 'system', hasDerivedSubcategories: false }, - elementalDisciplines: { id: 'elemental-disciplines', name: 'tokenActionHud.dnd5e.elementalDisciplines', type: 'system', hasDerivedSubcategories: false }, - equipment: { id: 'equipment', name: 'ITEM.TypeEquipmentPl', type: 'system', hasDerivedSubcategories: false }, - equipped: { id: 'equipped', name: 'DND5E.Equipped', type: 'system', hasDerivedSubcategories: false }, - feats: { id: 'feats', name: 'tokenActionHud.dnd5e.feats', type: 'system', hasDerivedSubcategories: false }, - fightingStyles: { id: 'fighting-styles', name: 'tokenActionHud.dnd5e.fightingStyles', type: 'system', hasDerivedSubcategories: false }, - huntersPrey: { id: 'hunters-prey', name: 'tokenActionHud.dnd5e.huntersPrey', type: 'system', hasDerivedSubcategories: false }, - innateSpells: { id: 'innate-spells', name: 'tokenActionHud.dnd5e.innateSpells', type: 'system', hasDerivedSubcategories: false }, - kiAbilities: { id: 'ki-abilities', name: 'tokenActionHud.dnd5e.kiAbilities', type: 'system', hasDerivedSubcategories: false }, - lairActions: { id: 'lair-actions', name: 'tokenActionHud.dnd5e.lairActions', type: 'system', hasDerivedSubcategories: true }, - legendaryActions: { id: 'legendary-actions', name: 'tokenActionHud.dnd5e.legendaryActions', type: 'system', hasDerivedSubcategories: true }, - loot: { id: 'loot', name: 'ITEM.TypeLootPl', type: 'system', hasDerivedSubcategories: false }, - maneuvers: { id: 'maneuvers', name: 'tokenActionHud.dnd5e.maneuvers', type: 'system', hasDerivedSubcategories: false }, - metamagicOptions: { id: 'metamagic-options', name: 'tokenActionHud.dnd5e.metamagicOptions', type: 'system', hasDerivedSubcategories: false }, - monsterFeatures: { id: 'monster-features', name: 'tokenActionHud.dnd5e.monsterFeatures', type: 'system', hasDerivedSubcategories: false }, - multiattacks: { id: 'multiattacks', name: 'tokenActionHud.dnd5e.multiattacks', type: 'system', hasDerivedSubcategories: false }, - otherActions: { id: 'other-actions', name: 'tokenActionHud.dnd5e.otherActions', type: 'system', hasDerivedSubcategories: true }, - pactBoons: { id: 'pact-boons', name: 'tokenActionHud.dnd5e.pactBoons', type: 'system', hasDerivedSubcategories: false }, - pactSpells: { id: 'pact-spells', name: 'tokenActionHud.dnd5e.pactSpells', type: 'system', hasDerivedSubcategories: false }, - passiveEffects: { id: 'passive-effects', name: 'DND5E.EffectPassive', type: 'system', hasDerivedSubcategories: false }, - passiveFeatures: { id: 'passive-features', name: 'tokenActionHud.dnd5e.passiveFeatures', type: 'system', hasDerivedSubcategories: false }, - psionicPowers: { id: 'psionic-powers', name: 'tokenActionHud.dnd5e.psionicPowers', type: 'system', hasDerivedSubcategories: false }, - raceFeatures: { id: 'race-features', name: 'tokenActionHud.dnd5e.raceFeatures', type: 'system', hasDerivedSubcategories: false }, - reactions: { id: 'reactions', name: 'DND5E.ReactionPl', type: 'system', hasDerivedSubcategories: true }, - rests: { id: 'rests', name: 'tokenActionHud.dnd5e.rests', type: 'system', hasDerivedSubcategories: false }, - runes: { id: 'runes', name: 'tokenActionHud.dnd5e.runes', type: 'system', hasDerivedSubcategories: false }, - saves: { id: 'saves', name: 'DND5E.ClassSaves', type: 'system', hasDerivedSubcategories: false }, - skills: { id: 'skills', name: 'tokenActionHud.dnd5e.skills', type: 'system', hasDerivedSubcategories: false }, - superiorHuntersDefense: { id: 'superior-hunters-defense', name: 'tokenActionHud.dnd5e.superiorHuntersDefense', type: 'system', hasDerivedSubcategories: false }, - temporaryEffects: { id: 'temporary-effects', name: 'DND5E.EffectTemporary', type: 'system', hasDerivedSubcategories: false }, - token: { id: 'token', name: 'tokenActionHud.token', type: 'system', hasDerivedSubcategories: false }, - tools: { id: 'tools', name: 'ITEM.TypeToolPl', type: 'system', hasDerivedSubcategories: false }, - unequipped: { id: 'unequipped', name: 'DND5E.Unequipped', type: 'system', hasDerivedSubcategories: false }, - utility: { id: 'utility', name: 'tokenActionHud.utility', type: 'system', hasDerivedSubcategories: false }, - weapons: { id: 'weapons', name: 'ITEM.TypeWeaponPl', type: 'system', hasDerivedSubcategories: false } +export const GROUP = { + _1stLevelSpells: { id: '1st-level-spells', name: 'tokenActionHud.dnd5e.1stLevelSpells', type: 'system' }, + _2ndLevelSpells: { id: '2nd-level-spells', name: 'tokenActionHud.dnd5e.2ndLevelSpells', type: 'system' }, + _3rdLevelSpells: { id: '3rd-level-spells', name: 'tokenActionHud.dnd5e.3rdLevelSpells', type: 'system' }, + _4thLevelSpells: { id: '4th-level-spells', name: 'tokenActionHud.dnd5e.4thLevelSpells', type: 'system' }, + _5thLevelSpells: { id: '5th-level-spells', name: 'tokenActionHud.dnd5e.5thLevelSpells', type: 'system' }, + _6thLevelSpells: { id: '6th-level-spells', name: 'tokenActionHud.dnd5e.6thLevelSpells', type: 'system' }, + _7thLevelSpells: { id: '7th-level-spells', name: 'tokenActionHud.dnd5e.7thLevelSpells', type: 'system' }, + _8thLevelSpells: { id: '8th-level-spells', name: 'tokenActionHud.dnd5e.8thLevelSpells', type: 'system' }, + _9thLevelSpells: { id: '9th-level-spells', name: 'tokenActionHud.dnd5e.9thLevelSpells', type: 'system' }, + abilities: { id: 'abilities', name: 'tokenActionHud.dnd5e.abilities', type: 'system' }, + actions: { id: 'actions', name: 'DND5E.ActionPl', type: 'system' }, + activeFeatures: { id: 'active-features', name: 'tokenActionHud.dnd5e.activeFeatures', type: 'system' }, + artificerInfusions: { id: 'artificer-infusions', name: 'tokenActionHud.dnd5e.artificerInfusions', type: 'system' }, + atWillSpells: { id: 'at-will-spells', name: 'tokenActionHud.dnd5e.atWillSpells', type: 'system' }, + backgroundFeatures: { id: 'background-features', name: 'tokenActionHud.dnd5e.backgroundFeatures', type: 'system' }, + bonusActions: { id: 'bonus-actions', name: 'tokenActionHud.dnd5e.bonusActions', type: 'system' }, + cantrips: { id: 'cantrips', name: 'tokenActionHud.dnd5e.cantrips', type: 'system' }, + channelDivinity: { id: 'channel-divinity', name: 'tokenActionHud.dnd5e.channelDivinity', type: 'system' }, + checks: { id: 'checks', name: 'tokenActionHud.dnd5e.checks', type: 'system' }, + classFeatures: { id: 'class-features', name: 'tokenActionHud.dnd5e.classFeatures', type: 'system' }, + combat: { id: 'combat', name: 'tokenActionHud.combat', type: 'system' }, + conditions: { id: 'conditions', name: 'tokenActionHud.dnd5e.conditions', type: 'system' }, + consumables: { id: 'consumables', name: 'ITEM.TypeConsumablePl', type: 'system' }, + containers: { id: 'containers', name: 'ITEM.TypeContainerPl', type: 'system' }, + crewActions: { id: 'crew-actions', name: 'tokenActionHud.dnd5e.crewActions', type: 'system' }, + defensiveTactics: { id: 'defensive-tactics', name: 'tokenActionHud.dnd5e.defensiveTactics', type: 'system' }, + eldritchInvocations: { id: 'eldritch-invocations', name: 'tokenActionHud.dnd5e.eldritchInvocations', type: 'system' }, + elementalDisciplines: { id: 'elemental-disciplines', name: 'tokenActionHud.dnd5e.elementalDisciplines', type: 'system' }, + equipment: { id: 'equipment', name: 'ITEM.TypeEquipmentPl', type: 'system' }, + equipped: { id: 'equipped', name: 'DND5E.Equipped', type: 'system' }, + feats: { id: 'feats', name: 'tokenActionHud.dnd5e.feats', type: 'system' }, + fightingStyles: { id: 'fighting-styles', name: 'tokenActionHud.dnd5e.fightingStyles', type: 'system' }, + huntersPrey: { id: 'hunters-prey', name: 'tokenActionHud.dnd5e.huntersPrey', type: 'system' }, + innateSpells: { id: 'innate-spells', name: 'tokenActionHud.dnd5e.innateSpells', type: 'system' }, + kiAbilities: { id: 'ki-abilities', name: 'tokenActionHud.dnd5e.kiAbilities', type: 'system' }, + lairActions: { id: 'lair-actions', name: 'tokenActionHud.dnd5e.lairActions', type: 'system' }, + legendaryActions: { id: 'legendary-actions', name: 'tokenActionHud.dnd5e.legendaryActions', type: 'system' }, + loot: { id: 'loot', name: 'ITEM.TypeLootPl', type: 'system' }, + maneuvers: { id: 'maneuvers', name: 'tokenActionHud.dnd5e.maneuvers', type: 'system' }, + metamagicOptions: { id: 'metamagic-options', name: 'tokenActionHud.dnd5e.metamagicOptions', type: 'system' }, + monsterFeatures: { id: 'monster-features', name: 'tokenActionHud.dnd5e.monsterFeatures', type: 'system' }, + multiattacks: { id: 'multiattacks', name: 'tokenActionHud.dnd5e.multiattacks', type: 'system' }, + otherActions: { id: 'other-actions', name: 'tokenActionHud.dnd5e.otherActions', type: 'system' }, + pactBoons: { id: 'pact-boons', name: 'tokenActionHud.dnd5e.pactBoons', type: 'system' }, + pactSpells: { id: 'pact-spells', name: 'tokenActionHud.dnd5e.pactSpells', type: 'system' }, + passiveEffects: { id: 'passive-effects', name: 'DND5E.EffectPassive', type: 'system' }, + passiveFeatures: { id: 'passive-features', name: 'tokenActionHud.dnd5e.passiveFeatures', type: 'system' }, + psionicPowers: { id: 'psionic-powers', name: 'tokenActionHud.dnd5e.psionicPowers', type: 'system' }, + raceFeatures: { id: 'race-features', name: 'tokenActionHud.dnd5e.raceFeatures', type: 'system' }, + reactions: { id: 'reactions', name: 'DND5E.ReactionPl', type: 'system' }, + rests: { id: 'rests', name: 'tokenActionHud.dnd5e.rests', type: 'system' }, + runes: { id: 'runes', name: 'tokenActionHud.dnd5e.runes', type: 'system' }, + saves: { id: 'saves', name: 'DND5E.ClassSaves', type: 'system' }, + skills: { id: 'skills', name: 'tokenActionHud.dnd5e.skills', type: 'system' }, + superiorHuntersDefense: { id: 'superior-hunters-defense', name: 'tokenActionHud.dnd5e.superiorHuntersDefense', type: 'system' }, + temporaryEffects: { id: 'temporary-effects', name: 'DND5E.EffectTemporary', type: 'system' }, + token: { id: 'token', name: 'tokenActionHud.token', type: 'system' }, + tools: { id: 'tools', name: 'ITEM.TypeToolPl', type: 'system' }, + unequipped: { id: 'unequipped', name: 'DND5E.Unequipped', type: 'system' }, + utility: { id: 'utility', name: 'tokenActionHud.utility', type: 'system' }, + weapons: { id: 'weapons', name: 'ITEM.TypeWeaponPl', type: 'system' } } diff --git a/scripts/defaults.js b/scripts/defaults.js index a606d20..766f49d 100644 --- a/scripts/defaults.js +++ b/scripts/defaults.js @@ -1,99 +1,99 @@ -import { SUBCATEGORY } from './constants.js' +import { GROUP } from './constants.js' /** - * Default categories and subcategories + * Default categories and groups */ export let DEFAULTS = null Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { - const subcategories = SUBCATEGORY - Object.values(subcategories).forEach(subcategory => { - subcategory.name = coreModule.api.Utils.i18n(subcategory.name) - subcategory.listName = `Subcategory: ${coreModule.api.Utils.i18n(subcategory.name)}` + const groups = GROUP + Object.values(groups).forEach(group => { + group.name = coreModule.api.Utils.i18n(group.name) + group.listName = `Group: ${coreModule.api.Utils.i18n(group.name)}` }) - const subcategoriesArray = Object.values(subcategories) + const groupsArray = Object.values(groups) DEFAULTS = { - categories: [ + layout: [ { nestId: 'inventory', id: 'inventory', name: coreModule.api.Utils.i18n('DND5E.Inventory'), - subcategories: [ - { ...subcategories.weapons, nestId: 'inventory_weapons' }, - { ...subcategories.equipment, nestId: 'inventory_equipment' }, - { ...subcategories.consumables, nestId: 'inventory_consumables' }, - { ...subcategories.tools, nestId: 'inventory_tools' }, - { ...subcategories.containers, nestId: 'inventory_containers' }, - { ...subcategories.loot, nestId: 'inventory_loot' } + groups: [ + { ...groups.weapons, nestId: 'inventory_weapons' }, + { ...groups.equipment, nestId: 'inventory_equipment' }, + { ...groups.consumables, nestId: 'inventory_consumables' }, + { ...groups.tools, nestId: 'inventory_tools' }, + { ...groups.containers, nestId: 'inventory_containers' }, + { ...groups.loot, nestId: 'inventory_loot' } ] }, { nestId: 'features', id: 'features', name: coreModule.api.Utils.i18n('DND5E.Features'), - subcategories: [ - { ...subcategories.activeFeatures, nestId: 'features_active-features' }, - { ...subcategories.passiveFeatures, nestId: 'features_passive-features' } + groups: [ + { ...groups.activeFeatures, nestId: 'features_active-features' }, + { ...groups.passiveFeatures, nestId: 'features_passive-features' } ] }, { nestId: 'spells', id: 'spells', name: coreModule.api.Utils.i18n('ITEM.TypeSpellPl'), - subcategories: [ - { ...subcategories.atWillSpells, nestId: 'spells_at-will-spells' }, - { ...subcategories.innateSpells, nestId: 'spells_innate-spells' }, - { ...subcategories.pactSpells, nestId: 'spells_pact-spells' }, - { ...subcategories.cantrips, nestId: 'spells_cantrips' }, - { ...subcategories._1stLevelSpells, nestId: 'spells_1st-level-spells' }, - { ...subcategories._2ndLevelSpells, nestId: 'spells_2nd-level-spells' }, - { ...subcategories._3rdLevelSpells, nestId: 'spells_3rd-level-spells' }, - { ...subcategories._4thLevelSpells, nestId: 'spells_4th-level-spells' }, - { ...subcategories._5thLevelSpells, nestId: 'spells_5th-level-spells' }, - { ...subcategories._6thLevelSpells, nestId: 'spells_6th-level-spells' }, - { ...subcategories._7thLevelSpells, nestId: 'spells_7th-level-spells' }, - { ...subcategories._8thLevelSpells, nestId: 'spells_8th-level-spells' }, - { ...subcategories._9thLevelSpells, nestId: 'spells_9th-level-spells' } + groups: [ + { ...groups.atWillSpells, nestId: 'spells_at-will-spells' }, + { ...groups.innateSpells, nestId: 'spells_innate-spells' }, + { ...groups.pactSpells, nestId: 'spells_pact-spells' }, + { ...groups.cantrips, nestId: 'spells_cantrips' }, + { ...groups._1stLevelSpells, nestId: 'spells_1st-level-spells' }, + { ...groups._2ndLevelSpells, nestId: 'spells_2nd-level-spells' }, + { ...groups._3rdLevelSpells, nestId: 'spells_3rd-level-spells' }, + { ...groups._4thLevelSpells, nestId: 'spells_4th-level-spells' }, + { ...groups._5thLevelSpells, nestId: 'spells_5th-level-spells' }, + { ...groups._6thLevelSpells, nestId: 'spells_6th-level-spells' }, + { ...groups._7thLevelSpells, nestId: 'spells_7th-level-spells' }, + { ...groups._8thLevelSpells, nestId: 'spells_8th-level-spells' }, + { ...groups._9thLevelSpells, nestId: 'spells_9th-level-spells' } ] }, { nestId: 'attributes', id: 'attributes', name: coreModule.api.Utils.i18n('DND5E.Attributes'), - subcategories: [ - { ...subcategories.abilities, nestId: 'attributes_abilities' }, - { ...subcategories.skills, nestId: 'attributes_skills' } + groups: [ + { ...groups.abilities, nestId: 'attributes_abilities' }, + { ...groups.skills, nestId: 'attributes_skills' } ] }, { nestId: 'effects', id: 'effects', name: coreModule.api.Utils.i18n('DND5E.Effects'), - subcategories: [ - { ...subcategories.temporaryEffects, nestId: 'effects_temporary-effects' }, - { ...subcategories.passiveEffects, nestId: 'effects_passive-effects' } + groups: [ + { ...groups.temporaryEffects, nestId: 'effects_temporary-effects' }, + { ...groups.passiveEffects, nestId: 'effects_passive-effects' } ] }, { nestId: 'conditions', id: 'conditions', name: coreModule.api.Utils.i18n('tokenActionHud.dnd5e.conditions'), - subcategories: [ - { ...subcategories.conditions, nestId: 'conditions_conditions' } + groups: [ + { ...groups.conditions, nestId: 'conditions_conditions' } ] }, { nestId: 'utility', id: 'utility', name: coreModule.api.Utils.i18n('tokenActionHud.utility'), - subcategories: [ - { ...subcategories.combat, nestId: 'utility_combat' }, - { ...subcategories.token, nestId: 'utility_token' }, - { ...subcategories.rests, nestId: 'utility_rests' }, - { ...subcategories.utility, nestId: 'utility_utility' } + groups: [ + { ...groups.combat, nestId: 'utility_combat' }, + { ...groups.token, nestId: 'utility_token' }, + { ...groups.rests, nestId: 'utility_rests' }, + { ...groups.utility, nestId: 'utility_utility' } ] } ], - subcategories: subcategoriesArray + groups: groupsArray } }) diff --git a/scripts/magic-items-extender.js b/scripts/magic-items-extender.js index bc92f51..b97368b 100644 --- a/scripts/magic-items-extender.js +++ b/scripts/magic-items-extender.js @@ -24,30 +24,30 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { if (magicItems.length === 0) return - const parentSubcategoryId = 'magic-items' - const parentSubcategoryType = 'system' - const parentSubcategoryData = { - id: parentSubcategoryId, - type: parentSubcategoryType + const parentGroupId = 'magic-items' + const parentGroupType = 'system' + const parentGroupData = { + id: parentGroupId, + type: parentGroupType } magicItems.forEach((magicItem) => { if (magicItem.attuned && !this._isItemAttuned(magicItem)) return if (magicItem.equipped && !this._isItemEquipped(magicItem)) return - const subcategoryId = `magic-items_${magicItem.id}` - const subcategoryName = magicItem.name - const subcategoryType = 'system-derived' - const subcategoryInfo1 = `${magicItem.uses}/${magicItem.charges}` - const subcategoryData = { - id: subcategoryId, - name: subcategoryName, - type: subcategoryType, - info1: subcategoryInfo1 + const groupId = `magic-items_${magicItem.id}` + const groupName = magicItem.name + const groupType = 'system-derived' + const groupInfo1 = `${magicItem.uses}/${magicItem.charges}` + const groupData = { + id: groupId, + name: groupName, + type: groupType, + info1: groupInfo1 } - // Add subcategory to action list - this.actionHandler.addSubcategoryToActionList(parentSubcategoryData, subcategoryData) + // Add group to HUD + this.actionHandler.addGroup(groupData, parentGroupData) const actions = magicItem.ownedEntries.map((entry) => { const effect = entry.item @@ -72,7 +72,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { }) // Add actions to action list - this.actionHandler.addActionsToActionList(actions, subcategoryData) + this.actionHandler.addActions(actions, groupData) }) } diff --git a/scripts/system-manager.js b/scripts/system-manager.js index 5b2e0ca..2079f9a 100644 --- a/scripts/system-manager.js +++ b/scripts/system-manager.js @@ -58,19 +58,18 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { /** @override */ async doRegisterDefaultFlags () { const defaults = DEFAULTS - // If the 'Magic Items' module is active, then add a subcategory for it + // If the 'Magic Items' module is active, then add a group for it if (game.modules.get('magicitems')?.active) { const name = coreModule.api.Utils.i18n('tokenActionHud.dnd5e.magicItems') - defaults.subcategories.push( + defaults.groups.push( { id: 'magic-items', name, - listName: `Subcategory: ${name}`, - type: 'system', - hasDerivedSubcategories: true + listName: `Group: ${name}`, + type: 'system' } ) - defaults.subcategories.sort((a, b) => a.id.localeCompare(b.id)) + defaults.groups.sort((a, b) => a.id.localeCompare(b.id)) } return defaults } diff --git a/scripts/token-action-hud-dnd5e.min.js b/scripts/token-action-hud-dnd5e.min.js index 5383e4d..7bdb5b0 100644 --- a/scripts/token-action-hud-dnd5e.min.js +++ b/scripts/token-action-hud-dnd5e.min.js @@ -1 +1 @@ -const e={ID:"token-action-hud-dnd5e"},t={ID:"token-action-hud-core"},s="1.3",i={ability:"DND5E.Ability",check:"tokenActionHud.dnd5e.check",condition:"tokenActionHud.dnd5e.condition",effect:"DND5E.Effect",feature:"ITEM.TypeFeat",item:"tokenActionHud.dnd5e.item",save:"DND5E.ActionSave",skill:"tokenActionHud.dnd5e.skill",spell:"ITEM.TypeSpell",utility:"DND5E.ActionUtil"},n={bonus:"fas fa-plus",crew:"fas fa-users",day:"fas fa-hourglass-end",hour:"fas fa-hourglass-half",lair:"fas fa-home",minute:"fas fa-hourglass-start",legendary:"fas fas fa-dragon",reaction:"fas fa-bolt",special:"fas fa-star"},a="fas fa-circle-c",l="fas fa-sun",o="fas fa-circle-r",c={.5:"fas fa-adjust",1:"fas fa-check",2:"fas fa-check-double"},r={_1stLevelSpells:{id:"1st-level-spells",name:"tokenActionHud.dnd5e.1stLevelSpells",type:"system",hasDerivedSubcategories:!1},_2ndLevelSpells:{id:"2nd-level-spells",name:"tokenActionHud.dnd5e.2ndLevelSpells",type:"system",hasDerivedSubcategories:!1},_3rdLevelSpells:{id:"3rd-level-spells",name:"tokenActionHud.dnd5e.3rdLevelSpells",type:"system",hasDerivedSubcategories:!1},_4thLevelSpells:{id:"4th-level-spells",name:"tokenActionHud.dnd5e.4thLevelSpells",type:"system",hasDerivedSubcategories:!1},_5thLevelSpells:{id:"5th-level-spells",name:"tokenActionHud.dnd5e.5thLevelSpells",type:"system",hasDerivedSubcategories:!1},_6thLevelSpells:{id:"6th-level-spells",name:"tokenActionHud.dnd5e.6thLevelSpells",type:"system",hasDerivedSubcategories:!1},_7thLevelSpells:{id:"7th-level-spells",name:"tokenActionHud.dnd5e.7thLevelSpells",type:"system",hasDerivedSubcategories:!1},_8thLevelSpells:{id:"8th-level-spells",name:"tokenActionHud.dnd5e.8thLevelSpells",type:"system",hasDerivedSubcategories:!1},_9thLevelSpells:{id:"9th-level-spells",name:"tokenActionHud.dnd5e.9thLevelSpells",type:"system",hasDerivedSubcategories:!1},abilities:{id:"abilities",name:"tokenActionHud.dnd5e.abilities",type:"system",hasDerivedSubcategories:!1},actions:{id:"actions",name:"DND5E.ActionPl",type:"system",hasDerivedSubcategories:!0},activeFeatures:{id:"active-features",name:"tokenActionHud.dnd5e.activeFeatures",type:"system",hasDerivedSubcategories:!1},artificerInfusions:{id:"artificer-infusions",name:"tokenActionHud.dnd5e.artificerInfusions",type:"system",hasDerivedSubcategories:!1},atWillSpells:{id:"at-will-spells",name:"tokenActionHud.dnd5e.atWillSpells",type:"system",hasDerivedSubcategories:!1},backgroundFeatures:{id:"background-features",name:"tokenActionHud.dnd5e.backgroundFeatures",type:"system",hasDerivedSubcategories:!1},bonusActions:{id:"bonus-actions",name:"tokenActionHud.dnd5e.bonusActions",type:"system",hasDerivedSubcategories:!0},cantrips:{id:"cantrips",name:"tokenActionHud.dnd5e.cantrips",type:"system",hasDerivedSubcategories:!1},channelDivinity:{id:"channel-divinity",name:"tokenActionHud.dnd5e.channelDivinity",type:"system",hasDerivedSubcategories:!1},checks:{id:"checks",name:"tokenActionHud.dnd5e.checks",type:"system",hasDerivedSubcategories:!1},classFeatures:{id:"class-features",name:"tokenActionHud.dnd5e.classFeatures",type:"system",hasDerivedSubcategories:!1},combat:{id:"combat",name:"tokenActionHud.combat",type:"system",hasDerivedSubcategories:!1},conditions:{id:"conditions",name:"tokenActionHud.dnd5e.conditions",type:"system",hasDerivedSubcategories:!1},consumables:{id:"consumables",name:"ITEM.TypeConsumablePl",type:"system",hasDerivedSubcategories:!1},containers:{id:"containers",name:"ITEM.TypeContainerPl",type:"system",hasDerivedSubcategories:!1},crewActions:{id:"crew-actions",name:"tokenActionHud.dnd5e.crewActions",type:"system",hasDerivedSubcategories:!0},defensiveTactics:{id:"defensive-tactics",name:"tokenActionHud.dnd5e.defensiveTactics",type:"system",hasDerivedSubcategories:!1},eldritchInvocations:{id:"eldritch-invocations",name:"tokenActionHud.dnd5e.eldritchInvocations",type:"system",hasDerivedSubcategories:!1},elementalDisciplines:{id:"elemental-disciplines",name:"tokenActionHud.dnd5e.elementalDisciplines",type:"system",hasDerivedSubcategories:!1},equipment:{id:"equipment",name:"ITEM.TypeEquipmentPl",type:"system",hasDerivedSubcategories:!1},equipped:{id:"equipped",name:"DND5E.Equipped",type:"system",hasDerivedSubcategories:!1},feats:{id:"feats",name:"tokenActionHud.dnd5e.feats",type:"system",hasDerivedSubcategories:!1},fightingStyles:{id:"fighting-styles",name:"tokenActionHud.dnd5e.fightingStyles",type:"system",hasDerivedSubcategories:!1},huntersPrey:{id:"hunters-prey",name:"tokenActionHud.dnd5e.huntersPrey",type:"system",hasDerivedSubcategories:!1},innateSpells:{id:"innate-spells",name:"tokenActionHud.dnd5e.innateSpells",type:"system",hasDerivedSubcategories:!1},kiAbilities:{id:"ki-abilities",name:"tokenActionHud.dnd5e.kiAbilities",type:"system",hasDerivedSubcategories:!1},lairActions:{id:"lair-actions",name:"tokenActionHud.dnd5e.lairActions",type:"system",hasDerivedSubcategories:!0},legendaryActions:{id:"legendary-actions",name:"tokenActionHud.dnd5e.legendaryActions",type:"system",hasDerivedSubcategories:!0},loot:{id:"loot",name:"ITEM.TypeLootPl",type:"system",hasDerivedSubcategories:!1},maneuvers:{id:"maneuvers",name:"tokenActionHud.dnd5e.maneuvers",type:"system",hasDerivedSubcategories:!1},metamagicOptions:{id:"metamagic-options",name:"tokenActionHud.dnd5e.metamagicOptions",type:"system",hasDerivedSubcategories:!1},monsterFeatures:{id:"monster-features",name:"tokenActionHud.dnd5e.monsterFeatures",type:"system",hasDerivedSubcategories:!1},multiattacks:{id:"multiattacks",name:"tokenActionHud.dnd5e.multiattacks",type:"system",hasDerivedSubcategories:!1},otherActions:{id:"other-actions",name:"tokenActionHud.dnd5e.otherActions",type:"system",hasDerivedSubcategories:!0},pactBoons:{id:"pact-boons",name:"tokenActionHud.dnd5e.pactBoons",type:"system",hasDerivedSubcategories:!1},pactSpells:{id:"pact-spells",name:"tokenActionHud.dnd5e.pactSpells",type:"system",hasDerivedSubcategories:!1},passiveEffects:{id:"passive-effects",name:"DND5E.EffectPassive",type:"system",hasDerivedSubcategories:!1},passiveFeatures:{id:"passive-features",name:"tokenActionHud.dnd5e.passiveFeatures",type:"system",hasDerivedSubcategories:!1},psionicPowers:{id:"psionic-powers",name:"tokenActionHud.dnd5e.psionicPowers",type:"system",hasDerivedSubcategories:!1},raceFeatures:{id:"race-features",name:"tokenActionHud.dnd5e.raceFeatures",type:"system",hasDerivedSubcategories:!1},reactions:{id:"reactions",name:"DND5E.ReactionPl",type:"system",hasDerivedSubcategories:!0},rests:{id:"rests",name:"tokenActionHud.dnd5e.rests",type:"system",hasDerivedSubcategories:!1},runes:{id:"runes",name:"tokenActionHud.dnd5e.runes",type:"system",hasDerivedSubcategories:!1},saves:{id:"saves",name:"DND5E.ClassSaves",type:"system",hasDerivedSubcategories:!1},skills:{id:"skills",name:"tokenActionHud.dnd5e.skills",type:"system",hasDerivedSubcategories:!1},superiorHuntersDefense:{id:"superior-hunters-defense",name:"tokenActionHud.dnd5e.superiorHuntersDefense",type:"system",hasDerivedSubcategories:!1},temporaryEffects:{id:"temporary-effects",name:"DND5E.EffectTemporary",type:"system",hasDerivedSubcategories:!1},token:{id:"token",name:"tokenActionHud.token",type:"system",hasDerivedSubcategories:!1},tools:{id:"tools",name:"ITEM.TypeToolPl",type:"system",hasDerivedSubcategories:!1},unequipped:{id:"unequipped",name:"DND5E.Unequipped",type:"system",hasDerivedSubcategories:!1},utility:{id:"utility",name:"tokenActionHud.utility",type:"system",hasDerivedSubcategories:!1},weapons:{id:"weapons",name:"ITEM.TypeWeaponPl",type:"system",hasDerivedSubcategories:!1}};let d=null;Hooks.once("tokenActionHudCoreApiReady",(async t=>{d=class Utils{static getSetting(s,i=null){let n=i??null;try{n=game.settings.get(e.ID,s)}catch{t.api.Logger.debug(`Setting '${s}' not found`)}return n}static async setSetting(s,i){try{i=await game.settings.set(e.ID,s,i),t.api.Logger.debug(`Setting '${s}' set to '${i}'`)}catch{t.api.Logger.debug(`Setting '${s}' not found`)}}}}));let p=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{p=class ActionHandler extends e.api.ActionHandler{actors=null;tokens=null;actorType=null;items=null;abbreviateSkills=null;displaySpellInfo=null;showItemsWithoutActivationCosts=null;showUnchargedItems=null;showUnequippedItems=null;showUnpreparedSpells=null;activationSubcategoryIds=null;featureSubcategoryIds=null;inventorySubcategoryIds=null;spellSubcategoryIds=null;featureActions=null;inventoryActions=null;spellActions=null;async buildSystemActions(e){if(this.actors=this.actor?[this.actor]:this._getActors(),this.tokens=this.token?[this.token]:this._getTokens(),this.actorType=this.actor?.type,this.actor){let e=this.actor.items;e=this._discardSlowItems(e),e=this.sortItemsByName(e),this.items=e}this.abbreviateSkills=d.getSetting("abbreviateSkills"),this.displaySpellInfo=d.getSetting("displaySpellInfo"),this.showItemsWithoutActivationCosts=d.getSetting("showItemsWithoutActivationCosts"),this.showUnchargedItems=d.getSetting("showUnchargedItems"),this.showUnequippedItems=d.getSetting("showUnequippedItems"),this.showUnpreparedSpells=d.getSetting("showUnpreparedSpells"),this.activationSubcategoryIds=["actions","bonus-actions","crew-actions","lair-actions","legendary-actions","reactions","other-actions"],this.featureSubcategoryIds=["active-features","passive-features","background-features","class-features","feats","monster-features","race-features","artificer-infusions","channel-divinity","defensive-tactics","eldritch-invocations","elemental-disciplines","fighting-styles","hunters-prey","ki-abilities","maneuvers","metamagic-options","multiattacks","pact-boons","psionic-powers","runes","superior-hunters-defense"],this.spellSubcategoryIds=["cantrips","1st-level-spells","2nd-level-spells","3rd-level-spells","4th-level-spells","5th-level-spells","6th-level-spells","7th-level-spells","8th-level-spells","9th-level-spells","at-will-spells","innate-spells","pact-spells"],"character"!==this.actorType&&"npc"!==this.actorType||(this.inventorySubcategoryIds=["equipped","consumables","containers","equipment","loot","tools","weapons","unequipped"],this._buildCharacterActions()),"vehicle"===this.actorType&&(this.inventorySubcategoryIds=["consumables","equipment","tools","weapons"],this._buildVehicleActions()),this.actor||this._buildMultipleTokenActions()}async _buildCharacterActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildEffects(),this._buildFeatures(),this._buildInventory(),this._buildRests(),this._buildSkills(),this._buildSpells(),this._buildUtility()}async _buildVehicleActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildEffects(),this._buildFeatures(),this._buildInventory(),this._buildUtility()}async _buildMultipleTokenActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildRests(),this._buildSkills(),this._buildUtility()}_buildAbilities(t,s){const n=this.actor?this.actor.system.abilities:game.dnd5e.config.abilities;if(0===n.length)return;const a=Object.entries(n).filter((e=>0!==n[e[0]].value)).map((a=>{const l=a[0],o=`${t}-${a[0]}`,c=l.charAt(0).toUpperCase()+l.slice(1),r=this.abbreviateSkills?c:game.dnd5e.config.abilities[l],d=`${`${e.api.Utils.i18n(i[t])}: `??""}${game.dnd5e.config.abilities[l]}`;return{id:o,name:r,encodedValue:[t,l].join(this.delimiter),icon:"checks"!==s?this._getProficiencyIcon(n[l].proficient):"",listName:d}})),l={id:s,type:"system"};this.addActionsToActionList(a,l)}async buildActivations(e,t,s="item"){const i=new Map,n={actions:"action","bonus-actions":"bonus","crew-actions":"crew","lair-actions":"lair","legendary-actions":"legendary",reactions:"reaction","other-actions":"other"},a=["action","bonus","crew","lair","legendary","reaction"];for(const[t,s]of e){const e=s.system?.activation?.type,n=a.includes(e)?e:"other";i.has(n)||i.set(n,new Map),i.get(n).set(t,s)}for(const e of this.activationSubcategoryIds){const a=n[e];if(!i.has(a))continue;const l={...t,id:`${e}+${t.id}`,type:"system-derived"},o={id:e,type:"system"};await this.addSubcategoryToActionList(o,l),this.addSubcategoryInfo(t),this._buildActions(i.get(a),l,s)}}_buildCombat(){const t="utility",s={initiative:{id:"initiative",name:e.api.Utils.i18n("tokenActionHud.dnd5e.rollInitiative")},endTurn:{id:"endTurn",name:e.api.Utils.i18n("tokenActionHud.endTurn")}};game.combat?.current?.tokenId!==this.token?.id&&delete s.endTurn;const n=Object.entries(s).map((s=>{const n=s[1].id,a=s[1].name,l=`${`${e.api.Utils.i18n(i[t])}: `??""}${a}`,o=[t,n].join(this.delimiter),c={};let r="";if("initiative"===s[0]&&game.combat){const e=canvas.tokens.controlled.map((e=>e.id)),t=game.combat.combatants.filter((t=>e.includes(t.tokenId)));if(1===t.length){const e=t[0].initiative;c.class="tah-spotlight",c.text=e}r=`toggle${t.length>0&&t.every((e=>e?.initiative))?" active":""}`}return{id:n,name:a,encodedValue:o,info1:c,cssClass:r,listName:l}}));this.addActionsToActionList(n,{id:"combat",type:"system"})}_buildConditions(){if(0===this.tokens?.length)return;const t="condition",s=CONFIG.statusEffects.filter((e=>""!==e.id));if(0===s.length)return;const n=s.map((s=>{const n=s.id,a=e.api.Utils.i18n(s.label),l=`${`${e.api.Utils.i18n(i[t])}: `??""}${a}`,o=[t,n].join(this.delimiter),c=`toggle${this.actors.every((e=>e.effects.map((e=>e.flags?.core?.statusId)).some((e=>e===n))))?" active":""}`,r=e.api.Utils.getImage(s);return{id:n,name:a,encodedValue:o,img:r,cssClass:c,listName:l}}));this.addActionsToActionList(n,{id:"conditions",type:"system"})}_buildEffects(){const e="effect",t=this.actor.effects;if(0===t.size)return;const s=new Map,i=new Map;for(const e of t){const t=e.id;e.isTemporary?i.set(t,e):s.set(t,e)}this._buildActions(s,{id:"passive-effects",type:"system"},e),this._buildActions(i,{id:"temporary-effects",type:"system"},e)}_buildFeatures(){const t="feature",s=new Map;for(const[e,t]of this.items){"feat"===t.type&&s.set(e,t)}if(0===s.size)return;const i=new Map,n=[{type:"background",subcategoryId:"background-features"},{type:"class",subcategoryId:"class-features"},{type:"monster",subcategoryId:"monster-features"},{type:"race",subcategoryId:"race-features"},{type:"feats",subcategoryId:"feats"}],a=[{type:"artificerInfusion",subcategoryId:"artificer-infusions"},{type:"channelDivinity",subcategoryId:"channel-divinity"},{type:"defensiveTactic",subcategoryId:"defensive-tactics"},{type:"eldritchInvocation",subcategoryId:"eldritch-invocations"},{type:"elementalDiscipline",subcategoryId:"elemental-disciplines"},{type:"fightingStyle",subcategoryId:"fighting-styles"},{type:"huntersPrey",subcategoryId:"hunters-prey"},{type:"ki",subcategoryId:"ki-abilities"},{type:"maneuver",subcategoryId:"maneuvers"},{type:"metamagic",subcategoryId:"metamagic-options"},{type:"multiattack",subcategoryId:"multiattacks"},{type:"pact",subcategoryId:"pact-boons"},{type:"psionicPower",subcategoryId:"psionic-powers"},{type:"rune",subcategoryId:"runes"},{type:"superiorHuntersDefense",subcategoryId:"superior-hunters-defense"}];for(const[e,t]of s){const s=t.system.activation?.type,l=t.system.type.value,o=t.system.type?.subtype,c=["","lair","legendary"];s&&!c.includes(s)&&(i.has("active-features")||i.set("active-features",new Map),i.get("active-features").set(e,t)),s&&""!==s||(i.has("passive-features")||i.set("passive-features",new Map),i.get("passive-features").set(e,t));for(const s of n){const n=s.subcategoryId;s.type===l&&(i.has(n)||i.set(n,new Map),i.get(n).set(e,t))}for(const s of a){const n=s.subcategoryId;o&&s.type===o&&(i.has(n)||i.set(n,new Map),i.get(n).set(e,t))}}const l={"active-features":e.api.Utils.i18n("tokenActionHud.dnd5e.activeFeatures"),"passive-features":e.api.Utils.i18n("tokenActionHud.dnd5e.passiveFeatures")};for(const e of this.featureSubcategoryIds){if(!i.has(e))continue;const s={id:e,name:l[e]??"",type:"system"},n=i.get(e);this._buildActions(n,s,t),l[e]&&this.buildActivations(n,s,t)}}_buildInventory(){if(0===this.items.size)return;const t=new Map;for(const[e,s]of this.items){const i=s.system.equipped,n=s.system?.quantity>0,a=this._isActiveItem(s),l=this._isUsableItem(s),o=this._isEquippedItem(s),c=s.type;n&&a&&(i&&(t.has("equipped")||t.set("equipped",new Map),t.get("equipped").set(e,s)),i||(t.has("unequipped")||t.set("unequipped",new Map),t.get("unequipped").set(e,s)),l&&"consumable"===c&&(t.has("consumables")||t.set("consumables",new Map),t.get("consumables").set(e,s)),o&&("backpack"===c&&(t.has("containers")||t.set("containers",new Map),t.get("containers").set(e,s)),"equipment"===c&&(t.has("equipment")||t.set("equipment",new Map),t.get("equipment").set(e,s)),"loot"===c&&(t.has("loot")||t.set("loot",new Map),t.get("loot").set(e,s)),"tool"===c&&(t.has("tools")||t.set("tools",new Map),t.get("tools").set(e,s)),"weapon"===c&&(t.has("weapons")||t.set("weapons",new Map),t.get("weapons").set(e,s))))}const s={equipped:e.api.Utils.i18n("DND5E.Equipped"),unequipped:e.api.Utils.i18n("DND5E.Unequipped"),consumables:e.api.Utils.i18n("ITEM.TypeConsumablePl"),containers:e.api.Utils.i18n("ITEM.TypeContainerPl"),equipment:e.api.Utils.i18n("ITEM.TypeEquipmentPl"),loot:e.api.Utils.i18n("ITEM.TypeLootPl"),tools:e.api.Utils.i18n("ITEM.TypeToolPl"),weapons:e.api.Utils.i18n("ITEM.TypeWeaponPl")};for(const e of this.inventorySubcategoryIds){if(!t.has(e))continue;const i={id:e,name:s[e],type:"system"},n=t.get(e);this._buildActions(n,i),this.activationSubcategoryIds&&this.buildActivations(n,i)}}_buildRests(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const t="utility",s={shortRest:{name:e.api.Utils.i18n("DND5E.ShortRest")},longRest:{name:e.api.Utils.i18n("DND5E.LongRest")}},n=Object.entries(s).map((s=>{const n=s[0],a=s[1].name,l=`${`${e.api.Utils.i18n(i[t])}: `??""}${a}`,o=[t,n].join(this.delimiter);return{id:n,name:a,encodedValue:o,listName:l}}));this.addActionsToActionList(n,{id:"rests",type:"system"})}_buildSkills(){const t="skill",s=this.actor?this.actor.system.skills:game.dnd5e.config.skills;if(0===s.length)return;const n=Object.entries(s).map((n=>{try{const a=n[0],l=a.charAt(0).toUpperCase()+a.slice(1),o=this.abbreviateSkills?l:game.dnd5e.config.skills[a].label,c=`${`${e.api.Utils.i18n(i[t])}: `??""}${game.dnd5e.config.skills[a].label}`,r=[t,a].join(this.delimiter);return{id:a,name:o,encodedValue:r,icon:this._getProficiencyIcon(s[a].value),listName:c}}catch(t){return e.api.Logger.error(n),null}})).filter((e=>!!e));this.addActionsToActionList(n,{id:"skills",type:"system"})}_buildSpells(){const t="spell",s=new Map;for(const[e,t]of this.items){if("spell"===t.type){const i=this._isUsableItem(t),n=this._isUsableSpell(t);if(i&&n){switch(t.system.preparation.mode){case"atwill":s.has("at-will-spells")||s.set("at-will-spells",new Map),s.get("at-will-spells").set(e,t);break;case"innate":s.has("innate-spells")||s.set("innate-spells",new Map),s.get("innate-spells").set(e,t);break;case"pact":s.has("pact-spells")||s.set("pact-spells",new Map),s.get("pact-spells").set(e,t);break;default:switch(t.system.level){case 0:s.has("cantrips")||s.set("cantrips",new Map),s.get("cantrips").set(e,t);break;case 1:s.has("1st-level-spells")||s.set("1st-level-spells",new Map),s.get("1st-level-spells").set(e,t);break;case 2:s.has("2nd-level-spells")||s.set("2nd-level-spells",new Map),s.get("2nd-level-spells").set(e,t);break;case 3:s.has("3rd-level-spells")||s.set("3rd-level-spells",new Map),s.get("3rd-level-spells").set(e,t);break;case 4:s.has("4th-level-spells")||s.set("4th-level-spells",new Map),s.get("4th-level-spells").set(e,t);break;case 5:s.has("5th-level-spells")||s.set("5th-level-spells",new Map),s.get("5th-level-spells").set(e,t);break;case 6:s.has("6th-level-spells")||s.set("6th-level-spells",new Map),s.get("6th-level-spells").set(e,t);break;case 7:s.has("7th-level-spells")||s.set("7th-level-spells",new Map),s.get("7th-level-spells").set(e,t);break;case 8:s.has("8th-level-spells")||s.set("8th-level-spells",new Map),s.get("8th-level-spells").set(e,t);break;case 9:s.has("9th-level-spells")||s.set("9th-level-spells",new Map),s.get("9th-level-spells").set(e,t)}}}}}const i=Object.entries(this.actor.system.spells).reverse();let n=null;const a=[];let l=this.showUnchargedItems,o=this.showUnchargedItems;for(const[e,t]of i){const s=t.value>0,i=t.max>0,c=t.level>0;"pact"===e&&(!o&&s&&i&&c&&(o=!0),c||(o=!1),t.slotAvailable=o,n=[e,t]),e.startsWith("spell")&&"spell0"!==e?(!l&&s&&i&&(l=!0),t.slotAvailable=l,a.push([e,t])):s&&(t.slotsAvailable=!0,a.push(e,t))}if(n[1].slotAvailable){const e=a.findIndex((e=>e[0]==="spell"+n[1].level));a[e][1].slotsAvailable=!0}const c={"1st-level-spells":{spellMode:1,name:e.api.Utils.i18n("tokenActionHud.dnd5e.1stLevelSpells")},"2nd-level-spells":{spellMode:2,name:e.api.Utils.i18n("tokenActionHud.dnd5e.2ndLevelSpells")},"3rd-level-spells":{spellMode:3,name:e.api.Utils.i18n("tokenActionHud.dnd5e.3rdLevelSpells")},"4th-level-spells":{spellMode:4,name:e.api.Utils.i18n("tokenActionHud.dnd5e.4thLevelSpells")},"5th-level-spells":{spellMode:5,name:e.api.Utils.i18n("tokenActionHud.dnd5e.5thLevelSpells")},"6th-level-spells":{spellMode:6,name:e.api.Utils.i18n("tokenActionHud.dnd5e.6thLevelSpells")},"7th-level-spells":{spellMode:7,name:e.api.Utils.i18n("tokenActionHud.dnd5e.7thLevelSpells")},"8th-level-spells":{spellMode:8,name:e.api.Utils.i18n("tokenActionHud.dnd5e.8thLevelSpells")},"9th-level-spells":{spellMode:9,name:e.api.Utils.i18n("tokenActionHud.dnd5e.9thLevelSpells")},"at-will-spells":{spellMode:"atwill",name:e.api.Utils.i18n("tokenActionHud.dnd5e.atWillSpells")},cantrips:{spellMode:0,name:e.api.Utils.i18n("tokenActionHud.dnd5e.cantrips")},"innate-spells":{spellMode:"innate",name:e.api.Utils.i18n("tokenActionHud.dnd5e.innateSpells")},"pact-spells":{spellMode:"pact",name:e.api.Utils.i18n("tokenActionHud.dnd5e.pactSpells")}},r=["1","2","3","4","5","6","7","8","9","pact"];for(const e of this.spellSubcategoryIds){const i=c[e].spellMode,l=c[e].name;if(!s.has(e))continue;const o="pact"===i?n[1]:a.find((e=>e[0]===`spell${i}`))?.[1],d=o?.value,p=o?.max,u=o?.slotAvailable;if(!u&&r.includes(i))continue;const m={};m.info1={class:"tah-spotlight",text:p>=0?`${d}/${p}`:""};const h={id:e,name:l,type:"system",info:m};this.addSubcategoryInfo(h);const y=s.get(e);this._buildActions(y,h,t),this.activationSubcategoryIds&&this.buildActivations(y,h,t)}}_buildUtility(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const t="utility",s={deathSave:{name:e.api.Utils.i18n("DND5E.DeathSave")},inspiration:{name:e.api.Utils.i18n("DND5E.Inspiration")}};(!this.actor||this.actor.system.attributes.hp.value>0)&&delete s.deathSave;const n=Object.entries(s).map((s=>{const n=s[0],a=s[1].name,l=`${`${e.api.Utils.i18n(i[t])}: `??""}${a}`,o=[t,n].join(this.delimiter);let c="";if("inspiration"===s[0]){c=`toggle${this.actors.every((e=>e.system.attributes?.inspiration))?" active":""}`}return{id:n,name:a,encodedValue:o,cssClass:c,listName:l}}));this.addActionsToActionList(n,{id:"utility",type:"system"})}_buildActions(e,t,s="item"){if(0===e.size)return;if(!("string"==typeof t?t:t?.id))return;const i=[...e].map((e=>this._getAction(s,e[1])));this.addActionsToActionList(i,t)}_getAction(t,s){const n=s.id??s._id;let a=s?.name??s?.label;s?.system?.recharge&&!s?.system?.recharge?.charged&&s?.system?.recharge?.value&&(a+=` (${e.api.Utils.i18n("DND5E.Recharge")})`);const l=`${`${e.api.Utils.i18n(i[t])}: `??""}${a}`;let o="";if(Object.hasOwn(s,"disabled")){o=`toggle${s.disabled?"":" active"}`}const c=[t,n].join(this.delimiter),r=e.api.Utils.getImage(s),d=this._getActivationTypeIcon(s?.system?.activation?.type);let p=null,u=null;"spell"===s.type?(p=this._getPreparedIcon(s),this.displaySpellInfo&&(u=this._getSpellInfo(s))):u=this._getItemInfo(s);const m=u?.info1,h=u?.info2,y=u?.info3;return{id:n,name:a,encodedValue:c,cssClass:o,img:r,icon1:d,icon2:p,info1:m,info2:h,info3:y,listName:l}}_isActiveItem(e){if(this.showItemsWithoutActivationCosts)return!0;const t=Object.keys(game.dnd5e.config.abilityActivationTypes).filter((e=>"none"!==e)),s=e.system.activation,i=s?.type;return!(!s||!t.includes(i))}_isEquippedItem(e){const t=e.type;if(this.showUnequippedItems&&!["consumable","spell","feat"].includes(t))return!0;return!(!e.system.equipped||"consumable"===t)}_isUsableItem(e){if(this.showUnchargedItems)return!0;return!!e.system.uses}_isUsableSpell(e){if("character"!==this.actorType&&this.showUnequippedItems)return!0;const t=e.system.preparation.prepared;if(this.showUnpreparedSpells)return!0;const s=e.system.level,i=Object.keys(game.dnd5e.config.spellPreparationModes).filter((e=>"prepared"!==e)),n=e.system.preparation.mode;return!(0!==s&&!i.includes(n)&&!t)}_getItemInfo(e){return{info1:{text:this._getQuantityData(e)},info2:{text:this._getUsesData(e)},info3:{text:this._getConsumeData(e)}}}_getSpellInfo(t){const s=t.system.components,i=[],n={},a={},l={};if(s?.vocal&&i.push(e.api.Utils.i18n("DND5E.ComponentVerbal")),s?.somatic&&i.push(e.api.Utils.i18n("DND5E.ComponentSomatic")),s?.material&&i.push(e.api.Utils.i18n("DND5E.ComponentMaterial")),i.length&&(n.title=i.join(", "),n.text=i.map((e=>e.charAt(0).toUpperCase())).join("")),s?.concentration){const t=e.api.Utils.i18n("DND5E.Concentration");a.title=t,a.text=t.charAt(0).toUpperCase()}if(s?.ritual){const t=e.api.Utils.i18n("DND5E.Ritual");l.title=t,l.text=t.charAt(0).toUpperCase()}return{info1:n,info2:a,info3:l}}_getActors(){const e=["character","npc"],t=canvas.tokens.controlled.filter((e=>e.actor)).map((e=>e.actor));return t.every((t=>e.includes(t.type)))?t:[]}_getTokens(){const e=["character","npc"],t=canvas.tokens.controlled;return t.filter((e=>e.actor)).map((e=>e.actor)).every((t=>e.includes(t.type)))?t:[]}_getQuantityData(e){const t=e?.system?.quantity??0;return t>1?t:""}_getUsesData(e){const t=e?.system?.uses;return t&&(t.value>0||t.max>0)?`${t.value??"0"}${t.max>0?`/${t.max}`:""}`:""}_getConsumeData(e){const t=e?.system?.consume?.target,s=e?.system?.consume?.type;if("attribute"===s){const e=t.substr(0,t.lastIndexOf(".")),s=this.actor.system[e];return s?`${s.value??"0"}${s.max?`/${s.max}`:""}`:""}const i=this.items.get(t);if("charges"===s){const e=i?.system.uses;return e?.value?`${e.value}${e.max?`/${e.max}`:""}`:""}return i?.system?.quantity??""}_discardSlowItems(e){if(d.getSetting("showSlowActions"))return e;const t=["minute","hour","day"],s=new Map;for(const[i,n]of e.entries()){const e=n.system.activation,a=n.system.activation?.type;e&&!t.includes(a)&&s.set(i,n)}return s}_getProficiencyIcon(e){const t=CONFIG.DND5E.proficiencyLevels[e]??"",s=c[e];if(s)return``}_getActivationTypeIcon(e){const t=CONFIG.DND5E.abilityActivationTypes[e]??"",s=n[e];if(s)return``}_getPreparedIcon(t){const s=t.system.level,i=t.system.preparation.mode,n=t.system.preparation.prepared,a=n?"fas fa-sun":"fas fa-sun tah-icon-disabled",l=n?e.api.Utils.i18n("DND5E.SpellPrepared"):e.api.Utils.i18n("DND5E.SpellUnprepared");return"prepared"===i&&0!==s?``:""}}}));let u=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{const t=r;Object.values(t).forEach((t=>{t.name=e.api.Utils.i18n(t.name),t.listName=`Subcategory: ${e.api.Utils.i18n(t.name)}`}));const s=Object.values(t);u={categories:[{nestId:"inventory",id:"inventory",name:e.api.Utils.i18n("DND5E.Inventory"),subcategories:[{...t.weapons,nestId:"inventory_weapons"},{...t.equipment,nestId:"inventory_equipment"},{...t.consumables,nestId:"inventory_consumables"},{...t.tools,nestId:"inventory_tools"},{...t.containers,nestId:"inventory_containers"},{...t.loot,nestId:"inventory_loot"}]},{nestId:"features",id:"features",name:e.api.Utils.i18n("DND5E.Features"),subcategories:[{...t.activeFeatures,nestId:"features_active-features"},{...t.passiveFeatures,nestId:"features_passive-features"}]},{nestId:"spells",id:"spells",name:e.api.Utils.i18n("ITEM.TypeSpellPl"),subcategories:[{...t.atWillSpells,nestId:"spells_at-will-spells"},{...t.innateSpells,nestId:"spells_innate-spells"},{...t.pactSpells,nestId:"spells_pact-spells"},{...t.cantrips,nestId:"spells_cantrips"},{...t._1stLevelSpells,nestId:"spells_1st-level-spells"},{...t._2ndLevelSpells,nestId:"spells_2nd-level-spells"},{...t._3rdLevelSpells,nestId:"spells_3rd-level-spells"},{...t._4thLevelSpells,nestId:"spells_4th-level-spells"},{...t._5thLevelSpells,nestId:"spells_5th-level-spells"},{...t._6thLevelSpells,nestId:"spells_6th-level-spells"},{...t._7thLevelSpells,nestId:"spells_7th-level-spells"},{...t._8thLevelSpells,nestId:"spells_8th-level-spells"},{...t._9thLevelSpells,nestId:"spells_9th-level-spells"}]},{nestId:"attributes",id:"attributes",name:e.api.Utils.i18n("DND5E.Attributes"),subcategories:[{...t.abilities,nestId:"attributes_abilities"},{...t.skills,nestId:"attributes_skills"}]},{nestId:"effects",id:"effects",name:e.api.Utils.i18n("DND5E.Effects"),subcategories:[{...t.temporaryEffects,nestId:"effects_temporary-effects"},{...t.passiveEffects,nestId:"effects_passive-effects"}]},{nestId:"conditions",id:"conditions",name:e.api.Utils.i18n("tokenActionHud.dnd5e.conditions"),subcategories:[{...t.conditions,nestId:"conditions_conditions"}]},{nestId:"utility",id:"utility",name:e.api.Utils.i18n("tokenActionHud.utility"),subcategories:[{...t.combat,nestId:"utility_combat"},{...t.token,nestId:"utility_token"},{...t.rests,nestId:"utility_rests"},{...t.utility,nestId:"utility_utility"}]}],subcategories:s}}));let m=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{m=class MagicItemActionListExtender extends e.api.ActionListExtender{constructor(e){super(e.categoryManager),this.actionHandler=e,this.categoryManager=e.categoryManager,this.actor=null}extendActionList(){if(this.actor=this.actionHandler.actor,!this.actor)return;const t=MagicItems.actor(this.actor.id);if(!t)return;const s=t.items??[];if(0===s.length)return;const i={id:"magic-items",type:"system"};s.forEach((t=>{if(t.attuned&&!this._isItemAttuned(t))return;if(t.equipped&&!this._isItemEquipped(t))return;const s={id:`magic-items_${t.id}`,name:t.name,type:"system-derived",info1:`${t.uses}/${t.charges}`};this.actionHandler.addSubcategoryToActionList(i,s);const n=t.ownedEntries.map((s=>{const i=s.item,n=i.id;return{id:n,name:i.name,encodedValue:["magicItem",`${t.id}>${n}`].join("|"),img:e.api.Utils.getImage(i),info1:i.consumption,info2:i.baseLevel?`${e.api.Utils.i18n("DND5E.AbbreviationLevel")} ${i.baseLevel}`:"",selected:!0}}));this.actionHandler.addActionsToActionList(n,s)}))}_isItemEquipped(e){return e.item.system.equipped}_isItemAttuned(e){return e.item.system.attunment!==(CONFIG.DND5E.attunementTypes?.REQUIRED??1)}}}));let h=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{h=class RollHandler extends e.api.RollHandler{async doHandleActionEvent(e,t){const s=t.split("|");2!==s.length&&super.throwInvalidValueErr();const i=s[0],n=s[1];if(this.actor)await this._handleMacros(e,i,this.actor,this.token,n);else for(const t of canvas.tokens.controlled){const s=t.actor;await this._handleMacros(e,i,s,t,n)}}async _handleMacros(e,t,s,i,n){switch(t){case"ability":this._rollAbility(e,s,n);break;case"check":this._rollAbilityTest(e,s,n);break;case"save":this._rollAbilitySave(e,s,n);break;case"condition":if(!i)return;await this._toggleCondition(e,i,n);break;case"effect":await this._toggleEffect(e,s,n);break;case"feature":case"item":case"spell":case"weapon":this.isRenderItem()?this.doRenderItem(s,n):this._useItem(e,s,n);break;case"magicItem":this._rollMagicItem(s,n);break;case"skill":this._rollSkill(e,s,n);break;case"utility":await this._performUtilityMacro(e,s,i,n)}}_rollAbility(e,t,s){t&&t.system?.abilities&&t.rollAbility(s,{event:e})}_rollAbilitySave(e,t,s){t&&t.system?.abilities&&t.rollAbilitySave(s,{event:e})}_rollAbilityTest(e,t,s){t&&t.system?.abilities&&t.rollAbilityTest(s,{event:e})}_rollMagicItem(e,t){const s=t.split(">"),i=s[0],n=s[1];MagicItems.actor(e.id).roll(i,n),Hooks.callAll("forceUpdateTokenActionHud")}_rollSkill(e,t,s){t&&t.system?.skills&&t.rollSkill(s,{event:e})}_useItem(t,s,i){const n=e.api.Utils.getItem(s,i);if(!this._needsRecharge(n))return n.use({event:t});n.rollRecharge()}_needsRecharge(e){return e.system.recharge&&!e.system.recharge.charged&&e.system.recharge.value}async _performUtilityMacro(e,t,s,i){switch(i){case"deathSave":t.rollDeathSave({event:e});break;case"endTurn":if(!s)break;game.combat?.current?.tokenId===s.id&&await(game.combat?.nextTurn());break;case"initiative":await this._rollInitiative(t);break;case"inspiration":{const e=!t.system.attributes.inspiration;t.update({"data.attributes.inspiration":e});break}case"longRest":t.longRest();break;case"shortRest":t.shortRest()}Hooks.callAll("forceUpdateTokenActionHud")}async _rollInitiative(e){e&&(await e.rollInitiative({createCombatants:!0}),Hooks.callAll("forceUpdateTokenActionHud"))}async _toggleCondition(e,t,s,i=null){if(!t)return;const n=this.isRightClick(e);if(game.dfreds&&i?.flags?.isConvenient){const e=i.label;game.dfreds.effectInterface._toggleEffect(e)}else{const e=this.findCondition(s);if(!e)return;n?await t.toggleEffect(e,{overlay:!0}):await t.toggleEffect(e)}Hooks.callAll("forceUpdateTokenActionHud")}findCondition(e){return CONFIG.statusEffects.find((t=>t.id===e))}async _toggleEffect(e,t,s){const i=("find"in t.effects.entries?t.effects.entries:t.effects).find((e=>e.id===s));if(!i)return;this.isRightClick(e)?await i.delete():await i.update({disabled:!i.disabled}),Hooks.callAll("forceUpdateTokenActionHud")}}}));class RollHandlerObsidian extends h{_rollAbilityTest(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"abl",abl:t})}_rollAbilitySave(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"save",save:t})}_rollSkill(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"skl",skl:t})}_useItem(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"item",id:t})}}function register(t){game.settings.register(e.ID,"abbreviateSkills",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.abbreviateSkills.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.abbreviateSkills.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showSlowActions",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showSlowActions.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showSlowActions.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"displaySpellInfo",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.displaySpellInfo.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.displaySpellInfo.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnchargedItems",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnchargedItems.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnchargedItems.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnequippedItems",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItems.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItems.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnpreparedSpells",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnpreparedSpells.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnpreparedSpells.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showItemsWithoutActivationCosts",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}})}let y=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{y=class SystemManager extends e.api.SystemManager{doGetCategoryManager(){return new e.api.CategoryManager}doGetActionHandler(t){const s=new p(t);return e.api.Utils.isModuleActive("magicitems")&&s.addFurtherActionHandler(new m(s)),s}getAvailableRollHandlers(){let t="Core D&D5e";e.api.Utils.isModuleActive("midi-qol")&&(t+=` [supports ${e.api.Utils.getModuleTitle("midi-qol")}]`);const s={core:t};return e.api.SystemManager.addHandler(s,"obsidian"),s}doGetRollHandler(e){let t;if("obsidian"===e)t=new RollHandlerObsidian;else t=new h;return t}doRegisterSettings(e){register(e)}async doRegisterDefaultFlags(){const t=u;if(game.modules.get("magicitems")?.active){const s=e.api.Utils.i18n("tokenActionHud.dnd5e.magicItems");t.subcategories.push({id:"magic-items",name:s,listName:`Subcategory: ${s}`,type:"system",hasDerivedSubcategories:!0}),t.subcategories.sort(((e,t)=>e.id.localeCompare(t.id)))}return t}}})),Hooks.on("tokenActionHudCoreApiReady",(async()=>{const t=game.modules.get(e.ID);t.api={requiredCoreModuleVersion:"1.3",SystemManager:y},Hooks.call("tokenActionHudSystemReady",t)}));export{i as ACTION_TYPE,n as ACTIVATION_TYPE_ICON,p as ActionHandler,a as CONCENTRATION_ICON,t as CORE_MODULE,u as DEFAULTS,e as MODULE,m as MagicItemActionListExtender,l as PREPARED_ICON,c as PROFICIENCY_LEVEL_ICON,s as REQUIRED_CORE_MODULE_VERSION,o as RITUAL_ICON,h as RollHandler,RollHandlerObsidian,r as SUBCATEGORY,y as SystemManager,d as Utils,register}; +const e={ID:"token-action-hud-dnd5e"},t={ID:"token-action-hud-core"},s="1.4",i={ability:"DND5E.Ability",check:"tokenActionHud.dnd5e.check",condition:"tokenActionHud.dnd5e.condition",effect:"DND5E.Effect",feature:"ITEM.TypeFeat",item:"tokenActionHud.dnd5e.item",save:"DND5E.ActionSave",skill:"tokenActionHud.dnd5e.skill",spell:"ITEM.TypeSpell",utility:"DND5E.ActionUtil"},n={bonus:"fas fa-plus",crew:"fas fa-users",day:"fas fa-hourglass-end",hour:"fas fa-hourglass-half",lair:"fas fa-home",minute:"fas fa-hourglass-start",legendary:"fas fas fa-dragon",reaction:"fas fa-bolt",special:"fas fa-star"},l="fas fa-circle-c",a="fas fa-sun",o="fas fa-circle-r",c={.5:"fas fa-adjust",1:"fas fa-check",2:"fas fa-check-double"},d={_1stLevelSpells:{id:"1st-level-spells",name:"tokenActionHud.dnd5e.1stLevelSpells",type:"system"},_2ndLevelSpells:{id:"2nd-level-spells",name:"tokenActionHud.dnd5e.2ndLevelSpells",type:"system"},_3rdLevelSpells:{id:"3rd-level-spells",name:"tokenActionHud.dnd5e.3rdLevelSpells",type:"system"},_4thLevelSpells:{id:"4th-level-spells",name:"tokenActionHud.dnd5e.4thLevelSpells",type:"system"},_5thLevelSpells:{id:"5th-level-spells",name:"tokenActionHud.dnd5e.5thLevelSpells",type:"system"},_6thLevelSpells:{id:"6th-level-spells",name:"tokenActionHud.dnd5e.6thLevelSpells",type:"system"},_7thLevelSpells:{id:"7th-level-spells",name:"tokenActionHud.dnd5e.7thLevelSpells",type:"system"},_8thLevelSpells:{id:"8th-level-spells",name:"tokenActionHud.dnd5e.8thLevelSpells",type:"system"},_9thLevelSpells:{id:"9th-level-spells",name:"tokenActionHud.dnd5e.9thLevelSpells",type:"system"},abilities:{id:"abilities",name:"tokenActionHud.dnd5e.abilities",type:"system"},actions:{id:"actions",name:"DND5E.ActionPl",type:"system"},activeFeatures:{id:"active-features",name:"tokenActionHud.dnd5e.activeFeatures",type:"system"},artificerInfusions:{id:"artificer-infusions",name:"tokenActionHud.dnd5e.artificerInfusions",type:"system"},atWillSpells:{id:"at-will-spells",name:"tokenActionHud.dnd5e.atWillSpells",type:"system"},backgroundFeatures:{id:"background-features",name:"tokenActionHud.dnd5e.backgroundFeatures",type:"system"},bonusActions:{id:"bonus-actions",name:"tokenActionHud.dnd5e.bonusActions",type:"system"},cantrips:{id:"cantrips",name:"tokenActionHud.dnd5e.cantrips",type:"system"},channelDivinity:{id:"channel-divinity",name:"tokenActionHud.dnd5e.channelDivinity",type:"system"},checks:{id:"checks",name:"tokenActionHud.dnd5e.checks",type:"system"},classFeatures:{id:"class-features",name:"tokenActionHud.dnd5e.classFeatures",type:"system"},combat:{id:"combat",name:"tokenActionHud.combat",type:"system"},conditions:{id:"conditions",name:"tokenActionHud.dnd5e.conditions",type:"system"},consumables:{id:"consumables",name:"ITEM.TypeConsumablePl",type:"system"},containers:{id:"containers",name:"ITEM.TypeContainerPl",type:"system"},crewActions:{id:"crew-actions",name:"tokenActionHud.dnd5e.crewActions",type:"system"},defensiveTactics:{id:"defensive-tactics",name:"tokenActionHud.dnd5e.defensiveTactics",type:"system"},eldritchInvocations:{id:"eldritch-invocations",name:"tokenActionHud.dnd5e.eldritchInvocations",type:"system"},elementalDisciplines:{id:"elemental-disciplines",name:"tokenActionHud.dnd5e.elementalDisciplines",type:"system"},equipment:{id:"equipment",name:"ITEM.TypeEquipmentPl",type:"system"},equipped:{id:"equipped",name:"DND5E.Equipped",type:"system"},feats:{id:"feats",name:"tokenActionHud.dnd5e.feats",type:"system"},fightingStyles:{id:"fighting-styles",name:"tokenActionHud.dnd5e.fightingStyles",type:"system"},huntersPrey:{id:"hunters-prey",name:"tokenActionHud.dnd5e.huntersPrey",type:"system"},innateSpells:{id:"innate-spells",name:"tokenActionHud.dnd5e.innateSpells",type:"system"},kiAbilities:{id:"ki-abilities",name:"tokenActionHud.dnd5e.kiAbilities",type:"system"},lairActions:{id:"lair-actions",name:"tokenActionHud.dnd5e.lairActions",type:"system"},legendaryActions:{id:"legendary-actions",name:"tokenActionHud.dnd5e.legendaryActions",type:"system"},loot:{id:"loot",name:"ITEM.TypeLootPl",type:"system"},maneuvers:{id:"maneuvers",name:"tokenActionHud.dnd5e.maneuvers",type:"system"},metamagicOptions:{id:"metamagic-options",name:"tokenActionHud.dnd5e.metamagicOptions",type:"system"},monsterFeatures:{id:"monster-features",name:"tokenActionHud.dnd5e.monsterFeatures",type:"system"},multiattacks:{id:"multiattacks",name:"tokenActionHud.dnd5e.multiattacks",type:"system"},otherActions:{id:"other-actions",name:"tokenActionHud.dnd5e.otherActions",type:"system"},pactBoons:{id:"pact-boons",name:"tokenActionHud.dnd5e.pactBoons",type:"system"},pactSpells:{id:"pact-spells",name:"tokenActionHud.dnd5e.pactSpells",type:"system"},passiveEffects:{id:"passive-effects",name:"DND5E.EffectPassive",type:"system"},passiveFeatures:{id:"passive-features",name:"tokenActionHud.dnd5e.passiveFeatures",type:"system"},psionicPowers:{id:"psionic-powers",name:"tokenActionHud.dnd5e.psionicPowers",type:"system"},raceFeatures:{id:"race-features",name:"tokenActionHud.dnd5e.raceFeatures",type:"system"},reactions:{id:"reactions",name:"DND5E.ReactionPl",type:"system"},rests:{id:"rests",name:"tokenActionHud.dnd5e.rests",type:"system"},runes:{id:"runes",name:"tokenActionHud.dnd5e.runes",type:"system"},saves:{id:"saves",name:"DND5E.ClassSaves",type:"system"},skills:{id:"skills",name:"tokenActionHud.dnd5e.skills",type:"system"},superiorHuntersDefense:{id:"superior-hunters-defense",name:"tokenActionHud.dnd5e.superiorHuntersDefense",type:"system"},temporaryEffects:{id:"temporary-effects",name:"DND5E.EffectTemporary",type:"system"},token:{id:"token",name:"tokenActionHud.token",type:"system"},tools:{id:"tools",name:"ITEM.TypeToolPl",type:"system"},unequipped:{id:"unequipped",name:"DND5E.Unequipped",type:"system"},utility:{id:"utility",name:"tokenActionHud.utility",type:"system"},weapons:{id:"weapons",name:"ITEM.TypeWeaponPl",type:"system"}};let r=null;Hooks.once("tokenActionHudCoreApiReady",(async t=>{r=class Utils{static getSetting(s,i=null){let n=i??null;try{n=game.settings.get(e.ID,s)}catch{t.api.Logger.debug(`Setting '${s}' not found`)}return n}static async setSetting(s,i){try{i=await game.settings.set(e.ID,s,i),t.api.Logger.debug(`Setting '${s}' set to '${i}'`)}catch{t.api.Logger.debug(`Setting '${s}' not found`)}}}}));let p=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{p=class ActionHandler extends e.api.ActionHandler{actors=null;tokens=null;actorType=null;items=null;abbreviateSkills=null;displaySpellInfo=null;showItemsWithoutActivationCosts=null;showUnchargedItems=null;showUnequippedItems=null;showUnpreparedSpells=null;activationgroupIds=null;featuregroupIds=null;inventorygroupIds=null;spellgroupIds=null;featureActions=null;inventoryActions=null;spellActions=null;async buildSystemActions(t){if(this.actors=this.actor?[this.actor]:this._getActors(),this.tokens=this.token?[this.token]:this._getTokens(),this.actorType=this.actor?.type,this.actor){let t=this.actor.items;t=this._discardSlowItems(t),t=e.api.Utils.sortItemsByName(t),this.items=t}this.abbreviateSkills=r.getSetting("abbreviateSkills"),this.displaySpellInfo=r.getSetting("displaySpellInfo"),this.showItemsWithoutActivationCosts=r.getSetting("showItemsWithoutActivationCosts"),this.showUnchargedItems=r.getSetting("showUnchargedItems"),this.showUnequippedItems=r.getSetting("showUnequippedItems"),this.showUnpreparedSpells=r.getSetting("showUnpreparedSpells"),this.activationgroupIds=["actions","bonus-actions","crew-actions","lair-actions","legendary-actions","reactions","other-actions"],this.featuregroupIds=["active-features","passive-features","background-features","class-features","feats","monster-features","race-features","artificer-infusions","channel-divinity","defensive-tactics","eldritch-invocations","elemental-disciplines","fighting-styles","hunters-prey","ki-abilities","maneuvers","metamagic-options","multiattacks","pact-boons","psionic-powers","runes","superior-hunters-defense"],this.spellgroupIds=["cantrips","1st-level-spells","2nd-level-spells","3rd-level-spells","4th-level-spells","5th-level-spells","6th-level-spells","7th-level-spells","8th-level-spells","9th-level-spells","at-will-spells","innate-spells","pact-spells"],"character"!==this.actorType&&"npc"!==this.actorType||(this.inventorygroupIds=["equipped","consumables","containers","equipment","loot","tools","weapons","unequipped"],this._buildCharacterActions()),"vehicle"===this.actorType&&(this.inventorygroupIds=["consumables","equipment","tools","weapons"],this._buildVehicleActions()),this.actor||this._buildMultipleTokenActions()}async _buildCharacterActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildEffects(),this._buildFeatures(),this._buildInventory(),this._buildRests(),this._buildSkills(),this._buildSpells(),this._buildUtility()}async _buildVehicleActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildEffects(),this._buildFeatures(),this._buildInventory(),this._buildUtility()}async _buildMultipleTokenActions(){this._buildAbilities("ability","abilities"),this._buildAbilities("check","checks"),this._buildAbilities("save","saves"),this._buildCombat(),this._buildConditions(),this._buildRests(),this._buildSkills(),this._buildUtility()}_buildAbilities(t,s){const n=this.actor?this.actor.system.abilities:game.dnd5e.config.abilities;if(0===n.length)return;const l=Object.entries(n).filter((e=>0!==n[e[0]].value)).map((l=>{const a=l[0],o=`${t}-${l[0]}`,c=a.charAt(0).toUpperCase()+a.slice(1),d=this.abbreviateSkills?c:game.dnd5e.config.abilities[a],r=`${`${e.api.Utils.i18n(i[t])}: `??""}${game.dnd5e.config.abilities[a]}`;return{id:o,name:d,encodedValue:[t,a].join(this.delimiter),icon1:"checks"!==s?this._getProficiencyIcon(n[a].proficient):"",listName:r}})),a={id:s,type:"system"};this.addActions(l,a)}async buildActivations(e,t,s="item"){const i=new Map,n={actions:"action","bonus-actions":"bonus","crew-actions":"crew","lair-actions":"lair","legendary-actions":"legendary",reactions:"reaction","other-actions":"other"},l=["action","bonus","crew","lair","legendary","reaction"];for(const[t,s]of e){const e=s.system?.activation?.type,n=l.includes(e)?e:"other";i.has(n)||i.set(n,new Map),i.get(n).set(t,s)}for(const e of this.activationgroupIds){const l=n[e];if(!i.has(l))continue;const a={...t,id:`${e}+${t.id}`,type:"system-derived"},o={id:e,type:"system"};await this.addGroup(a,o),this.addGroupInfo(t),this._buildActions(i.get(l),a,s)}}_buildCombat(){const t="utility",s={initiative:{id:"initiative",name:e.api.Utils.i18n("tokenActionHud.dnd5e.rollInitiative")},endTurn:{id:"endTurn",name:e.api.Utils.i18n("tokenActionHud.endTurn")}};game.combat?.current?.tokenId!==this.token?.id&&delete s.endTurn;const n=Object.entries(s).map((s=>{const n=s[1].id,l=s[1].name,a=`${`${e.api.Utils.i18n(i[t])}: `??""}${l}`,o=[t,n].join(this.delimiter),c={};let d="";if("initiative"===s[0]&&game.combat){const e=canvas.tokens.controlled.map((e=>e.id)),t=game.combat.combatants.filter((t=>e.includes(t.tokenId)));if(1===t.length){const e=t[0].initiative;c.class="tah-spotlight",c.text=e}d=`toggle${t.length>0&&t.every((e=>e?.initiative))?" active":""}`}return{id:n,name:l,encodedValue:o,info1:c,cssClass:d,listName:a}}));this.addActions(n,{id:"combat",type:"system"})}_buildConditions(){if(0===this.tokens?.length)return;const t="condition",s=CONFIG.statusEffects.filter((e=>""!==e.id));if(0===s.length)return;const n=s.map((s=>{const n=s.id,l=e.api.Utils.i18n(s.label),a=`${`${e.api.Utils.i18n(i[t])}: `??""}${l}`,o=[t,n].join(this.delimiter),c=`toggle${this.actors.every((e=>e.effects.map((e=>e.flags?.core?.statusId)).some((e=>e===n))))?" active":""}`,d=e.api.Utils.getImage(s);return{id:n,name:l,encodedValue:o,img:d,cssClass:c,listName:a}}));this.addActions(n,{id:"conditions",type:"system"})}_buildEffects(){const e="effect",t=this.actor.effects;if(0===t.size)return;const s=new Map,i=new Map;for(const e of t){const t=e.id;e.isTemporary?i.set(t,e):s.set(t,e)}this._buildActions(s,{id:"passive-effects",type:"system"},e),this._buildActions(i,{id:"temporary-effects",type:"system"},e)}_buildFeatures(){const t="feature",s=new Map;for(const[e,t]of this.items){"feat"===t.type&&s.set(e,t)}if(0===s.size)return;const i=new Map,n=[{type:"background",groupId:"background-features"},{type:"class",groupId:"class-features"},{type:"monster",groupId:"monster-features"},{type:"race",groupId:"race-features"},{type:"feats",groupId:"feats"}],l=[{type:"artificerInfusion",groupId:"artificer-infusions"},{type:"channelDivinity",groupId:"channel-divinity"},{type:"defensiveTactic",groupId:"defensive-tactics"},{type:"eldritchInvocation",groupId:"eldritch-invocations"},{type:"elementalDiscipline",groupId:"elemental-disciplines"},{type:"fightingStyle",groupId:"fighting-styles"},{type:"huntersPrey",groupId:"hunters-prey"},{type:"ki",groupId:"ki-abilities"},{type:"maneuver",groupId:"maneuvers"},{type:"metamagic",groupId:"metamagic-options"},{type:"multiattack",groupId:"multiattacks"},{type:"pact",groupId:"pact-boons"},{type:"psionicPower",groupId:"psionic-powers"},{type:"rune",groupId:"runes"},{type:"superiorHuntersDefense",groupId:"superior-hunters-defense"}];for(const[e,t]of s){const s=t.system.activation?.type,a=t.system.type.value,o=t.system.type?.subtype,c=["","lair","legendary"];s&&!c.includes(s)&&(i.has("active-features")||i.set("active-features",new Map),i.get("active-features").set(e,t)),s&&""!==s||(i.has("passive-features")||i.set("passive-features",new Map),i.get("passive-features").set(e,t));for(const s of n){const n=s.groupId;s.type===a&&(i.has(n)||i.set(n,new Map),i.get(n).set(e,t))}for(const s of l){const n=s.groupId;o&&s.type===o&&(i.has(n)||i.set(n,new Map),i.get(n).set(e,t))}}const a={"active-features":e.api.Utils.i18n("tokenActionHud.dnd5e.activeFeatures"),"passive-features":e.api.Utils.i18n("tokenActionHud.dnd5e.passiveFeatures")};for(const e of this.featuregroupIds){if(!i.has(e))continue;const s={id:e,name:a[e]??"",type:"system"},n=i.get(e);this._buildActions(n,s,t),a[e]&&this.buildActivations(n,s,t)}}_buildInventory(){if(0===this.items.size)return;const t=new Map;for(const[e,s]of this.items){const i=s.system.equipped,n=s.system?.quantity>0,l=this._isActiveItem(s),a=this._isUsableItem(s),o=this._isEquippedItem(s),c=s.type;n&&l&&(i&&(t.has("equipped")||t.set("equipped",new Map),t.get("equipped").set(e,s)),i||(t.has("unequipped")||t.set("unequipped",new Map),t.get("unequipped").set(e,s)),a&&"consumable"===c&&(t.has("consumables")||t.set("consumables",new Map),t.get("consumables").set(e,s)),o&&("backpack"===c&&(t.has("containers")||t.set("containers",new Map),t.get("containers").set(e,s)),"equipment"===c&&(t.has("equipment")||t.set("equipment",new Map),t.get("equipment").set(e,s)),"loot"===c&&(t.has("loot")||t.set("loot",new Map),t.get("loot").set(e,s)),"tool"===c&&(t.has("tools")||t.set("tools",new Map),t.get("tools").set(e,s)),"weapon"===c&&(t.has("weapons")||t.set("weapons",new Map),t.get("weapons").set(e,s))))}const s={equipped:e.api.Utils.i18n("DND5E.Equipped"),unequipped:e.api.Utils.i18n("DND5E.Unequipped"),consumables:e.api.Utils.i18n("ITEM.TypeConsumablePl"),containers:e.api.Utils.i18n("ITEM.TypeContainerPl"),equipment:e.api.Utils.i18n("ITEM.TypeEquipmentPl"),loot:e.api.Utils.i18n("ITEM.TypeLootPl"),tools:e.api.Utils.i18n("ITEM.TypeToolPl"),weapons:e.api.Utils.i18n("ITEM.TypeWeaponPl")};for(const e of this.inventorygroupIds){if(!t.has(e))continue;const i={id:e,name:s[e],type:"system"},n=t.get(e);this._buildActions(n,i),this.activationgroupIds&&this.buildActivations(n,i)}}_buildRests(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const t="utility",s={shortRest:{name:e.api.Utils.i18n("DND5E.ShortRest")},longRest:{name:e.api.Utils.i18n("DND5E.LongRest")}},n=Object.entries(s).map((s=>{const n=s[0],l=s[1].name,a=`${`${e.api.Utils.i18n(i[t])}: `??""}${l}`,o=[t,n].join(this.delimiter);return{id:n,name:l,encodedValue:o,listName:a}}));this.addActions(n,{id:"rests",type:"system"})}_buildSkills(){const t="skill",s=this.actor?this.actor.system.skills:game.dnd5e.config.skills;if(0===s.length)return;const n=Object.entries(s).map((n=>{try{const l=n[0],a=l.charAt(0).toUpperCase()+l.slice(1),o=this.abbreviateSkills?a:game.dnd5e.config.skills[l].label,c=`${`${e.api.Utils.i18n(i[t])}: `??""}${game.dnd5e.config.skills[l].label}`,d=[t,l].join(this.delimiter),r=this._getProficiencyIcon(s[l].value),p=s[l].mod;return{id:l,name:o,encodedValue:d,icon1:r,info1:this.actor?{text:p||0===p?`${p>=0?"+":""}${p}`:""}:"",listName:c}}catch(t){return e.api.Logger.error(n),null}})).filter((e=>!!e));this.addActions(n,{id:"skills",type:"system"})}_buildSpells(){const t="spell",s=new Map;for(const[e,t]of this.items){if("spell"===t.type){const i=this._isUsableItem(t),n=this._isUsableSpell(t);if(i&&n){switch(t.system.preparation.mode){case"atwill":s.has("at-will-spells")||s.set("at-will-spells",new Map),s.get("at-will-spells").set(e,t);break;case"innate":s.has("innate-spells")||s.set("innate-spells",new Map),s.get("innate-spells").set(e,t);break;case"pact":s.has("pact-spells")||s.set("pact-spells",new Map),s.get("pact-spells").set(e,t);break;default:switch(t.system.level){case 0:s.has("cantrips")||s.set("cantrips",new Map),s.get("cantrips").set(e,t);break;case 1:s.has("1st-level-spells")||s.set("1st-level-spells",new Map),s.get("1st-level-spells").set(e,t);break;case 2:s.has("2nd-level-spells")||s.set("2nd-level-spells",new Map),s.get("2nd-level-spells").set(e,t);break;case 3:s.has("3rd-level-spells")||s.set("3rd-level-spells",new Map),s.get("3rd-level-spells").set(e,t);break;case 4:s.has("4th-level-spells")||s.set("4th-level-spells",new Map),s.get("4th-level-spells").set(e,t);break;case 5:s.has("5th-level-spells")||s.set("5th-level-spells",new Map),s.get("5th-level-spells").set(e,t);break;case 6:s.has("6th-level-spells")||s.set("6th-level-spells",new Map),s.get("6th-level-spells").set(e,t);break;case 7:s.has("7th-level-spells")||s.set("7th-level-spells",new Map),s.get("7th-level-spells").set(e,t);break;case 8:s.has("8th-level-spells")||s.set("8th-level-spells",new Map),s.get("8th-level-spells").set(e,t);break;case 9:s.has("9th-level-spells")||s.set("9th-level-spells",new Map),s.get("9th-level-spells").set(e,t)}}}}}const i=Object.entries(this.actor.system.spells).reverse();let n=null;const l=[];let a=this.showUnchargedItems,o=this.showUnchargedItems;for(const[e,t]of i){const s=t.value>0,i=t.max>0,c=t.level>0;"pact"===e&&(!o&&s&&i&&c&&(o=!0),c||(o=!1),t.slotAvailable=o,n=[e,t]),e.startsWith("spell")&&"spell0"!==e?(!a&&s&&i&&(a=!0),t.slotAvailable=a,l.push([e,t])):s&&(t.slotsAvailable=!0,l.push(e,t))}if(n[1].slotAvailable){const e=l.findIndex((e=>e[0]==="spell"+n[1].level));l[e][1].slotsAvailable=!0}const c={"1st-level-spells":{spellMode:1,name:e.api.Utils.i18n("tokenActionHud.dnd5e.1stLevelSpells")},"2nd-level-spells":{spellMode:2,name:e.api.Utils.i18n("tokenActionHud.dnd5e.2ndLevelSpells")},"3rd-level-spells":{spellMode:3,name:e.api.Utils.i18n("tokenActionHud.dnd5e.3rdLevelSpells")},"4th-level-spells":{spellMode:4,name:e.api.Utils.i18n("tokenActionHud.dnd5e.4thLevelSpells")},"5th-level-spells":{spellMode:5,name:e.api.Utils.i18n("tokenActionHud.dnd5e.5thLevelSpells")},"6th-level-spells":{spellMode:6,name:e.api.Utils.i18n("tokenActionHud.dnd5e.6thLevelSpells")},"7th-level-spells":{spellMode:7,name:e.api.Utils.i18n("tokenActionHud.dnd5e.7thLevelSpells")},"8th-level-spells":{spellMode:8,name:e.api.Utils.i18n("tokenActionHud.dnd5e.8thLevelSpells")},"9th-level-spells":{spellMode:9,name:e.api.Utils.i18n("tokenActionHud.dnd5e.9thLevelSpells")},"at-will-spells":{spellMode:"atwill",name:e.api.Utils.i18n("tokenActionHud.dnd5e.atWillSpells")},cantrips:{spellMode:0,name:e.api.Utils.i18n("tokenActionHud.dnd5e.cantrips")},"innate-spells":{spellMode:"innate",name:e.api.Utils.i18n("tokenActionHud.dnd5e.innateSpells")},"pact-spells":{spellMode:"pact",name:e.api.Utils.i18n("tokenActionHud.dnd5e.pactSpells")}},d=["1","2","3","4","5","6","7","8","9","pact"];for(const e of this.spellgroupIds){const i=c[e].spellMode,a=c[e].name;if(!s.has(e))continue;const o="pact"===i?n[1]:l.find((e=>e[0]===`spell${i}`))?.[1],r=o?.value,p=o?.max,u=o?.slotAvailable;if(!u&&d.includes(i))continue;const m={};m.info1={class:"tah-spotlight",text:p>=0?`${r}/${p}`:""};const h={id:e,name:a,type:"system",info:m};this.addGroupInfo(h);const y=s.get(e);this._buildActions(y,h,t),this.activationgroupIds&&this.buildActivations(y,h,t)}}_buildUtility(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const t="utility",s={deathSave:{name:e.api.Utils.i18n("DND5E.DeathSave")},inspiration:{name:e.api.Utils.i18n("DND5E.Inspiration")}};(!this.actor||this.actor.system.attributes.hp.value>0)&&delete s.deathSave;const n=Object.entries(s).map((s=>{const n=s[0],l=s[1].name,a=`${`${e.api.Utils.i18n(i[t])}: `??""}${l}`,o=[t,n].join(this.delimiter);let c="";if("inspiration"===s[0]){c=`toggle${this.actors.every((e=>e.system.attributes?.inspiration))?" active":""}`}return{id:n,name:l,encodedValue:o,cssClass:c,listName:a}}));this.addActions(n,{id:"utility",type:"system"})}_buildActions(e,t,s="item"){if(0===e.size)return;if(!("string"==typeof t?t:t?.id))return;const i=[...e].map((e=>this._getAction(s,e[1])));this.addActions(i,t)}_getAction(t,s){const n=s.id??s._id;let l=s?.name??s?.label;s?.system?.recharge&&!s?.system?.recharge?.charged&&s?.system?.recharge?.value&&(l+=` (${e.api.Utils.i18n("DND5E.Recharge")})`);const a=`${`${e.api.Utils.i18n(i[t])}: `??""}${l}`;let o="";if(Object.hasOwn(s,"disabled")){o=`toggle${s.disabled?"":" active"}`}const c=[t,n].join(this.delimiter),d=e.api.Utils.getImage(s),r=this._getActivationTypeIcon(s?.system?.activation?.type);let p=null,u=null;"spell"===s.type?(p=this._getPreparedIcon(s),this.displaySpellInfo&&(u=this._getSpellInfo(s))):u=this._getItemInfo(s);const m=u?.info1,h=u?.info2,y=u?.info3;return{id:n,name:l,encodedValue:c,cssClass:o,img:d,icon1:r,icon2:p,info1:m,info2:h,info3:y,listName:a}}_isActiveItem(e){if(this.showItemsWithoutActivationCosts)return!0;const t=Object.keys(game.dnd5e.config.abilityActivationTypes).filter((e=>"none"!==e)),s=e.system.activation,i=s?.type;return!(!s||!t.includes(i))}_isEquippedItem(e){const t=e.type;if(this.showUnequippedItems&&!["consumable","spell","feat"].includes(t))return!0;return!(!e.system.equipped||"consumable"===t)}_isUsableItem(e){if(this.showUnchargedItems)return!0;return!!e.system.uses}_isUsableSpell(e){if("character"!==this.actorType&&this.showUnequippedItems)return!0;const t=e.system.preparation.prepared;if(this.showUnpreparedSpells)return!0;const s=e.system.level,i=Object.keys(game.dnd5e.config.spellPreparationModes).filter((e=>"prepared"!==e)),n=e.system.preparation.mode;return!(0!==s&&!i.includes(n)&&!t)}_getItemInfo(e){return{info1:{text:this._getQuantityData(e)},info2:{text:this._getUsesData(e)},info3:{text:this._getConsumeData(e)}}}_getSpellInfo(t){const s=t.system.components,i=[],n={},l={},a={};if(s?.vocal&&i.push(e.api.Utils.i18n("DND5E.ComponentVerbal")),s?.somatic&&i.push(e.api.Utils.i18n("DND5E.ComponentSomatic")),s?.material&&i.push(e.api.Utils.i18n("DND5E.ComponentMaterial")),i.length&&(n.title=i.join(", "),n.text=i.map((e=>e.charAt(0).toUpperCase())).join("")),s?.concentration){const t=e.api.Utils.i18n("DND5E.Concentration");l.title=t,l.text=t.charAt(0).toUpperCase()}if(s?.ritual){const t=e.api.Utils.i18n("DND5E.Ritual");a.title=t,a.text=t.charAt(0).toUpperCase()}return{info1:n,info2:l,info3:a}}_getActors(){const e=["character","npc"],t=canvas.tokens.controlled.filter((e=>e.actor)).map((e=>e.actor));return t.every((t=>e.includes(t.type)))?t:[]}_getTokens(){const e=["character","npc"],t=canvas.tokens.controlled;return t.filter((e=>e.actor)).map((e=>e.actor)).every((t=>e.includes(t.type)))?t:[]}_getQuantityData(e){const t=e?.system?.quantity??0;return t>1?t:""}_getUsesData(e){const t=e?.system?.uses;return t&&(t.value>0||t.max>0)?`${t.value??"0"}${t.max>0?`/${t.max}`:""}`:""}_getConsumeData(e){const t=e?.system?.consume?.target,s=e?.system?.consume?.type;if("attribute"===s){const e=t.substr(0,t.lastIndexOf(".")),s=this.actor.system[e];return s?`${s.value??"0"}${s.max?`/${s.max}`:""}`:""}const i=this.items.get(t);if("charges"===s){const e=i?.system.uses;return e?.value?`${e.value}${e.max?`/${e.max}`:""}`:""}return i?.system?.quantity??""}_discardSlowItems(e){if(r.getSetting("showSlowActions"))return e;const t=["minute","hour","day"],s=new Map;for(const[i,n]of e.entries()){const e=n.system.activation,l=n.system.activation?.type;e&&!t.includes(l)&&s.set(i,n)}return s}_getProficiencyIcon(e){const t=CONFIG.DND5E.proficiencyLevels[e]??"",s=c[e];if(s)return``}_getActivationTypeIcon(e){const t=CONFIG.DND5E.abilityActivationTypes[e]??"",s=n[e];if(s)return``}_getPreparedIcon(t){const s=t.system.level,i=t.system.preparation.mode,n=t.system.preparation.prepared,l=n?"fas fa-sun":"fas fa-sun tah-icon-disabled",a=n?e.api.Utils.i18n("DND5E.SpellPrepared"):e.api.Utils.i18n("DND5E.SpellUnprepared");return"prepared"===i&&0!==s?``:""}}}));let u=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{const t=d;Object.values(t).forEach((t=>{t.name=e.api.Utils.i18n(t.name),t.listName=`Group: ${e.api.Utils.i18n(t.name)}`}));const s=Object.values(t);u={layout:[{nestId:"inventory",id:"inventory",name:e.api.Utils.i18n("DND5E.Inventory"),groups:[{...t.weapons,nestId:"inventory_weapons"},{...t.equipment,nestId:"inventory_equipment"},{...t.consumables,nestId:"inventory_consumables"},{...t.tools,nestId:"inventory_tools"},{...t.containers,nestId:"inventory_containers"},{...t.loot,nestId:"inventory_loot"}]},{nestId:"features",id:"features",name:e.api.Utils.i18n("DND5E.Features"),groups:[{...t.activeFeatures,nestId:"features_active-features"},{...t.passiveFeatures,nestId:"features_passive-features"}]},{nestId:"spells",id:"spells",name:e.api.Utils.i18n("ITEM.TypeSpellPl"),groups:[{...t.atWillSpells,nestId:"spells_at-will-spells"},{...t.innateSpells,nestId:"spells_innate-spells"},{...t.pactSpells,nestId:"spells_pact-spells"},{...t.cantrips,nestId:"spells_cantrips"},{...t._1stLevelSpells,nestId:"spells_1st-level-spells"},{...t._2ndLevelSpells,nestId:"spells_2nd-level-spells"},{...t._3rdLevelSpells,nestId:"spells_3rd-level-spells"},{...t._4thLevelSpells,nestId:"spells_4th-level-spells"},{...t._5thLevelSpells,nestId:"spells_5th-level-spells"},{...t._6thLevelSpells,nestId:"spells_6th-level-spells"},{...t._7thLevelSpells,nestId:"spells_7th-level-spells"},{...t._8thLevelSpells,nestId:"spells_8th-level-spells"},{...t._9thLevelSpells,nestId:"spells_9th-level-spells"}]},{nestId:"attributes",id:"attributes",name:e.api.Utils.i18n("DND5E.Attributes"),groups:[{...t.abilities,nestId:"attributes_abilities"},{...t.skills,nestId:"attributes_skills"}]},{nestId:"effects",id:"effects",name:e.api.Utils.i18n("DND5E.Effects"),groups:[{...t.temporaryEffects,nestId:"effects_temporary-effects"},{...t.passiveEffects,nestId:"effects_passive-effects"}]},{nestId:"conditions",id:"conditions",name:e.api.Utils.i18n("tokenActionHud.dnd5e.conditions"),groups:[{...t.conditions,nestId:"conditions_conditions"}]},{nestId:"utility",id:"utility",name:e.api.Utils.i18n("tokenActionHud.utility"),groups:[{...t.combat,nestId:"utility_combat"},{...t.token,nestId:"utility_token"},{...t.rests,nestId:"utility_rests"},{...t.utility,nestId:"utility_utility"}]}],groups:s}}));let m=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{m=class MagicItemActionListExtender extends e.api.ActionListExtender{constructor(e){super(e.categoryManager),this.actionHandler=e,this.categoryManager=e.categoryManager,this.actor=null}extendActionList(){if(this.actor=this.actionHandler.actor,!this.actor)return;const t=MagicItems.actor(this.actor.id);if(!t)return;const s=t.items??[];if(0===s.length)return;const i={id:"magic-items",type:"system"};s.forEach((t=>{if(t.attuned&&!this._isItemAttuned(t))return;if(t.equipped&&!this._isItemEquipped(t))return;const s={id:`magic-items_${t.id}`,name:t.name,type:"system-derived",info1:`${t.uses}/${t.charges}`};this.actionHandler.addGroup(s,i);const n=t.ownedEntries.map((s=>{const i=s.item,n=i.id;return{id:n,name:i.name,encodedValue:["magicItem",`${t.id}>${n}`].join("|"),img:e.api.Utils.getImage(i),info1:i.consumption,info2:i.baseLevel?`${e.api.Utils.i18n("DND5E.AbbreviationLevel")} ${i.baseLevel}`:"",selected:!0}}));this.actionHandler.addActions(n,s)}))}_isItemEquipped(e){return e.item.system.equipped}_isItemAttuned(e){return e.item.system.attunment!==(CONFIG.DND5E.attunementTypes?.REQUIRED??1)}}}));let h=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{h=class RollHandler extends e.api.RollHandler{async doHandleActionEvent(e,t){const s=t.split("|");2!==s.length&&super.throwInvalidValueErr();const i=s[0],n=s[1];if(this.actor)await this._handleMacros(e,i,this.actor,this.token,n);else for(const t of canvas.tokens.controlled){const s=t.actor;await this._handleMacros(e,i,s,t,n)}}async _handleMacros(e,t,s,i,n){switch(t){case"ability":this._rollAbility(e,s,n);break;case"check":this._rollAbilityTest(e,s,n);break;case"save":this._rollAbilitySave(e,s,n);break;case"condition":if(!i)return;await this._toggleCondition(e,i,n);break;case"effect":await this._toggleEffect(e,s,n);break;case"feature":case"item":case"spell":case"weapon":this.isRenderItem()?this.doRenderItem(s,n):this._useItem(e,s,n);break;case"magicItem":this._rollMagicItem(s,n);break;case"skill":this._rollSkill(e,s,n);break;case"utility":await this._performUtilityMacro(e,s,i,n)}}_rollAbility(e,t,s){t&&t.system?.abilities&&t.rollAbility(s,{event:e})}_rollAbilitySave(e,t,s){t&&t.system?.abilities&&t.rollAbilitySave(s,{event:e})}_rollAbilityTest(e,t,s){t&&t.system?.abilities&&t.rollAbilityTest(s,{event:e})}_rollMagicItem(e,t){const s=t.split(">"),i=s[0],n=s[1];MagicItems.actor(e.id).roll(i,n),Hooks.callAll("forceUpdateTokenActionHud")}_rollSkill(e,t,s){t&&t.system?.skills&&t.rollSkill(s,{event:e})}_useItem(t,s,i){const n=e.api.Utils.getItem(s,i);if(!this._needsRecharge(n))return n.use({event:t});n.rollRecharge()}_needsRecharge(e){return e.system.recharge&&!e.system.recharge.charged&&e.system.recharge.value}async _performUtilityMacro(e,t,s,i){switch(i){case"deathSave":t.rollDeathSave({event:e});break;case"endTurn":if(!s)break;game.combat?.current?.tokenId===s.id&&await(game.combat?.nextTurn());break;case"initiative":await this._rollInitiative(t);break;case"inspiration":{const e=!t.system.attributes.inspiration;t.update({"data.attributes.inspiration":e});break}case"longRest":t.longRest();break;case"shortRest":t.shortRest()}Hooks.callAll("forceUpdateTokenActionHud")}async _rollInitiative(e){e&&(await e.rollInitiative({createCombatants:!0}),Hooks.callAll("forceUpdateTokenActionHud"))}async _toggleCondition(e,t,s,i=null){if(!t)return;const n=this.isRightClick(e);if(game.dfreds&&i?.flags?.isConvenient){const e=i.label;game.dfreds.effectInterface._toggleEffect(e)}else{const e=this.findCondition(s);if(!e)return;n?await t.toggleEffect(e,{overlay:!0}):await t.toggleEffect(e)}Hooks.callAll("forceUpdateTokenActionHud")}findCondition(e){return CONFIG.statusEffects.find((t=>t.id===e))}async _toggleEffect(e,t,s){const i=("find"in t.effects.entries?t.effects.entries:t.effects).find((e=>e.id===s));if(!i)return;this.isRightClick(e)?await i.delete():await i.update({disabled:!i.disabled}),Hooks.callAll("forceUpdateTokenActionHud")}}}));class RollHandlerObsidian extends h{_rollAbilityTest(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"abl",abl:t})}_rollAbilitySave(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"save",save:t})}_rollSkill(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"skl",skl:t})}_useItem(e,t){OBSIDIAN.Items.roll(super.actor,{roll:"item",id:t})}}function register(t){game.settings.register(e.ID,"abbreviateSkills",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.abbreviateSkills.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.abbreviateSkills.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showSlowActions",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showSlowActions.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showSlowActions.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"displaySpellInfo",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.displaySpellInfo.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.displaySpellInfo.hint"),scope:"client",config:!0,type:Boolean,default:!0,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnchargedItems",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnchargedItems.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnchargedItems.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnequippedItems",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItems.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItems.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showUnpreparedSpells",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnpreparedSpells.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnpreparedSpells.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}}),game.settings.register(e.ID,"showItemsWithoutActivationCosts",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.hint"),scope:"client",config:!0,type:Boolean,default:!1,onChange:e=>{t(e)}})}let y=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{y=class SystemManager extends e.api.SystemManager{doGetCategoryManager(){return new e.api.CategoryManager}doGetActionHandler(t){const s=new p(t);return e.api.Utils.isModuleActive("magicitems")&&s.addFurtherActionHandler(new m(s)),s}getAvailableRollHandlers(){let t="Core D&D5e";e.api.Utils.isModuleActive("midi-qol")&&(t+=` [supports ${e.api.Utils.getModuleTitle("midi-qol")}]`);const s={core:t};return e.api.SystemManager.addHandler(s,"obsidian"),s}doGetRollHandler(e){let t;if("obsidian"===e)t=new RollHandlerObsidian;else t=new h;return t}doRegisterSettings(e){register(e)}async doRegisterDefaultFlags(){const t=u;if(game.modules.get("magicitems")?.active){const s=e.api.Utils.i18n("tokenActionHud.dnd5e.magicItems");t.groups.push({id:"magic-items",name:s,listName:`Group: ${s}`,type:"system"}),t.groups.sort(((e,t)=>e.id.localeCompare(t.id)))}return t}}})),Hooks.on("tokenActionHudCoreApiReady",(async()=>{const t=game.modules.get(e.ID);t.api={requiredCoreModuleVersion:"1.4",SystemManager:y},Hooks.call("tokenActionHudSystemReady",t)}));export{i as ACTION_TYPE,n as ACTIVATION_TYPE_ICON,p as ActionHandler,l as CONCENTRATION_ICON,t as CORE_MODULE,u as DEFAULTS,d as GROUP,e as MODULE,m as MagicItemActionListExtender,a as PREPARED_ICON,c as PROFICIENCY_LEVEL_ICON,s as REQUIRED_CORE_MODULE_VERSION,o as RITUAL_ICON,h as RollHandler,RollHandlerObsidian,y as SystemManager,r as Utils,register};