From 1843ecb5cd5734ab380fdb68bf71410cdf6ee2c1 Mon Sep 17 00:00:00 2001 From: Russell Larkin Date: Thu, 6 Apr 2023 01:37:21 +0100 Subject: [PATCH] #28 - Handle unlinked tokens. --- scripts/action-handler.js | 4 ++-- scripts/roll-handler.js | 5 +++++ scripts/token-action-hud-dnd5e.min.js | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/scripts/action-handler.js b/scripts/action-handler.js index dc7214d..a7b3f48 100644 --- a/scripts/action-handler.js +++ b/scripts/action-handler.js @@ -1124,7 +1124,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { */ _getActors () { const allowedTypes = ['character', 'npc'] - const actors = canvas.tokens.controlled.map((token) => token.actor) + const actors = canvas.tokens.controlled.filter(token => token.actor).map((token) => token.actor) if (actors.every((actor) => allowedTypes.includes(actor.type))) { return actors } } @@ -1136,7 +1136,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { _getTokens () { const allowedTypes = ['character', 'npc'] const tokens = canvas.tokens.controlled - const actors = tokens.map((token) => token.actor) + const actors = tokens.filter(token => token.actor).map((token) => token.actor) if (actors.every((actor) => allowedTypes.includes(actor.type))) { return tokens } } diff --git a/scripts/roll-handler.js b/scripts/roll-handler.js index 822dae9..1f294bc 100644 --- a/scripts/roll-handler.js +++ b/scripts/roll-handler.js @@ -84,6 +84,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @param {string} actionId The action id */ _rollAbility (event, actor, actionId) { + if (!actor) return actor.rollAbility(actionId, { event }) } @@ -95,6 +96,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @param {string} actionId The action id */ _rollAbilitySave (event, actor, actionId) { + if (!actor) return actor.rollAbilitySave(actionId, { event }) } @@ -106,6 +108,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @param {string} actionId The action id */ _rollAbilityTest (event, actor, actionId) { + if (!actor) return actor.rollAbilityTest(actionId, { event }) } @@ -137,6 +140,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @param {string} actionId The action id */ _rollSkill (event, actor, actionId) { + if (!actor) return actor.rollSkill(actionId, { event }) } @@ -217,6 +221,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @private */ async _rollInitiative (actor) { + if (!actor) return await actor.rollInitiative({ createCombatants: true }) Hooks.callAll('forceUpdateTokenActionHud') diff --git a/scripts/token-action-hud-dnd5e.min.js b/scripts/token-action-hud-dnd5e.min.js index fb0d710..a8e2139 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.2",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 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);d={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 p=null;Hooks.once("tokenActionHudCoreApiReady",(async t=>{p=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 u=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{u=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=p.getSetting("abbreviateSkills"),this.displaySpellInfo=p.getSetting("displaySpellInfo"),this.showItemsWithoutActivationCosts=p.getSetting("showItemsWithoutActivationCosts"),this.showUnchargedItems=p.getSetting("showUnchargedItems"),this.showUnequippedItems=p.getSetting("showUnequippedItems"),this.showUnpreparedSpells=p.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(!this.token&&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(){if(!this.actor)return;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(!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 h={};h.info1={class:"tah-spotlight",text:p>=0?`${d}/${p}`:""};const m={id:e,name:l,type:"system",info:h};this.addSubcategoryInfo(m);const y=s.get(e);this._buildActions(y,m,t),this.activationSubcategoryIds&&this.buildActivations(y,m,t)}}_buildUtility(){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 h=u?.info1,m=u?.info2,y=u?.info3;return{id:n,name:a,encodedValue:c,cssClass:o,img:r,icon1:d,icon2:p,info1:h,info2:m,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.map((e=>e.actor));if(t.every((t=>e.includes(t.type))))return t}_getTokens(){const e=["character","npc"],t=canvas.tokens.controlled;if(t.map((e=>e.actor)).every((t=>e.includes(t.type))))return 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(p.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 h=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{h=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 m=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{m=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.rollAbility(s,{event:e})}_rollAbilitySave(e,t,s){t.rollAbilitySave(s,{event:e})}_rollAbilityTest(e,t,s){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.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){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 m{_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 u(t);return e.api.Utils.isModuleActive("magicitems")&&s.addFurtherActionHandler(new h(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 m;return t}doRegisterSettings(e){register(e)}async doRegisterDefaultFlags(){const t=d;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.2",SystemManager:y},Hooks.call("tokenActionHudSystemReady",t)}));export{i as ACTION_TYPE,n as ACTIVATION_TYPE_ICON,u as ActionHandler,a as CONCENTRATION_ICON,t as CORE_MODULE,d as DEFAULTS,e as MODULE,h as MagicItemActionListExtender,l as PREPARED_ICON,c as PROFICIENCY_LEVEL_ICON,s as REQUIRED_CORE_MODULE_VERSION,o as RITUAL_ICON,m as RollHandler,RollHandlerObsidian,r as SUBCATEGORY,y as SystemManager,p as Utils,register}; +const e={ID:"token-action-hud-dnd5e"},t={ID:"token-action-hud-core"},s="1.2",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(!this.token&&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(!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 h={};h.info1={class:"tah-spotlight",text:p>=0?`${d}/${p}`:""};const m={id:e,name:l,type:"system",info:h};this.addSubcategoryInfo(m);const y=s.get(e);this._buildActions(y,m,t),this.activationSubcategoryIds&&this.buildActivations(y,m,t)}}_buildUtility(){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 h=u?.info1,m=u?.info2,y=u?.info3;return{id:n,name:a,encodedValue:c,cssClass:o,img:r,icon1:d,icon2:p,info1:h,info2:m,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));if(t.every((t=>e.includes(t.type))))return t}_getTokens(){const e=["character","npc"],t=canvas.tokens.controlled;if(t.filter((e=>e.actor)).map((e=>e.actor)).every((t=>e.includes(t.type))))return 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=>{u=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=>{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);h={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 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.rollAbility(s,{event:e})}_rollAbilitySave(e,t,s){t&&t.rollAbilitySave(s,{event:e})}_rollAbilityTest(e,t,s){t&&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.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 m{_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 u(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 m;return t}doRegisterSettings(e){register(e)}async doRegisterDefaultFlags(){const t=h;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.2",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,h as DEFAULTS,e as MODULE,u as MagicItemActionListExtender,l as PREPARED_ICON,c as PROFICIENCY_LEVEL_ICON,s as REQUIRED_CORE_MODULE_VERSION,o as RITUAL_ICON,m as RollHandler,RollHandlerObsidian,r as SUBCATEGORY,y as SystemManager,d as Utils,register};