From 88959d8c971b2e3ecd27a27393be4d89c16ca948 Mon Sep 17 00:00:00 2001 From: Russell Larkin Date: Mon, 4 Nov 2024 22:14:55 +0000 Subject: [PATCH] #130 - #130: Fix rolling abilities. --- scripts/action-handler.js | 2 +- scripts/token-action-hud-dnd5e.min.js | 2 +- scripts/token-action-hud-dnd5e.min.js.map | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/action-handler.js b/scripts/action-handler.js index 9ed05a4..d5168ea 100644 --- a/scripts/action-handler.js +++ b/scripts/action-handler.js @@ -169,7 +169,7 @@ Hooks.once("tokenActionHudCoreApiReady", async coreModule => { title: `${game.i18n.localize("DND5E.SavingThrow")}: ${coreModule.api.Utils.getModifier(ability?.save)}` } : null, listName: this.#getListName(actionType, name), - system: { actionType, abilityId } + system: { actionType, actionId: abilityId } }; }); diff --git a/scripts/token-action-hud-dnd5e.min.js b/scripts/token-action-hud-dnd5e.min.js index af7dadb..d626b7d 100644 --- a/scripts/token-action-hud-dnd5e.min.js +++ b/scripts/token-action-hud-dnd5e.min.js @@ -1,2 +1,2 @@ -const e={ID:"token-action-hud-dnd5e"},t={ID:"token-action-hud-core"},s="2.0",i={ability:"DND5E.Ability",check:"tokenActionHud.dnd5e.check",condition:"tokenActionHud.dnd5e.condition",counter:"tokenActionHud.dnd5e.counter",effect:"DND5E.Effect",exhaustion:"DND5E.Exhaustion",feature:"TYPES.Item.feat",item:"tokenActionHud.dnd5e.item",save:"DND5E.SAVE.Title.one",skill:"tokenActionHud.dnd5e.skill",spell:"TYPES.Item.spell",utility:"DND5E.ActionUtil"},n={action:{group:"actions"},bonus:{group:"bonus-actions",icon:"fas fa-plus"},crew:{group:"crew-actions",icon:"fas fa-users"},day:{icon:"fas fa-hourglass-end"},hour:{icon:"fas fa-hourglass-half"},lair:{group:"lair-actions",icon:"fas fa-home"},minute:{icon:"fas fa-hourglass-start"},legendary:{group:"legendary-actions",icon:"fas fas fa-dragon"},reaction:{group:"reactions",icon:"fas fa-bolt"},reactiondamage:{group:"reactions",icon:"fas fa-bolt"},reactionmanual:{group:"reactions",icon:"fas fa-bolt"},special:{group:"special-actions",icon:"fas fa-star"},other:{group:"other-actions"}},a="systems/dnd5e/icons/svg/statuses/concentrating.svg",o={ID:"custom-dnd5e",COUNTERS:{character:"character-counters",group:"group-counters",npc:"npc-counters"}},l=["activeFeatures","passiveFeatures","backgroundFeatures","classFeatures","feats","monsterFeatures","raceFeatures","artificerInfusions","channelDivinity","defensiveTactics","eldritchInvocations","elementalDisciplines","fightingStyles","huntersPrey","kiAbilities","maneuvers","metamagicOptions","multiattacks","pactBoons","psionicPowers","runes","superiorHuntersDefense"],c={_1stLevelSpells:{id:"1st-level-spells",name:"tokenActionHud.dnd5e.1stLevelSpells",spellMode:1,type:"system"},_2ndLevelSpells:{id:"2nd-level-spells",name:"tokenActionHud.dnd5e.2ndLevelSpells",spellMode:2,type:"system"},_3rdLevelSpells:{id:"3rd-level-spells",name:"tokenActionHud.dnd5e.3rdLevelSpells",spellMode:3,type:"system"},_4thLevelSpells:{id:"4th-level-spells",name:"tokenActionHud.dnd5e.4thLevelSpells",spellMode:4,type:"system"},_5thLevelSpells:{id:"5th-level-spells",name:"tokenActionHud.dnd5e.5thLevelSpells",spellMode:5,type:"system"},_6thLevelSpells:{id:"6th-level-spells",name:"tokenActionHud.dnd5e.6thLevelSpells",spellMode:6,type:"system"},_7thLevelSpells:{id:"7th-level-spells",name:"tokenActionHud.dnd5e.7thLevelSpells",spellMode:7,type:"system"},_8thLevelSpells:{id:"8th-level-spells",name:"tokenActionHud.dnd5e.8thLevelSpells",spellMode:8,type:"system"},_9thLevelSpells:{id:"9th-level-spells",name:"tokenActionHud.dnd5e.9thLevelSpells",spellMode:9,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",spellMode:"atwill",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",spellMode:0,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:"TYPES.Item.consumablePl",type:"system"},containers:{id:"containers",name:"TYPES.Item.containerPl",type:"system"},counters:{id:"counters",name:"tokenActionHud.dnd5e.counters",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:"TYPES.Item.equipmentPl",type:"system"},equipped:{id:"equipped",name:"DND5E.Equipped",type:"system"},exhaustion:{id:"exhaustion",name:"DND5E.Exhaustion",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",spellMode:"innate",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:"TYPES.Item.lootPl",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",spellMode:"pact",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:"TYPES.Item.toolPl",type:"system"},unequipped:{id:"unequipped",name:"DND5E.Unequipped",type:"system"},utility:{id:"utility",name:"tokenActionHud.utility",type:"system"},weapons:{id:"weapons",name:"TYPES.Item.weaponPl",type:"system"}},r="fas fa-sun",d={0:"fa-regular fa-circle",.5:"fa-regular fa-circle-half-stroke",1:"fa-solid fa-circle",2:"fa-regular fa-circle-dot"},p={common:"tokenActionHud.dnd5e.common",uncommon:"tokenActionHud.dnd5e.uncommon",rare:"tokenActionHud.dnd5e.rare",veryRare:"tokenActionHud.dnd5e.veryRare",legendary:"tokenActionHud.dnd5e.legendary",artifact:"tokenActionHud.dnd5e.artifact"},u="fas fa-circle-r",m=["cantrips","_1stLevelSpells","_2ndLevelSpells","_3rdLevelSpells","_4thLevelSpells","_5thLevelSpells","_6thLevelSpells","_7thLevelSpells","_8thLevelSpells","_9thLevelSpells","atWillSpells","innateSpells","pactSpells"];let h=null;Hooks.once("tokenActionHudCoreApiReady",(async t=>{h=class Utils{static capitalize(e){return e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substring(1).toLowerCase()))}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 y=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{y=class ActionHandler extends e.api.ActionHandler{featureActions=null;inventoryActions=null;spellActions=null;async buildSystemActions(t){this.actors=this.actor?[this.actor]:this.#e(),this.tokens=this.token?[this.token]:this.#t(),this.actor&&(this.items=e.api.Utils.sortItemsByName(this.#s(this.actor.items))),this.abbreviateSkills=h.getSetting("abbreviateSkills"),this.displaySpellInfo=h.getSetting("displaySpellInfo"),this.showItemsWithoutActivationCosts=h.getSetting("showItemsWithoutActivationCosts"),this.showUnchargedItems=h.getSetting("showUnchargedItems"),this.showUnequippedItems=h.getSetting("showUnequippedItems"),"npc"!==this.actor?.type||this.showUnequippedItems||(this.showUnequippedItems=h.getSetting("showUnequippedItemsNpcs")),this.showUnpreparedSpells=h.getSetting("showUnpreparedSpells"),this.activationgroupIds=["actions","bonus-actions","crew-actions","lair-actions","legendary-actions","reactions","other-actions"],"character"===this.actor?.type||"npc"===this.actor?.type?(this.inventorygroupIds=["equipped","consumables","containers","equipment","loot","tools","weapons","unequipped"],await this.#i()):"vehicle"===this.actor?.type?(this.inventorygroupIds=["consumables","equipment","tools","weapons"],await this.#n()):this.actor||await this.#a()}async#i(){await Promise.all([this.#o(),this.#l(),this.#c(),this.#r(),this.#d()]),this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),this.#m(),this.#h(),this.#y(),this.#g(),this.#f()}async#n(){await Promise.all([this.#o(),this.#l(),this.#c(),this.#r()]),this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),this.#f()}async#a(){this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),await this.#o(),this.#y(),this.#g(),this.#f()}#p(t,s){const i=this.actor?.system.abilities||CONFIG.DND5E.abilities;if(0===i.length)return;const n=Object.entries(i).filter((e=>0!==i[e[0]].value)).map((([n,a])=>{const o=CONFIG.DND5E.abilities[n].label,l="saves"===s?a?.save:a?.mod;return{id:`${t}-${n}`,name:this.abbreviateSkills?h.capitalize(n):o,icon1:"checks"!==s?this.#v(i[n].proficient):"",info1:this.actor?{text:e.api.Utils.getModifier(l),title:`${game.i18n.localize("DND5E.ActionAbil")}: ${e.api.Utils.getModifier(l)}`}:null,info2:this.actor&&"abilities"===s?{text:`(${e.api.Utils.getModifier(a?.save)})`,title:`${game.i18n.localize("DND5E.SavingThrow")}: ${e.api.Utils.getModifier(a?.save)}`}:null,listName:this.#b(t,o),system:{actionType:t,abilityId:n}}}));this.addActions(n,{id:s})}async buildActivations(e){const{groupData:t,actionData:s,actionType:i="item"}=e,a=new Map;for(const[e,t]of s){const s=t.system?.activities?.contents[0]?.activation?.type,i=n[s]?.group??"other";a.has(i)||a.set(i,new Map),a.get(i).set(e,t)}for(const e of Object.values(n)){const s=e.group;if(!a.has(s))continue;const n={...t,id:`${s}+${t.id}`,type:"system-derived"};["equipped","unequipped"].includes(t.id)&&(n.defaultSelected=!1);const o={id:s,type:"system"};await this.addGroup(n,o),"spell"===i&&this.addGroupInfo(n),await this.buildActions({groupData:n,actionData:a.get(s),actionType:i})}}#u(){const t={initiative:"tokenActionHud.dnd5e.rollInitiative",...game.combat?.current?.tokenId!==this.token?.id&&{endTurn:"tokenActionHud.endTurn"}},s=e.api.Utils.getControlledTokens(),i=s?.map((e=>e.id)),n=game.combat?game.combat.combatants.filter((e=>i.includes(e.tokenId))):[],getInfo1=e=>{if("initiative"===e&&1===n.length){return{class:"tah-spotlight",text:n[0].initiative}}return{}},a="utility",o=Object.entries(t).map((([e,t])=>({id:e,name:game.i18n.localize(t),info1:getInfo1(e),cssClass:"initiative"===e?"toggle"+(n.length>0&&n.every((e=>e?.initiative))?" active":""):"",listName:this.#b(a,t),system:{actionType:a,actionId:e}})));this.addActions(o,{id:"combat"})}async#o(){if(0===this.tokens?.length)return;const t=CONFIG.statusEffects.filter((e=>""!==e.id));if(0===t.length)return;const s="condition",i=await Promise.all(t.map((async t=>{const i=this.actors.every((e=>e.effects.some((e=>e.statuses.some((e=>e===t.id))&&!e?.disabled)))),n=game.i18n.localize(t.label)??t.name;return{id:t.id,name:n,img:e.api.Utils.getImage(t),cssClass:"toggle"+(i?" active":""),listName:this.#b(s,n),tooltip:await this.#k(await this.#A(t.id,t.name)),system:{actionType:s,actionId:t.id}}})));this.addActions(i,{id:"conditions"})}async#m(){if(!e.api.Utils.isModuleActive(o.ID)||!o.COUNTERS[this.actor?.type])return;const t="counter";let s=game.settings.get(o.ID,o.COUNTERS[this.actor?.type])??{};s=e.api.Utils.isModuleActive(o.ID)&&Object.keys(s).length?Object.entries(s).filter((([e,t])=>t.visible)).map((([e,t])=>(t.key=e,t))):[{name:game.i18n.localize("DND5E.DeathSave"),type:"successFailure",system:!0,visible:!0,key:"death-saves"},{name:game.i18n.localize("DND5E.Exhaustion"),type:"number",system:!0,visible:!0,key:"exhaustion"},{name:game.i18n.localize("DND5E.Inspiration"),type:"checkbox",system:!0,visible:!0,key:"inspiration"}];const i=s.map((s=>{let i="",n="",a="",l="";if(s.system)switch(s.key){case"exhaustion":i=this.actor.system.attributes.exhaustion>0?" active":"",n=`toggle${i}`,a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/exhaustion.svg"),l={text:this.actor.system.attributes.exhaustion};break;case"death-saves":a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/death-saves.svg"),l={text:`${this.actor.system.attributes.death.success}/${this.actor.system.attributes.death.failure}`};break;case"inspiration":i=this.actor.system.attributes.inspiration?" active":"",n=`toggle${i}`,a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/inspiration.svg")}else{const e=this.actor.getFlag(o.ID,s.key);switch(s.type){case"checkbox":i=e?" active":"",n=`toggle${i}`;break;case"fraction":i=e.value>0?" active":"",n=`toggle${i}`,l={text:`${e.value??0}/${e.max??0}`};break;case"number":i=e>0?" active":"",n=`toggle${i}`,l={text:e};break;case"successFailure":l={text:`${e?.success??0}/${e?.failure??0}`}}}return{id:s.key,name:s.label,listName:this.#b(t,s.name),cssClass:n,img:a,info1:l,system:{actionType:t,counterKey:s.key,counterType:s.type}}}));this.addActions(i,{id:"counters"})}async#l(){const e="effect",t=new Map(this.actor.allApplicableEffects().map((e=>[e.id,e])));if(0===t.size)return;const s=new Map,i=new Map,n=new Set(CONFIG.statusEffects.map((e=>e._id)));for(const[e,a]of t.entries())a.isSuppressed||(!1!==a.parent?.system?.identified||game.user.isGM)&&(n.has(a.id)||(a.isTemporary?i.set(e,a):s.set(e,a)));await Promise.all([this.buildActions({groupData:{id:"passive-effects"},actionData:s,actionType:e}),this.buildActions({groupData:{id:"temporary-effects"},actionData:i,actionType:e})])}#h(){if(!this.actors.every((e=>"character"===e.type)))return;const t="exhaustion",s=this.actor.system.attributes.exhaustion>0?" active":"",i=[{id:"exhaustion",name:game.i18n.localize("DND5E.Exhaustion"),cssClass:`toggle${s}`,img:e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/exhaustion.svg"),info1:{text:this.actor.system.attributes.exhaustion},listName:this.#b(t,name),system:{actionType:t,actionId:"exhaustion"}}];this.addActions(i,{id:"exhaustion"})}async#c(){const e=new Map([...this.items].filter((([,e])=>"feat"===e.type)));if(0===e.size)return;const t=new Map([["activeFeatures",new Map],["passiveFeatures",new Map]]),s={background:"backgroundFeatures",class:"classFeatures",monster:"monsterFeatures",race:"raceFeatures",feats:"feats"},i={artificerInfusion:"artificerInfusions",channelDivinity:"channelDivinity",defensiveTactic:"defensiveTactics",eldritchInvocation:"eldritchInvocations",elementalDiscipline:"elementalDisciplines",fightingStyle:"fightingStyles",huntersPrey:"huntersPrey",ki:"kiAbilities",maneuver:"maneuvers",metamagic:"metamagicOptions",multiattack:"multiattacks",pact:"pactBoons",psionicPower:"psionicPowers",rune:"runes",superiorHuntersDefense:"superiorHuntersDefense"};for(const[n,a]of e){const e=a.system.activities.contents[0]?.type,o=a.system.type.value,l=a.system.type?.subtype;e?t.get("activeFeatures").set(n,a):t.get("passiveFeatures").set(n,a),s[o]&&(t.has(s[o])||t.set(s[o],new Map),t.get(s[o]).set(n,a)),i[l]&&(t.has(i[l])||t.set(i[l],new Map),t.get(i[l]).set(n,a))}for(const e of l){const s=t.get(e);if(!s||0===s.size)continue;const i={id:c[e].id,name:game.i18n.localize(c[e].name)??""},n="feature";await this.buildActions({groupData:i,actionData:s,actionType:n}),await this.buildActivations({groupData:i,actionData:s,actionType:n})}}async#r(){if(0===this.items.size)return;const e=new Map([["equipped",new Map],["unequipped",new Map],["consumables",new Map],["containers",new Map],["equipment",new Map],["loot",new Map],["tools",new Map],["weapons",new Map]]);for(const[t,s]of this.items)if(s.system?.quantity>0&&this.#I(s)&&(s.system.equipped?e.get("equipped").set(t,s):e.get("unequipped").set(t,s),this.#w(s)&&"consumable"===s.type&&e.get("consumables").set(t,s),this.#S(s)))switch(s.type){case"container":e.get("containers").set(t,s);break;case"equipment":e.get("equipment").set(t,s);break;case"loot":e.get("loot").set(t,s);break;case"tool":e.get("tools").set(t,s);break;case"weapon":e.get("weapons").set(t,s)}for(const t of this.inventorygroupIds){const s=e.get(t);if(!s||0===s.size)continue;const i={groupData:{id:t,name:game.i18n.localize(c[t].name)},actionData:s};await this.buildActions(i),await this.buildActivations(i)}}#y(){if(0===this.actors.length||!this.actors.every((e=>"character"===e.type)))return;const e="utility",t=Object.entries({shortRest:"DND5E.ShortRest",longRest:"DND5E.LongRest"}).map((([t,s])=>({id:t,name:s=game.i18n.localize(s),listName:this.#b(e,s),system:{actionType:e,actionId:t}})));this.addActions(t,{id:"rests"})}#g(){const t=this.actor?.system.skills||CONFIG.DND5E.skills;if(0===t.length)return;const s="skill",i=Object.entries(t).map((([t,i])=>{try{const n=CONFIG.DND5E.skills[t].label;return{id:t,name:this.abbreviateSkills?h.capitalize(t):n,icon1:this.#v(i.value),info1:this.actor?{text:e.api.Utils.getModifier(i.total)}:"",listName:this.#b(s,n),system:{actionType:s,actionId:t}}}catch(t){return e.api.Logger.error(i),null}})).filter((e=>!!e));this.addActions(i,{id:"skills"})}async#d(){const e=new Map([...this.items].filter((([,e])=>"spell"===e.type)));if(0===e.size)return;const t=new Map([["atWillSpells",new Map],["innateSpells",new Map],["pactSpells",new Map],["cantrips",new Map],["_1stLevelSpells",new Map],["_2ndLevelSpells",new Map],["_3rdLevelSpells",new Map],["_4thLevelSpells",new Map],["_5thLevelSpells",new Map],["_6thLevelSpells",new Map],["_7thLevelSpells",new Map],["_8thLevelSpells",new Map],["_9thLevelSpells",new Map]]);for(const[s,i]of e)if(this.#w(i)&&this.#D(i))switch(i.system.preparation.mode){case"atwill":t.get("atWillSpells").set(s,i);break;case"innate":t.get("innateSpells").set(s,i);break;case"pact":t.get("pactSpells").set(s,i);break;default:switch(i.system.level){case 0:t.get("cantrips").set(s,i);break;case 1:t.get("_1stLevelSpells").set(s,i);break;case 2:t.get("_2ndLevelSpells").set(s,i);break;case 3:t.get("_3rdLevelSpells").set(s,i);break;case 4:t.get("_4thLevelSpells").set(s,i);break;case 5:t.get("_5thLevelSpells").set(s,i);break;case 6:t.get("_6thLevelSpells").set(s,i);break;case 7:t.get("_7thLevelSpells").set(s,i);break;case 8:t.get("_8thLevelSpells").set(s,i);break;case 9:t.get("_9thLevelSpells").set(s,i)}}const s=Object.entries(this.actor.system.spells).reverse(),i=new Map;let n=this.showUnchargedItems,a=this.showUnchargedItems,o=null;for(const[e,t]of s){const s=t.value>0,l=t.max>0,c=t.level>0;"pact"===e?(a=a||s&&l&&c,t.slotAvailable=a&&c,o=[e,t]):e.startsWith("spell")&&"spell0"!==e?(n=n||s&&l,t.slotAvailable=n,i.set(e,t)):s&&(t.slotsAvailable=!0,i.set(e,t))}if(o[1].slotAvailable){i.get(`spell${o[1].level}`).slotsAvailable=!0}const l=new Set([1,2,3,4,5,6,7,8,9,"pact"]);for(const e of m){if(!t.has(e))continue;const s=c[e].spellMode,n="pact"===s?o[1]:i.get(`spell${s}`),{value:a=0,max:r=0,slotAvailable:d=!1}=n||{};if(!d&&l.has(s))continue;const p={id:c[e].id,name:game.i18n.localize(c[e].name),info:{info1:{class:"tah-spotlight",text:r>0?`${a}/${r}`:""}}};this.addGroupInfo(p);const u={groupData:p,actionData:t.get(e),actionType:"spell"};await this.buildActions(u),await this.buildActivations(u)}}#f(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const e="utility",t={deathSave:{name:game.i18n.localize("DND5E.DeathSave")},inspiration:{name:game.i18n.localize("DND5E.Inspiration")}};(!this.actor||this.actor.system.attributes.hp.value>0)&&delete t.deathSave;const s=Object.entries(t).map((t=>{const s=t[0],i=t[1].name;let n="";if("inspiration"===t[0]){n=`toggle${this.actors.every((e=>e.system.attributes?.inspiration))?" active":""}`}return{id:s,name:i,cssClass:n,listName:this.#b(e,i),system:{actionType:e,actionId:s}}}));this.addActions(s,{id:"utility"})}async buildActions(e,t){const{actionData:s,groupData:i,actionType:n}=e;if(0===s.size)return;if(!("string"==typeof i?i:i?.id))return;const a=await Promise.all([...s].map((async e=>await this.#H(e[1],n))));this.addActions(a,i)}async#H(t,s="item"){const i=t.id??t._id;let n=t?.name??t?.label,a="";if(Object.hasOwn(t,"disabled")){a=`toggle${t.disabled?"":" active"}`}const o=this.#E(t),l=await this.#k(await this.#C(t));return{id:i,name:n,cssClass:a,img:e.api.Utils.getImage(t),icon1:this.#N(t.system?.activities?.contents[0]?.activation.type),icon2:this.#$(t),icon3:this.#U(t),info1:o?.info1,info2:o?.info2,info3:o?.info3,listName:this.#b(s,n),tooltip:l,system:{actionType:s,actionId:i}}}#I(e){if(this.showItemsWithoutActivationCosts)return!0;const t=new Set(Object.keys(CONFIG.DND5E.activityActivationTypes).filter((e=>"none"!==e))),s=e.system?.activities?.contents[0]?.activation?.type;return t.has(s)||"tool"===e.type}#S(e){return this.showUnequippedItems&&!["consumable","spell","feat"].includes(e.type)||e.system.equipped&&"consumable"!==e.type}#w(e){return this.showUnchargedItems||!!e.system.uses?.value||!e.system.uses?.max}#D(e){if("character"!==this.actor?.type&&this.showUnequippedItems)return!0;if(this.showUnpreparedSpells)return!0;return new Set(Object.keys(CONFIG.DND5E.spellPreparationModes).filter((e=>"prepared"!==e))).has(e.system.preparation.mode)||e.system.preparation.prepared}#b(e,t){return`${`${game.i18n.localize(i[e])}: `??""}${t}`??""}#E(e){return{info1:"spell"===e.type?this.#_(e):this.#T(e),info2:this.#M(e),info3:this.#L(e)}}#_(e){if(!this.displaySpellInfo)return null;const t=e.system?.properties;if(!t)return null;const s={text:"",title:""},i=Object.entries({vocal:"DND5E.ComponentVerbal",somatic:"DND5E.ComponentSomatic",material:"DND5E.ComponentMaterial"}).filter((([e])=>t[e])).map((([e,t])=>(s.text+=game.i18n.localize(`${t}Abbr`),game.i18n.localize(t))));return t.ritual&&(i.push(`[${game.i18n.localize("DND5E.Ritual")}]`),s.text+=` [${game.i18n.localize("DND5E.RitualAbbr")}]`),s.title=i.join(", "),s}#e(){const e=["character","npc"];return this.actors.every((t=>e.includes(t.type)))?this.actors:[]}#t(){const e=["character","npc"];return this.actors.every((t=>e.includes(t.type)))?this.tokens:[]}#T(e){const t=e?.system?.quantity??0;return{text:t>1?t:"",title:`${game.i18n.localize("DND5E.Quantity")}: ${t}`}}#M(e){const t=e?.system?.uses;if(!(t?.max>0))return{};const s="charges"===t.recovery[0]?.period?"":` ${game.i18n.localize("DND5E.per")} `,i=CONFIG.DND5E.limitedUsePeriods[t.recovery[0]?.period]?.label??t.recovery[0]?.period,n=i?`${s}${i}`:"",a=`${t.max-(t.spent??0)}/${t.max}`;return{text:a,title:`${a}${n}`}}#L(e){const t=e?.system?.activities?.contents[0],s=t?.consumption?.targets?.[0],i=s?.target,n=s?.type,a=s?.value;if(!i||!n||i===e.id)return{};if("attribute"===n){const e=i.substr(0,i.lastIndexOf(".")),t=foundry.utils.getProperty(this.actor.system,e);if(t){const e=`${t.value??"0"}${t.max?`/${t.max}`:""}`;return{text:e,title:`${e} ${t.label??""}`}}}else{const e=this.actor.items?.get(i);if(e&&"charges"===n)return this.#M(e);if(e?.system?.quantity){const t=`${a>1?`${a} ${game.i18n.localize("DND5E.of")} `:""}${e.system.quantity}`;return{text:t,title:`${t} ${e.name}`}}}return{}}#s(e){if(h.getSetting("showSlowActions"))return e;const t=new Set(["minute","hour","day"]);return new Map([...e.entries()].filter((([e,s])=>{const i=s.system?.activation?.type;return!t.has(i)})))}#v(e){const t=CONFIG.DND5E.proficiencyLevels[e]??"",s=d[e];return s?``:""}#N(e){const t=CONFIG.DND5E.abilityActivationTypes[e]??"",s=n[e]?.icon;return s?``:""}#U(e){if("spell"!==e?.type||!this.displaySpellInfo||!e.system?.properties?.has("concentration"))return null;const t=game.i18n.localize("DND5E.Scroll.RequiresConcentration");return``}#$(e){if("spell"!==e?.type||!this.showUnpreparedSpells)return null;const t=e.system.level,s=e.system.preparation.mode,i=e.system.preparation.prepared,n=i?r:`${r} tah-icon-disabled`,a="always"===s?game.i18n.localize("DND5E.SpellPrepAlways"):i?game.i18n.localize("DND5E.SpellPrepared"):game.i18n.localize("DND5E.SpellUnprepared");return"prepared"!==s&&"always"!==s||0===t?null:``}async#C(e){if("none"===this.tooltipsSetting)return"";const t=e?.name??"";if("nameOnly"===this.tooltipsSetting)return t;const s=!1===e.system?.identified,i="string"==typeof e?.system?.description?e?.system?.description:(s?e?.system?.unidentified?.description:e?.system?.description?.value)??"";let n,a,o,l;return s||(n=e?.modifiers??null,a=[...e.system?.chatProperties??[],...e.system?.equippableItemCardProperties??[],e.system?.parent?.labels?.activation,e.system?.parent?.labels?.target,e.system?.parent?.labels?.range,e.system?.parent?.labels?.duration].filter((e=>e)),o=s?null:e?.rarity??null,l="weapon"===e?.type?this.#x(e?.system?.properties):null),{name:t,description:i,modifiers:n,properties:a,rarity:o,traits:l}}async#A(e,t){if("none"===this.tooltipsSetting)return"";const s=CONFIG.DND5E.conditionTypes[e];if("nameOnly"===this.tooltipsSetting||!s)return t;const i=s.reference?await fromUuid(s.reference):null;return{name:t,description:i?.text?.content??"",relativeTo:i}}async#k(e){if("none"===this.tooltipsSetting)return"";if("string"==typeof e)return e;const t=game.i18n.localize(e.name);if("nameOnly"===this.tooltipsSetting)return t;const s=`

${t}

`,i=e.relativeTo??this.actor,n=e?.descriptionLocalised??await TextEditor.enrichHTML(game.i18n.localize(e?.description??""),{async:!0,relativeTo:i,secrets:!0}),a=e?.rarity?`${game.i18n.localize(p[e.rarity])}`:"",o=e?.properties?`
${e.properties.map((e=>`${game.i18n.localize(e)}`)).join("")}
`:"",l=e?.traits?e.traits.map((e=>`${game.i18n.localize(e.label??e)}`)).join(""):"",c=e?.traits2?e.traits2.map((e=>`${game.i18n.localize(e.label??e)}`)).join(""):"",r=e?.traitsAlt?e.traitsAlt.map((e=>`${game.i18n.localize(e.label)}`)).join(""):"",d=e?.modifiers?`
${e.modifiers.filter((e=>e.enabled)).map((e=>`${game.i18n.localize(e.label)} ${`${e.modifier>=0?"+":""}${e.modifier??""}`}`)).join("")}
`:"",u=[a,l,c,r].join(""),m=u?`
${u}
`:"";return n||m||d?`
${s}${m||d?`
${m}${d}
`:""}${n}${o}
`:t}#x(e){return e?Object.entries(e).filter((([e,t])=>t&&CONFIG.DND5E.validProperties.weapon.has(e))).map((([e,t])=>game.i18n.localize(CONFIG.DND5E.itemProperties[e]))):null}}}));let g=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{g=class MagicItemActionHandlerExtender extends e.api.ActionHandlerExtender{constructor(e){super(),this.actionHandler=e,this.actor=null}async extendActionHandler(){if(this.actor=this.actionHandler.actor,!this.actor)return;const t=await 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,a=i.name,o=e.api.Utils.getImage(i),l=i.consumption,c=i.baseLevel?`${e.api.Utils.i18n("DND5E.AbbreviationLevel")} ${i.baseLevel}`:"";return{id:n,name:a,encodedValue:encodedValue,img:o,info1:l,info2:c,selected:!0,system:{actionType:"magicItem",itemId:t.id,effectId:n}}}));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 f=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{f=class RollHandler extends e.api.RollHandler{async handleActionClick(t){const{actionType:s,actionId:i}=this.action.system;if(this.actor)await this.handleAction(t,s,this.actor,this.token,i);else for(const n of e.api.Utils.getControlledTokens()){const e=n.actor;await this.handleAction(t,s,e,n,i)}}async handleAction(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(s,i,n);break;case"counter":await this.modifyCounter(e,s);break;case"effect":await this.toggleEffect(s,n);break;case"exhaustion":await this.modifyExhaustion(e,s);break;case"feature":case"item":case"spell":case"weapon":this.isRenderItem()?this.renderItem(s,n):this.useItem(e,s,n);break;case"magicItem":await this.rollMagicItem(s,n);break;case"skill":this.rollSkill(e,s,n);break;case"utility":await this.performUtilityAction(e,s,i,n)}}async modifyCounter(e,t){switch(this.action?.system?.counterKey){case"death-saves":this.rollDeathSave(e,t);break;case"exhaustion":await this.modifyExhaustion(t);break;case"inspiration":await this.modifyInspiration(t);break;default:await this.modifyCustomCounter(t)}}async modifyExhaustion(e){const t=e.system.attributes.exhaustion,s=t+(this.isRightClick?-1:1);s>=0&&s!==t&&e.update({"system.attributes.exhaustion":s})}async modifyInspiration(e){const t=!e.system.attributes.inspiration;e.update({"system.attributes.inspiration":t})}async modifyCustomCounter(e){const{counterKey:t,counterType:s}=this.action.system;let i=e.getFlag(o.ID,t)||{};const setFlag=async(t,s,i)=>{i!==s&&await e.setFlag(o.ID,t,i)},adjustValue=(e,t=0,s=1)=>{const i=this.isRightClick?Math.max(0,t-s):t+s;setFlag(e,t,i)};switch(s){case"checkbox":await setFlag(id,!i);break;case"fraction":(this.isRightClick||i.max&&i.value0)}async performUtilityAction(e,t,s,i){switch(i){case"deathSave":this.rollDeathSave(e,t);break;case"endTurn":if(!s||game.combat?.current?.tokenId!==s.id)break;await(game.combat?.nextTurn());break;case"initiative":await this.rollInitiative(t);break;case"inspiration":await this.modifyInspiration(t);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){if(!t)return;const i=CONFIG.statusEffects.find((e=>e.id===s)),n=i?.flags?.["dfreds-convenient-effects"]?.isConvenient??s.startsWith("Convenient Effect");if(game.dfreds&&n){const e=i.name??i.label;await game.dfreds.effectInterface.toggleEffect(e,{overlay:!!this.isRightClick})}else{const t=this.#F(s);if(!t)return;const i=this.#q(e,s);i?.disabled&&await i.delete(),await e.toggleStatusEffect(t.id,{overlay:!!this.isRightClick})}Hooks.callAll("forceUpdateTokenActionHud")}#F(e){return CONFIG.statusEffects.find((t=>t.id===e))}#q(e,t){return e.effects.find((e=>e.statuses.every((e=>e===t))))}async toggleEffect(e,t){const s=e.allApplicableEffects().find((e=>e.id===t));s&&(this.isRightClick&&!s.transfer?await s.delete():await s.update({disabled:!s.disabled}),Hooks.callAll("forceUpdateTokenActionHud"))}async handleActionHover(t){const{actionType:s,actionId:i}=this.action.system;if(!["feature","item","spell","weapon","magicItem"].includes(s))return;const n=e.api.Utils.getItem(this.actor,i);this.isHover?Hooks.call("tokenActionHudSystemActionHoverOn",t,n):Hooks.call("tokenActionHudSystemActionHoverOff",t,n)}}}));let v=null;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,"showUnequippedItemsNpcs",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.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:!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)}})}Hooks.once("tokenActionHudCoreApiReady",(async e=>{const t=c;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);v={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("TYPES.Item.spellPl"),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"},{...t.conditions,nestId:"effects_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 b=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{b=class SystemManager extends e.api.SystemManager{getActionHandler(){const t=new y;return(e.api.Utils.isModuleActive("magic-items-2")||e.api.Utils.isModuleActive("magicitems"))&&t.addActionHandlerExtender(new g(t)),t}getAvailableRollHandlers(){let t="Core D&D5e";e.api.Utils.isModuleActive("midi-qol")&&(t+=` [supports ${e.api.Utils.getModuleTitle("midi-qol")}]`);return{core:t}}getRollHandler(e){let t;return t=new f,t}registerSettings(e){register(e)}async registerDefaults(){const t=v;if(game.modules.get("magicitems")?.active||game.modules.get("magic-items-2")?.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:"2.0",SystemManager:b},Hooks.call("tokenActionHudSystemReady",t)}));export{i as ACTION_TYPE,n as ACTIVATION_TYPE,y as ActionHandler,a as CONCENTRATION_ICON,t as CORE_MODULE,o as CUSTOM_DND5E,v as DEFAULTS,l as FEATURE_GROUP_IDS,c as GROUP,e as MODULE,g as MagicItemActionHandlerExtender,r as PREPARED_ICON,d as PROFICIENCY_LEVEL_ICON,p as RARITY,s as REQUIRED_CORE_MODULE_VERSION,u as RITUAL_ICON,f as RollHandler,m as SPELL_GROUP_IDS,b as SystemManager,h as Utils,register}; +const e={ID:"token-action-hud-dnd5e"},t={ID:"token-action-hud-core"},s="2.0",i={ability:"DND5E.Ability",check:"tokenActionHud.dnd5e.check",condition:"tokenActionHud.dnd5e.condition",counter:"tokenActionHud.dnd5e.counter",effect:"DND5E.Effect",exhaustion:"DND5E.Exhaustion",feature:"TYPES.Item.feat",item:"tokenActionHud.dnd5e.item",save:"DND5E.SAVE.Title.one",skill:"tokenActionHud.dnd5e.skill",spell:"TYPES.Item.spell",utility:"DND5E.ActionUtil"},n={action:{group:"actions"},bonus:{group:"bonus-actions",icon:"fas fa-plus"},crew:{group:"crew-actions",icon:"fas fa-users"},day:{icon:"fas fa-hourglass-end"},hour:{icon:"fas fa-hourglass-half"},lair:{group:"lair-actions",icon:"fas fa-home"},minute:{icon:"fas fa-hourglass-start"},legendary:{group:"legendary-actions",icon:"fas fas fa-dragon"},reaction:{group:"reactions",icon:"fas fa-bolt"},reactiondamage:{group:"reactions",icon:"fas fa-bolt"},reactionmanual:{group:"reactions",icon:"fas fa-bolt"},special:{group:"special-actions",icon:"fas fa-star"},other:{group:"other-actions"}},a="systems/dnd5e/icons/svg/statuses/concentrating.svg",o={ID:"custom-dnd5e",COUNTERS:{character:"character-counters",group:"group-counters",npc:"npc-counters"}},l=["activeFeatures","passiveFeatures","backgroundFeatures","classFeatures","feats","monsterFeatures","raceFeatures","artificerInfusions","channelDivinity","defensiveTactics","eldritchInvocations","elementalDisciplines","fightingStyles","huntersPrey","kiAbilities","maneuvers","metamagicOptions","multiattacks","pactBoons","psionicPowers","runes","superiorHuntersDefense"],c={_1stLevelSpells:{id:"1st-level-spells",name:"tokenActionHud.dnd5e.1stLevelSpells",spellMode:1,type:"system"},_2ndLevelSpells:{id:"2nd-level-spells",name:"tokenActionHud.dnd5e.2ndLevelSpells",spellMode:2,type:"system"},_3rdLevelSpells:{id:"3rd-level-spells",name:"tokenActionHud.dnd5e.3rdLevelSpells",spellMode:3,type:"system"},_4thLevelSpells:{id:"4th-level-spells",name:"tokenActionHud.dnd5e.4thLevelSpells",spellMode:4,type:"system"},_5thLevelSpells:{id:"5th-level-spells",name:"tokenActionHud.dnd5e.5thLevelSpells",spellMode:5,type:"system"},_6thLevelSpells:{id:"6th-level-spells",name:"tokenActionHud.dnd5e.6thLevelSpells",spellMode:6,type:"system"},_7thLevelSpells:{id:"7th-level-spells",name:"tokenActionHud.dnd5e.7thLevelSpells",spellMode:7,type:"system"},_8thLevelSpells:{id:"8th-level-spells",name:"tokenActionHud.dnd5e.8thLevelSpells",spellMode:8,type:"system"},_9thLevelSpells:{id:"9th-level-spells",name:"tokenActionHud.dnd5e.9thLevelSpells",spellMode:9,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",spellMode:"atwill",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",spellMode:0,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:"TYPES.Item.consumablePl",type:"system"},containers:{id:"containers",name:"TYPES.Item.containerPl",type:"system"},counters:{id:"counters",name:"tokenActionHud.dnd5e.counters",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:"TYPES.Item.equipmentPl",type:"system"},equipped:{id:"equipped",name:"DND5E.Equipped",type:"system"},exhaustion:{id:"exhaustion",name:"DND5E.Exhaustion",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",spellMode:"innate",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:"TYPES.Item.lootPl",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",spellMode:"pact",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:"TYPES.Item.toolPl",type:"system"},unequipped:{id:"unequipped",name:"DND5E.Unequipped",type:"system"},utility:{id:"utility",name:"tokenActionHud.utility",type:"system"},weapons:{id:"weapons",name:"TYPES.Item.weaponPl",type:"system"}},r="fas fa-sun",d={0:"fa-regular fa-circle",.5:"fa-regular fa-circle-half-stroke",1:"fa-solid fa-circle",2:"fa-regular fa-circle-dot"},p={common:"tokenActionHud.dnd5e.common",uncommon:"tokenActionHud.dnd5e.uncommon",rare:"tokenActionHud.dnd5e.rare",veryRare:"tokenActionHud.dnd5e.veryRare",legendary:"tokenActionHud.dnd5e.legendary",artifact:"tokenActionHud.dnd5e.artifact"},u="fas fa-circle-r",m=["cantrips","_1stLevelSpells","_2ndLevelSpells","_3rdLevelSpells","_4thLevelSpells","_5thLevelSpells","_6thLevelSpells","_7thLevelSpells","_8thLevelSpells","_9thLevelSpells","atWillSpells","innateSpells","pactSpells"];let h=null;Hooks.once("tokenActionHudCoreApiReady",(async t=>{h=class Utils{static capitalize(e){return e.replace(/\w\S*/g,(e=>e.charAt(0).toUpperCase()+e.substring(1).toLowerCase()))}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 y=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{y=class ActionHandler extends e.api.ActionHandler{featureActions=null;inventoryActions=null;spellActions=null;async buildSystemActions(t){this.actors=this.actor?[this.actor]:this.#e(),this.tokens=this.token?[this.token]:this.#t(),this.actor&&(this.items=e.api.Utils.sortItemsByName(this.#s(this.actor.items))),this.abbreviateSkills=h.getSetting("abbreviateSkills"),this.displaySpellInfo=h.getSetting("displaySpellInfo"),this.showItemsWithoutActivationCosts=h.getSetting("showItemsWithoutActivationCosts"),this.showUnchargedItems=h.getSetting("showUnchargedItems"),this.showUnequippedItems=h.getSetting("showUnequippedItems"),"npc"!==this.actor?.type||this.showUnequippedItems||(this.showUnequippedItems=h.getSetting("showUnequippedItemsNpcs")),this.showUnpreparedSpells=h.getSetting("showUnpreparedSpells"),this.activationgroupIds=["actions","bonus-actions","crew-actions","lair-actions","legendary-actions","reactions","other-actions"],"character"===this.actor?.type||"npc"===this.actor?.type?(this.inventorygroupIds=["equipped","consumables","containers","equipment","loot","tools","weapons","unequipped"],await this.#i()):"vehicle"===this.actor?.type?(this.inventorygroupIds=["consumables","equipment","tools","weapons"],await this.#n()):this.actor||await this.#a()}async#i(){await Promise.all([this.#o(),this.#l(),this.#c(),this.#r(),this.#d()]),this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),this.#m(),this.#h(),this.#y(),this.#g(),this.#f()}async#n(){await Promise.all([this.#o(),this.#l(),this.#c(),this.#r()]),this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),this.#f()}async#a(){this.#p("ability","abilities"),this.#p("check","checks"),this.#p("save","saves"),this.#u(),await this.#o(),this.#y(),this.#g(),this.#f()}#p(t,s){const i=this.actor?.system.abilities||CONFIG.DND5E.abilities;if(0===i.length)return;const n=Object.entries(i).filter((e=>0!==i[e[0]].value)).map((([n,a])=>{const o=CONFIG.DND5E.abilities[n].label,l="saves"===s?a?.save:a?.mod;return{id:`${t}-${n}`,name:this.abbreviateSkills?h.capitalize(n):o,icon1:"checks"!==s?this.#v(i[n].proficient):"",info1:this.actor?{text:e.api.Utils.getModifier(l),title:`${game.i18n.localize("DND5E.ActionAbil")}: ${e.api.Utils.getModifier(l)}`}:null,info2:this.actor&&"abilities"===s?{text:`(${e.api.Utils.getModifier(a?.save)})`,title:`${game.i18n.localize("DND5E.SavingThrow")}: ${e.api.Utils.getModifier(a?.save)}`}:null,listName:this.#b(t,o),system:{actionType:t,actionId:n}}}));this.addActions(n,{id:s})}async buildActivations(e){const{groupData:t,actionData:s,actionType:i="item"}=e,a=new Map;for(const[e,t]of s){const s=t.system?.activities?.contents[0]?.activation?.type,i=n[s]?.group??"other";a.has(i)||a.set(i,new Map),a.get(i).set(e,t)}for(const e of Object.values(n)){const s=e.group;if(!a.has(s))continue;const n={...t,id:`${s}+${t.id}`,type:"system-derived"};["equipped","unequipped"].includes(t.id)&&(n.defaultSelected=!1);const o={id:s,type:"system"};await this.addGroup(n,o),"spell"===i&&this.addGroupInfo(n),await this.buildActions({groupData:n,actionData:a.get(s),actionType:i})}}#u(){const t={initiative:"tokenActionHud.dnd5e.rollInitiative",...game.combat?.current?.tokenId===this.token?.id&&{endTurn:"tokenActionHud.endTurn"}},s=e.api.Utils.getControlledTokens(),i=s?.map((e=>e.id)),n=game.combat?game.combat.combatants.filter((e=>i.includes(e.tokenId))):[],getInfo1=e=>{if("initiative"===e&&1===n.length){return{class:"tah-spotlight",text:n[0].initiative}}return{}},a="utility",o=Object.entries(t).map((([e,t])=>({id:e,name:game.i18n.localize(t),info1:getInfo1(e),cssClass:"initiative"===e?"toggle"+(n.length>0&&n.every((e=>e?.initiative))?" active":""):"",listName:this.#b(a,t),system:{actionType:a,actionId:e}})));this.addActions(o,{id:"combat"})}async#o(){if(0===this.tokens?.length)return;const t=CONFIG.statusEffects.filter((e=>""!==e.id));if(0===t.length)return;const s="condition",i=await Promise.all(t.map((async t=>{const i=this.actors.every((e=>e.effects.some((e=>e.statuses.some((e=>e===t.id))&&!e?.disabled)))),n=game.i18n.localize(t.label)??t.name;return{id:t.id,name:n,img:e.api.Utils.getImage(t),cssClass:"toggle"+(i?" active":""),listName:this.#b(s,n),tooltip:await this.#k(await this.#A(t.id,t.name)),system:{actionType:s,actionId:t.id}}})));this.addActions(i,{id:"conditions"})}async#m(){if(!e.api.Utils.isModuleActive(o.ID)||!o.COUNTERS[this.actor?.type])return;const t="counter";let s=game.settings.get(o.ID,o.COUNTERS[this.actor?.type])??{};s=e.api.Utils.isModuleActive(o.ID)&&Object.keys(s).length?Object.entries(s).filter((([e,t])=>t.visible)).map((([e,t])=>(t.key=e,t))):[{name:game.i18n.localize("DND5E.DeathSave"),type:"successFailure",system:!0,visible:!0,key:"death-saves"},{name:game.i18n.localize("DND5E.Exhaustion"),type:"number",system:!0,visible:!0,key:"exhaustion"},{name:game.i18n.localize("DND5E.Inspiration"),type:"checkbox",system:!0,visible:!0,key:"inspiration"}];const i=s.map((s=>{let i="",n="",a="",l="";if(s.system)switch(s.key){case"exhaustion":i=this.actor.system.attributes.exhaustion>0?" active":"",n=`toggle${i}`,a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/exhaustion.svg"),l={text:this.actor.system.attributes.exhaustion};break;case"death-saves":a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/death-saves.svg"),l={text:`${this.actor.system.attributes.death.success}/${this.actor.system.attributes.death.failure}`};break;case"inspiration":i=this.actor.system.attributes.inspiration?" active":"",n=`toggle${i}`,a=e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/inspiration.svg")}else{const e=this.actor.getFlag(o.ID,s.key);switch(s.type){case"checkbox":i=e?" active":"",n=`toggle${i}`;break;case"fraction":i=e.value>0?" active":"",n=`toggle${i}`,l={text:`${e.value??0}/${e.max??0}`};break;case"number":i=e>0?" active":"",n=`toggle${i}`,l={text:e};break;case"successFailure":l={text:`${e?.success??0}/${e?.failure??0}`}}}return{id:s.key,name:s.label,listName:this.#b(t,s.name),cssClass:n,img:a,info1:l,system:{actionType:t,counterKey:s.key,counterType:s.type}}}));this.addActions(i,{id:"counters"})}async#l(){const e="effect",t=new Map(this.actor.allApplicableEffects().map((e=>[e.id,e])));if(0===t.size)return;const s=new Map,i=new Map,n=new Set(CONFIG.statusEffects.map((e=>e._id)));for(const[e,a]of t.entries())a.isSuppressed||(!1!==a.parent?.system?.identified||game.user.isGM)&&(n.has(a.id)||(a.isTemporary?i.set(e,a):s.set(e,a)));await Promise.all([this.buildActions({groupData:{id:"passive-effects"},actionData:s,actionType:e}),this.buildActions({groupData:{id:"temporary-effects"},actionData:i,actionType:e})])}#h(){if(!this.actors.every((e=>"character"===e.type)))return;const t="exhaustion",s=this.actor.system.attributes.exhaustion>0?" active":"",i=[{id:"exhaustion",name:game.i18n.localize("DND5E.Exhaustion"),cssClass:`toggle${s}`,img:e.api.Utils.getImage("modules/token-action-hud-dnd5e/icons/exhaustion.svg"),info1:{text:this.actor.system.attributes.exhaustion},listName:this.#b(t,name),system:{actionType:t,actionId:"exhaustion"}}];this.addActions(i,{id:"exhaustion"})}async#c(){const e=new Map([...this.items].filter((([,e])=>"feat"===e.type)));if(0===e.size)return;const t=new Map([["activeFeatures",new Map],["passiveFeatures",new Map]]),s={background:"backgroundFeatures",class:"classFeatures",monster:"monsterFeatures",race:"raceFeatures",feats:"feats"},i={artificerInfusion:"artificerInfusions",channelDivinity:"channelDivinity",defensiveTactic:"defensiveTactics",eldritchInvocation:"eldritchInvocations",elementalDiscipline:"elementalDisciplines",fightingStyle:"fightingStyles",huntersPrey:"huntersPrey",ki:"kiAbilities",maneuver:"maneuvers",metamagic:"metamagicOptions",multiattack:"multiattacks",pact:"pactBoons",psionicPower:"psionicPowers",rune:"runes",superiorHuntersDefense:"superiorHuntersDefense"};for(const[n,a]of e){const e=a.system.activities.contents[0]?.type,o=a.system.type.value,l=a.system.type?.subtype;e?t.get("activeFeatures").set(n,a):t.get("passiveFeatures").set(n,a),s[o]&&(t.has(s[o])||t.set(s[o],new Map),t.get(s[o]).set(n,a)),i[l]&&(t.has(i[l])||t.set(i[l],new Map),t.get(i[l]).set(n,a))}for(const e of l){const s=t.get(e);if(!s||0===s.size)continue;const i={id:c[e].id,name:game.i18n.localize(c[e].name)??""},n="feature";await this.buildActions({groupData:i,actionData:s,actionType:n}),await this.buildActivations({groupData:i,actionData:s,actionType:n})}}async#r(){if(0===this.items.size)return;const e=new Map([["equipped",new Map],["unequipped",new Map],["consumables",new Map],["containers",new Map],["equipment",new Map],["loot",new Map],["tools",new Map],["weapons",new Map]]);for(const[t,s]of this.items)if(s.system?.quantity>0&&this.#I(s)&&(s.system.equipped?e.get("equipped").set(t,s):e.get("unequipped").set(t,s),this.#w(s)&&"consumable"===s.type&&e.get("consumables").set(t,s),this.#S(s)))switch(s.type){case"container":e.get("containers").set(t,s);break;case"equipment":e.get("equipment").set(t,s);break;case"loot":e.get("loot").set(t,s);break;case"tool":e.get("tools").set(t,s);break;case"weapon":e.get("weapons").set(t,s)}for(const t of this.inventorygroupIds){const s=e.get(t);if(!s||0===s.size)continue;const i={groupData:{id:t,name:game.i18n.localize(c[t].name)},actionData:s};await this.buildActions(i),await this.buildActivations(i)}}#y(){if(0===this.actors.length||!this.actors.every((e=>"character"===e.type)))return;const e="utility",t=Object.entries({shortRest:"DND5E.ShortRest",longRest:"DND5E.LongRest"}).map((([t,s])=>({id:t,name:s=game.i18n.localize(s),listName:this.#b(e,s),system:{actionType:e,actionId:t}})));this.addActions(t,{id:"rests"})}#g(){const t=this.actor?.system.skills||CONFIG.DND5E.skills;if(0===t.length)return;const s="skill",i=Object.entries(t).map((([t,i])=>{try{const n=CONFIG.DND5E.skills[t].label;return{id:t,name:this.abbreviateSkills?h.capitalize(t):n,icon1:this.#v(i.value),info1:this.actor?{text:e.api.Utils.getModifier(i.total)}:"",listName:this.#b(s,n),system:{actionType:s,actionId:t}}}catch(t){return e.api.Logger.error(i),null}})).filter((e=>!!e));this.addActions(i,{id:"skills"})}async#d(){const e=new Map([...this.items].filter((([,e])=>"spell"===e.type)));if(0===e.size)return;const t=new Map([["atWillSpells",new Map],["innateSpells",new Map],["pactSpells",new Map],["cantrips",new Map],["_1stLevelSpells",new Map],["_2ndLevelSpells",new Map],["_3rdLevelSpells",new Map],["_4thLevelSpells",new Map],["_5thLevelSpells",new Map],["_6thLevelSpells",new Map],["_7thLevelSpells",new Map],["_8thLevelSpells",new Map],["_9thLevelSpells",new Map]]);for(const[s,i]of e)if(this.#w(i)&&this.#D(i))switch(i.system.preparation.mode){case"atwill":t.get("atWillSpells").set(s,i);break;case"innate":t.get("innateSpells").set(s,i);break;case"pact":t.get("pactSpells").set(s,i);break;default:switch(i.system.level){case 0:t.get("cantrips").set(s,i);break;case 1:t.get("_1stLevelSpells").set(s,i);break;case 2:t.get("_2ndLevelSpells").set(s,i);break;case 3:t.get("_3rdLevelSpells").set(s,i);break;case 4:t.get("_4thLevelSpells").set(s,i);break;case 5:t.get("_5thLevelSpells").set(s,i);break;case 6:t.get("_6thLevelSpells").set(s,i);break;case 7:t.get("_7thLevelSpells").set(s,i);break;case 8:t.get("_8thLevelSpells").set(s,i);break;case 9:t.get("_9thLevelSpells").set(s,i)}}const s=Object.entries(this.actor.system.spells).reverse(),i=new Map;let n=this.showUnchargedItems,a=this.showUnchargedItems,o=null;for(const[e,t]of s){const s=t.value>0,l=t.max>0,c=t.level>0;"pact"===e?(a=a||s&&l&&c,t.slotAvailable=a&&c,o=[e,t]):e.startsWith("spell")&&"spell0"!==e?(n=n||s&&l,t.slotAvailable=n,i.set(e,t)):s&&(t.slotsAvailable=!0,i.set(e,t))}if(o[1].slotAvailable){i.get(`spell${o[1].level}`).slotsAvailable=!0}const l=new Set([1,2,3,4,5,6,7,8,9,"pact"]);for(const e of m){if(!t.has(e))continue;const s=c[e].spellMode,n="pact"===s?o[1]:i.get(`spell${s}`),{value:a=0,max:r=0,slotAvailable:d=!1}=n||{};if(!d&&l.has(s))continue;const p={id:c[e].id,name:game.i18n.localize(c[e].name),info:{info1:{class:"tah-spotlight",text:r>0?`${a}/${r}`:""}}};this.addGroupInfo(p);const u={groupData:p,actionData:t.get(e),actionType:"spell"};await this.buildActions(u),await this.buildActivations(u)}}#f(){if(0===this.actors.length)return;if(!this.actors.every((e=>"character"===e.type)))return;const e="utility",t={deathSave:{name:game.i18n.localize("DND5E.DeathSave")},inspiration:{name:game.i18n.localize("DND5E.Inspiration")}};(!this.actor||this.actor.system.attributes.hp.value>0)&&delete t.deathSave;const s=Object.entries(t).map((t=>{const s=t[0],i=t[1].name;let n="";if("inspiration"===t[0]){n=`toggle${this.actors.every((e=>e.system.attributes?.inspiration))?" active":""}`}return{id:s,name:i,cssClass:n,listName:this.#b(e,i),system:{actionType:e,actionId:s}}}));this.addActions(s,{id:"utility"})}async buildActions(e,t){const{actionData:s,groupData:i,actionType:n}=e;if(0===s.size)return;if(!("string"==typeof i?i:i?.id))return;const a=await Promise.all([...s].map((async e=>await this.#H(e[1],n))));this.addActions(a,i)}async#H(t,s="item"){const i=t.id??t._id;let n=t?.name??t?.label,a="";if(Object.hasOwn(t,"disabled")){a=`toggle${t.disabled?"":" active"}`}const o=this.#E(t),l=await this.#k(await this.#C(t));return{id:i,name:n,cssClass:a,img:e.api.Utils.getImage(t),icon1:this.#N(t.system?.activities?.contents[0]?.activation.type),icon2:this.#$(t),icon3:this.#U(t),info1:o?.info1,info2:o?.info2,info3:o?.info3,listName:this.#b(s,n),tooltip:l,system:{actionType:s,actionId:i}}}#I(e){if(this.showItemsWithoutActivationCosts)return!0;const t=new Set(Object.keys(CONFIG.DND5E.activityActivationTypes).filter((e=>"none"!==e))),s=e.system?.activities?.contents[0]?.activation?.type;return t.has(s)||"tool"===e.type}#S(e){return this.showUnequippedItems&&!["consumable","spell","feat"].includes(e.type)||e.system.equipped&&"consumable"!==e.type}#w(e){return this.showUnchargedItems||!!e.system.uses?.value||!e.system.uses?.max}#D(e){if("character"!==this.actor?.type&&this.showUnequippedItems)return!0;if(this.showUnpreparedSpells)return!0;return new Set(Object.keys(CONFIG.DND5E.spellPreparationModes).filter((e=>"prepared"!==e))).has(e.system.preparation.mode)||e.system.preparation.prepared}#b(e,t){return`${`${game.i18n.localize(i[e])}: `??""}${t}`??""}#E(e){return{info1:"spell"===e.type?this.#_(e):this.#T(e),info2:this.#M(e),info3:this.#L(e)}}#_(e){if(!this.displaySpellInfo)return null;const t=e.system?.properties;if(!t)return null;const s={text:"",title:""},i=Object.entries({vocal:"DND5E.ComponentVerbal",somatic:"DND5E.ComponentSomatic",material:"DND5E.ComponentMaterial"}).filter((([e])=>t[e])).map((([e,t])=>(s.text+=game.i18n.localize(`${t}Abbr`),game.i18n.localize(t))));return t.ritual&&(i.push(`[${game.i18n.localize("DND5E.Ritual")}]`),s.text+=` [${game.i18n.localize("DND5E.RitualAbbr")}]`),s.title=i.join(", "),s}#e(){const e=["character","npc"];return this.actors.every((t=>e.includes(t.type)))?this.actors:[]}#t(){const e=["character","npc"];return this.actors.every((t=>e.includes(t.type)))?this.tokens:[]}#T(e){const t=e?.system?.quantity??0;return{text:t>1?t:"",title:`${game.i18n.localize("DND5E.Quantity")}: ${t}`}}#M(e){const t=e?.system?.uses;if(!(t?.max>0))return{};const s="charges"===t.recovery[0]?.period?"":` ${game.i18n.localize("DND5E.per")} `,i=CONFIG.DND5E.limitedUsePeriods[t.recovery[0]?.period]?.label??t.recovery[0]?.period,n=i?`${s}${i}`:"",a=`${t.max-(t.spent??0)}/${t.max}`;return{text:a,title:`${a}${n}`}}#L(e){const t=e?.system?.activities?.contents[0],s=t?.consumption?.targets?.[0],i=s?.target,n=s?.type,a=s?.value;if(!i||!n||i===e.id)return{};if("attribute"===n){const e=i.substr(0,i.lastIndexOf(".")),t=foundry.utils.getProperty(this.actor.system,e);if(t){const e=`${t.value??"0"}${t.max?`/${t.max}`:""}`;return{text:e,title:`${e} ${t.label??""}`}}}else{const e=this.actor.items?.get(i);if(e&&"charges"===n)return this.#M(e);if(e?.system?.quantity){const t=`${a>1?`${a} ${game.i18n.localize("DND5E.of")} `:""}${e.system.quantity}`;return{text:t,title:`${t} ${e.name}`}}}return{}}#s(e){if(h.getSetting("showSlowActions"))return e;const t=new Set(["minute","hour","day"]);return new Map([...e.entries()].filter((([e,s])=>{const i=s.system?.activation?.type;return!t.has(i)})))}#v(e){const t=CONFIG.DND5E.proficiencyLevels[e]??"",s=d[e];return s?``:""}#N(e){const t=CONFIG.DND5E.abilityActivationTypes[e]??"",s=n[e]?.icon;return s?``:""}#U(e){if("spell"!==e?.type||!this.displaySpellInfo||!e.system?.properties?.has("concentration"))return null;const t=game.i18n.localize("DND5E.Scroll.RequiresConcentration");return``}#$(e){if("spell"!==e?.type||!this.showUnpreparedSpells)return null;const t=e.system.level,s=e.system.preparation.mode,i=e.system.preparation.prepared,n=i?r:`${r} tah-icon-disabled`,a="always"===s?game.i18n.localize("DND5E.SpellPrepAlways"):i?game.i18n.localize("DND5E.SpellPrepared"):game.i18n.localize("DND5E.SpellUnprepared");return"prepared"!==s&&"always"!==s||0===t?null:``}async#C(e){if("none"===this.tooltipsSetting)return"";const t=e?.name??"";if("nameOnly"===this.tooltipsSetting)return t;const s=!1===e.system?.identified,i="string"==typeof e?.system?.description?e?.system?.description:(s?e?.system?.unidentified?.description:e?.system?.description?.value)??"";let n,a,o,l;return s||(n=e?.modifiers??null,a=[...e.system?.chatProperties??[],...e.system?.equippableItemCardProperties??[],e.system?.parent?.labels?.activation,e.system?.parent?.labels?.target,e.system?.parent?.labels?.range,e.system?.parent?.labels?.duration].filter((e=>e)),o=s?null:e?.rarity??null,l="weapon"===e?.type?this.#x(e?.system?.properties):null),{name:t,description:i,modifiers:n,properties:a,rarity:o,traits:l}}async#A(e,t){if("none"===this.tooltipsSetting)return"";const s=CONFIG.DND5E.conditionTypes[e];if("nameOnly"===this.tooltipsSetting||!s)return t;const i=s.reference?await fromUuid(s.reference):null;return{name:t,description:i?.text?.content??"",relativeTo:i}}async#k(e){if("none"===this.tooltipsSetting)return"";if("string"==typeof e)return e;const t=game.i18n.localize(e.name);if("nameOnly"===this.tooltipsSetting)return t;const s=`

${t}

`,i=e.relativeTo??this.actor,n=e?.descriptionLocalised??await TextEditor.enrichHTML(game.i18n.localize(e?.description??""),{async:!0,relativeTo:i,secrets:!0}),a=e?.rarity?`${game.i18n.localize(p[e.rarity])}`:"",o=e?.properties?`
${e.properties.map((e=>`${game.i18n.localize(e)}`)).join("")}
`:"",l=e?.traits?e.traits.map((e=>`${game.i18n.localize(e.label??e)}`)).join(""):"",c=e?.traits2?e.traits2.map((e=>`${game.i18n.localize(e.label??e)}`)).join(""):"",r=e?.traitsAlt?e.traitsAlt.map((e=>`${game.i18n.localize(e.label)}`)).join(""):"",d=e?.modifiers?`
${e.modifiers.filter((e=>e.enabled)).map((e=>`${game.i18n.localize(e.label)} ${`${e.modifier>=0?"+":""}${e.modifier??""}`}`)).join("")}
`:"",u=[a,l,c,r].join(""),m=u?`
${u}
`:"";return n||m||d?`
${s}${m||d?`
${m}${d}
`:""}${n}${o}
`:t}#x(e){return e?Object.entries(e).filter((([e,t])=>t&&CONFIG.DND5E.validProperties.weapon.has(e))).map((([e,t])=>game.i18n.localize(CONFIG.DND5E.itemProperties[e]))):null}}}));let g=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{g=class MagicItemActionHandlerExtender extends e.api.ActionHandlerExtender{constructor(e){super(),this.actionHandler=e,this.actor=null}async extendActionHandler(){if(this.actor=this.actionHandler.actor,!this.actor)return;const t=await 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,a=i.name,o=e.api.Utils.getImage(i),l=i.consumption,c=i.baseLevel?`${e.api.Utils.i18n("DND5E.AbbreviationLevel")} ${i.baseLevel}`:"";return{id:n,name:a,encodedValue:encodedValue,img:o,info1:l,info2:c,selected:!0,system:{actionType:"magicItem",itemId:t.id,effectId:n}}}));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 f=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{f=class RollHandler extends e.api.RollHandler{async handleActionClick(t){const{actionType:s,actionId:i}=this.action.system;if(this.actor)await this.handleAction(t,s,this.actor,this.token,i);else for(const n of e.api.Utils.getControlledTokens()){const e=n.actor;await this.handleAction(t,s,e,n,i)}}async handleAction(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(s,i,n);break;case"counter":await this.modifyCounter(e,s);break;case"effect":await this.toggleEffect(s,n);break;case"exhaustion":await this.modifyExhaustion(e,s);break;case"feature":case"item":case"spell":case"weapon":this.isRenderItem()?this.renderItem(s,n):this.useItem(e,s,n);break;case"magicItem":await this.rollMagicItem(s,n);break;case"skill":this.rollSkill(e,s,n);break;case"utility":await this.performUtilityAction(e,s,i,n)}}async modifyCounter(e,t){switch(this.action?.system?.counterKey){case"death-saves":this.rollDeathSave(e,t);break;case"exhaustion":await this.modifyExhaustion(t);break;case"inspiration":await this.modifyInspiration(t);break;default:await this.modifyCustomCounter(t)}}async modifyExhaustion(e){const t=e.system.attributes.exhaustion,s=t+(this.isRightClick?-1:1);s>=0&&s!==t&&e.update({"system.attributes.exhaustion":s})}async modifyInspiration(e){const t=!e.system.attributes.inspiration;e.update({"system.attributes.inspiration":t})}async modifyCustomCounter(e){const{counterKey:t,counterType:s}=this.action.system;let i=e.getFlag(o.ID,t)||{};const setFlag=async(t,s,i)=>{i!==s&&await e.setFlag(o.ID,t,i)},adjustValue=(e,t=0,s=1)=>{const i=this.isRightClick?Math.max(0,t-s):t+s;setFlag(e,t,i)};switch(s){case"checkbox":await setFlag(id,!i);break;case"fraction":(this.isRightClick||i.max&&i.value0)}async performUtilityAction(e,t,s,i){switch(i){case"deathSave":this.rollDeathSave(e,t);break;case"endTurn":if(!s||game.combat?.current?.tokenId!==s.id)break;await(game.combat?.nextTurn());break;case"initiative":await this.rollInitiative(t);break;case"inspiration":await this.modifyInspiration(t);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){if(!t)return;const i=CONFIG.statusEffects.find((e=>e.id===s)),n=i?.flags?.["dfreds-convenient-effects"]?.isConvenient??s.startsWith("Convenient Effect");if(game.dfreds&&n){const e=i.name??i.label;await game.dfreds.effectInterface.toggleEffect(e,{overlay:!!this.isRightClick})}else{const t=this.#F(s);if(!t)return;const i=this.#q(e,s);i?.disabled&&await i.delete(),await e.toggleStatusEffect(t.id,{overlay:!!this.isRightClick})}Hooks.callAll("forceUpdateTokenActionHud")}#F(e){return CONFIG.statusEffects.find((t=>t.id===e))}#q(e,t){return e.effects.find((e=>e.statuses.every((e=>e===t))))}async toggleEffect(e,t){const s=e.allApplicableEffects().find((e=>e.id===t));s&&(this.isRightClick&&!s.transfer?await s.delete():await s.update({disabled:!s.disabled}),Hooks.callAll("forceUpdateTokenActionHud"))}async handleActionHover(t){const{actionType:s,actionId:i}=this.action.system;if(!["feature","item","spell","weapon","magicItem"].includes(s))return;const n=e.api.Utils.getItem(this.actor,i);this.isHover?Hooks.call("tokenActionHudSystemActionHoverOn",t,n):Hooks.call("tokenActionHudSystemActionHoverOff",t,n)}}}));let v=null;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,"showUnequippedItemsNpcs",{name:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.name"),hint:game.i18n.localize("tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.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:!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)}})}Hooks.once("tokenActionHudCoreApiReady",(async e=>{const t=c;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);v={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("TYPES.Item.spellPl"),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"},{...t.conditions,nestId:"effects_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 b=null;Hooks.once("tokenActionHudCoreApiReady",(async e=>{b=class SystemManager extends e.api.SystemManager{getActionHandler(){const t=new y;return(e.api.Utils.isModuleActive("magic-items-2")||e.api.Utils.isModuleActive("magicitems"))&&t.addActionHandlerExtender(new g(t)),t}getAvailableRollHandlers(){let t="Core D&D5e";e.api.Utils.isModuleActive("midi-qol")&&(t+=` [supports ${e.api.Utils.getModuleTitle("midi-qol")}]`);return{core:t}}getRollHandler(e){let t;return t=new f,t}registerSettings(e){register(e)}async registerDefaults(){const t=v;if(game.modules.get("magicitems")?.active||game.modules.get("magic-items-2")?.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:"2.0",SystemManager:b},Hooks.call("tokenActionHudSystemReady",t)}));export{i as ACTION_TYPE,n as ACTIVATION_TYPE,y as ActionHandler,a as CONCENTRATION_ICON,t as CORE_MODULE,o as CUSTOM_DND5E,v as DEFAULTS,l as FEATURE_GROUP_IDS,c as GROUP,e as MODULE,g as MagicItemActionHandlerExtender,r as PREPARED_ICON,d as PROFICIENCY_LEVEL_ICON,p as RARITY,s as REQUIRED_CORE_MODULE_VERSION,u as RITUAL_ICON,f as RollHandler,m as SPELL_GROUP_IDS,b as SystemManager,h as Utils,register}; //# sourceMappingURL=token-action-hud-dnd5e.min.js.map diff --git a/scripts/token-action-hud-dnd5e.min.js.map b/scripts/token-action-hud-dnd5e.min.js.map index af25db0..1e531b2 100644 --- a/scripts/token-action-hud-dnd5e.min.js.map +++ b/scripts/token-action-hud-dnd5e.min.js.map @@ -1 +1 @@ -{"version":3,"file":"token-action-hud-dnd5e.min.js","sources":["constants.js","utils.js","action-handler.js","magic-items-extender.js","roll-handler.js","defaults.js","settings.js","system-manager.js","init.js"],"sourcesContent":["/**\r\n * Module-based constants\r\n */\r\nexport const MODULE = {\r\n ID: \"token-action-hud-dnd5e\"\r\n};\r\n\r\n/**\r\n * Core module\r\n */\r\nexport const CORE_MODULE = {\r\n ID: \"token-action-hud-core\"\r\n};\r\n\r\n/**\r\n * Core module version required by the system module\r\n */\r\nexport const REQUIRED_CORE_MODULE_VERSION = \"2.0\";\r\n\r\n/**\r\n * Action type\r\n */\r\nexport const ACTION_TYPE = {\r\n ability: \"DND5E.Ability\",\r\n check: \"tokenActionHud.dnd5e.check\",\r\n condition: \"tokenActionHud.dnd5e.condition\",\r\n counter: \"tokenActionHud.dnd5e.counter\",\r\n effect: \"DND5E.Effect\",\r\n exhaustion: \"DND5E.Exhaustion\",\r\n feature: \"TYPES.Item.feat\",\r\n item: \"tokenActionHud.dnd5e.item\",\r\n save: \"DND5E.SAVE.Title.one\",\r\n skill: \"tokenActionHud.dnd5e.skill\",\r\n spell: \"TYPES.Item.spell\",\r\n utility: \"DND5E.ActionUtil\"\r\n};\r\n\r\n/**\r\n * Activation types\r\n */\r\nexport const ACTIVATION_TYPE = {\r\n action: { group: \"actions\" },\r\n bonus: { group: \"bonus-actions\", icon: \"fas fa-plus\" },\r\n crew: { group: \"crew-actions\", icon: \"fas fa-users\" },\r\n day: { icon: \"fas fa-hourglass-end\" },\r\n hour: { icon: \"fas fa-hourglass-half\" },\r\n lair: { group: \"lair-actions\", icon: \"fas fa-home\" },\r\n minute: { icon: \"fas fa-hourglass-start\" },\r\n legendary: { group: \"legendary-actions\", icon: \"fas fas fa-dragon\" },\r\n reaction: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n reactiondamage: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n reactionmanual: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n special: { group: \"special-actions\", icon: \"fas fa-star\" },\r\n other: { group: \"other-actions\" }\r\n};\r\n\r\n/**\r\n * Concentration icon\r\n */\r\nexport const CONCENTRATION_ICON = \"systems/dnd5e/icons/svg/statuses/concentrating.svg\";\r\n\r\nexport const CUSTOM_DND5E = {\r\n ID: \"custom-dnd5e\",\r\n COUNTERS: {\r\n character: \"character-counters\",\r\n group: \"group-counters\",\r\n npc: \"npc-counters\"\r\n }\r\n};\r\n\r\n/**\r\n * Feature Group IDs\r\n */\r\nexport const FEATURE_GROUP_IDS = [\r\n \"activeFeatures\",\r\n \"passiveFeatures\",\r\n \"backgroundFeatures\",\r\n \"classFeatures\",\r\n \"feats\",\r\n \"monsterFeatures\",\r\n \"raceFeatures\",\r\n \"artificerInfusions\",\r\n \"channelDivinity\",\r\n \"defensiveTactics\",\r\n \"eldritchInvocations\",\r\n \"elementalDisciplines\",\r\n \"fightingStyles\",\r\n \"huntersPrey\",\r\n \"kiAbilities\",\r\n \"maneuvers\",\r\n \"metamagicOptions\",\r\n \"multiattacks\",\r\n \"pactBoons\",\r\n \"psionicPowers\",\r\n \"runes\",\r\n \"superiorHuntersDefense\"\r\n];\r\n\r\n/**\r\n * Groups\r\n */\r\nexport const GROUP = {\r\n _1stLevelSpells: { id: \"1st-level-spells\", name: \"tokenActionHud.dnd5e.1stLevelSpells\", spellMode: 1, type: \"system\" },\r\n _2ndLevelSpells: { id: \"2nd-level-spells\", name: \"tokenActionHud.dnd5e.2ndLevelSpells\", spellMode: 2, type: \"system\" },\r\n _3rdLevelSpells: { id: \"3rd-level-spells\", name: \"tokenActionHud.dnd5e.3rdLevelSpells\", spellMode: 3, type: \"system\" },\r\n _4thLevelSpells: { id: \"4th-level-spells\", name: \"tokenActionHud.dnd5e.4thLevelSpells\", spellMode: 4, type: \"system\" },\r\n _5thLevelSpells: { id: \"5th-level-spells\", name: \"tokenActionHud.dnd5e.5thLevelSpells\", spellMode: 5, type: \"system\" },\r\n _6thLevelSpells: { id: \"6th-level-spells\", name: \"tokenActionHud.dnd5e.6thLevelSpells\", spellMode: 6, type: \"system\" },\r\n _7thLevelSpells: { id: \"7th-level-spells\", name: \"tokenActionHud.dnd5e.7thLevelSpells\", spellMode: 7, type: \"system\" },\r\n _8thLevelSpells: { id: \"8th-level-spells\", name: \"tokenActionHud.dnd5e.8thLevelSpells\", spellMode: 8, type: \"system\" },\r\n _9thLevelSpells: { id: \"9th-level-spells\", name: \"tokenActionHud.dnd5e.9thLevelSpells\", spellMode: 9, type: \"system\" },\r\n abilities: { id: \"abilities\", name: \"tokenActionHud.dnd5e.abilities\", type: \"system\" },\r\n actions: { id: \"actions\", name: \"DND5E.ActionPl\", type: \"system\" },\r\n activeFeatures: { id: \"active-features\", name: \"tokenActionHud.dnd5e.activeFeatures\", type: \"system\" },\r\n artificerInfusions: { id: \"artificer-infusions\", name: \"tokenActionHud.dnd5e.artificerInfusions\", type: \"system\" },\r\n atWillSpells: { id: \"at-will-spells\", name: \"tokenActionHud.dnd5e.atWillSpells\", spellMode: \"atwill\", type: \"system\" },\r\n backgroundFeatures: { id: \"background-features\", name: \"tokenActionHud.dnd5e.backgroundFeatures\", type: \"system\" },\r\n bonusActions: { id: \"bonus-actions\", name: \"tokenActionHud.dnd5e.bonusActions\", type: \"system\" },\r\n cantrips: { id: \"cantrips\", name: \"tokenActionHud.dnd5e.cantrips\", spellMode: 0, type: \"system\" },\r\n channelDivinity: { id: \"channel-divinity\", name: \"tokenActionHud.dnd5e.channelDivinity\", type: \"system\" },\r\n checks: { id: \"checks\", name: \"tokenActionHud.dnd5e.checks\", type: \"system\" },\r\n classFeatures: { id: \"class-features\", name: \"tokenActionHud.dnd5e.classFeatures\", type: \"system\" },\r\n combat: { id: \"combat\", name: \"tokenActionHud.combat\", type: \"system\" },\r\n conditions: { id: \"conditions\", name: \"tokenActionHud.dnd5e.conditions\", type: \"system\" },\r\n consumables: { id: \"consumables\", name: \"TYPES.Item.consumablePl\", type: \"system\" },\r\n containers: { id: \"containers\", name: \"TYPES.Item.containerPl\", type: \"system\" },\r\n counters: { id: \"counters\", name: \"tokenActionHud.dnd5e.counters\", type: \"system\" },\r\n crewActions: { id: \"crew-actions\", name: \"tokenActionHud.dnd5e.crewActions\", type: \"system\" },\r\n defensiveTactics: { id: \"defensive-tactics\", name: \"tokenActionHud.dnd5e.defensiveTactics\", type: \"system\" },\r\n eldritchInvocations: { id: \"eldritch-invocations\", name: \"tokenActionHud.dnd5e.eldritchInvocations\", type: \"system\" },\r\n elementalDisciplines: { id: \"elemental-disciplines\", name: \"tokenActionHud.dnd5e.elementalDisciplines\", type: \"system\" },\r\n equipment: { id: \"equipment\", name: \"TYPES.Item.equipmentPl\", type: \"system\" },\r\n equipped: { id: \"equipped\", name: \"DND5E.Equipped\", type: \"system\" },\r\n exhaustion: { id: \"exhaustion\", name: \"DND5E.Exhaustion\", type: \"system\" },\r\n feats: { id: \"feats\", name: \"tokenActionHud.dnd5e.feats\", type: \"system\" },\r\n fightingStyles: { id: \"fighting-styles\", name: \"tokenActionHud.dnd5e.fightingStyles\", type: \"system\" },\r\n huntersPrey: { id: \"hunters-prey\", name: \"tokenActionHud.dnd5e.huntersPrey\", type: \"system\" },\r\n innateSpells: { id: \"innate-spells\", name: \"tokenActionHud.dnd5e.innateSpells\", spellMode: \"innate\", type: \"system\" },\r\n kiAbilities: { id: \"ki-abilities\", name: \"tokenActionHud.dnd5e.kiAbilities\", type: \"system\" },\r\n lairActions: { id: \"lair-actions\", name: \"tokenActionHud.dnd5e.lairActions\", type: \"system\" },\r\n legendaryActions: { id: \"legendary-actions\", name: \"tokenActionHud.dnd5e.legendaryActions\", type: \"system\" },\r\n loot: { id: \"loot\", name: \"TYPES.Item.lootPl\", type: \"system\" },\r\n maneuvers: { id: \"maneuvers\", name: \"tokenActionHud.dnd5e.maneuvers\", type: \"system\" },\r\n metamagicOptions: { id: \"metamagic-options\", name: \"tokenActionHud.dnd5e.metamagicOptions\", type: \"system\" },\r\n monsterFeatures: { id: \"monster-features\", name: \"tokenActionHud.dnd5e.monsterFeatures\", type: \"system\" },\r\n multiattacks: { id: \"multiattacks\", name: \"tokenActionHud.dnd5e.multiattacks\", type: \"system\" },\r\n otherActions: { id: \"other-actions\", name: \"tokenActionHud.dnd5e.otherActions\", type: \"system\" },\r\n pactBoons: { id: \"pact-boons\", name: \"tokenActionHud.dnd5e.pactBoons\", type: \"system\" },\r\n pactSpells: { id: \"pact-spells\", name: \"tokenActionHud.dnd5e.pactSpells\", spellMode: \"pact\", type: \"system\" },\r\n passiveEffects: { id: \"passive-effects\", name: \"DND5E.EffectPassive\", type: \"system\" },\r\n passiveFeatures: { id: \"passive-features\", name: \"tokenActionHud.dnd5e.passiveFeatures\", type: \"system\" },\r\n psionicPowers: { id: \"psionic-powers\", name: \"tokenActionHud.dnd5e.psionicPowers\", type: \"system\" },\r\n raceFeatures: { id: \"race-features\", name: \"tokenActionHud.dnd5e.raceFeatures\", type: \"system\" },\r\n reactions: { id: \"reactions\", name: \"DND5E.ReactionPl\", type: \"system\" },\r\n rests: { id: \"rests\", name: \"tokenActionHud.dnd5e.rests\", type: \"system\" },\r\n runes: { id: \"runes\", name: \"tokenActionHud.dnd5e.runes\", type: \"system\" },\r\n saves: { id: \"saves\", name: \"DND5E.ClassSaves\", type: \"system\" },\r\n skills: { id: \"skills\", name: \"tokenActionHud.dnd5e.skills\", type: \"system\" },\r\n superiorHuntersDefense: { id: \"superior-hunters-defense\", name: \"tokenActionHud.dnd5e.superiorHuntersDefense\", type: \"system\" },\r\n temporaryEffects: { id: \"temporary-effects\", name: \"DND5E.EffectTemporary\", type: \"system\" },\r\n token: { id: \"token\", name: \"tokenActionHud.token\", type: \"system\" },\r\n tools: { id: \"tools\", name: \"TYPES.Item.toolPl\", type: \"system\" },\r\n unequipped: { id: \"unequipped\", name: \"DND5E.Unequipped\", type: \"system\" },\r\n utility: { id: \"utility\", name: \"tokenActionHud.utility\", type: \"system\" },\r\n weapons: { id: \"weapons\", name: \"TYPES.Item.weaponPl\", type: \"system\" }\r\n};\r\n\r\n/**\r\n * Prepared icon\r\n */\r\nexport const PREPARED_ICON = \"fas fa-sun\";\r\n\r\n/**\r\n * Proficiency level icons\r\n */\r\nexport const PROFICIENCY_LEVEL_ICON = {\r\n 0: \"fa-regular fa-circle\",\r\n 0.5: \"fa-regular fa-circle-half-stroke\",\r\n 1: \"fa-solid fa-circle\",\r\n 2: \"fa-regular fa-circle-dot\"\r\n};\r\n\r\n/**\r\n * Rarity\r\n */\r\nexport const RARITY = {\r\n common: \"tokenActionHud.dnd5e.common\",\r\n uncommon: \"tokenActionHud.dnd5e.uncommon\",\r\n rare: \"tokenActionHud.dnd5e.rare\",\r\n veryRare: \"tokenActionHud.dnd5e.veryRare\",\r\n legendary: \"tokenActionHud.dnd5e.legendary\",\r\n artifact: \"tokenActionHud.dnd5e.artifact\"\r\n};\r\n\r\n/**\r\n * Ritual icon\r\n */\r\nexport const RITUAL_ICON = \"fas fa-circle-r\";\r\n\r\n/**\r\n * Spell Group IDs\r\n */\r\nexport const SPELL_GROUP_IDS = [\r\n \"cantrips\",\r\n \"_1stLevelSpells\",\r\n \"_2ndLevelSpells\",\r\n \"_3rdLevelSpells\",\r\n \"_4thLevelSpells\",\r\n \"_5thLevelSpells\",\r\n \"_6thLevelSpells\",\r\n \"_7thLevelSpells\",\r\n \"_8thLevelSpells\",\r\n \"_9thLevelSpells\",\r\n \"atWillSpells\",\r\n \"innateSpells\",\r\n \"pactSpells\"\r\n];\r\n","import { MODULE } from \"./constants.js\";\r\n\r\nexport let Utils = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n Utils = class Utils {\r\n /**\r\n * Capitalize the first letter of every word\r\n * @param {string} value The string to capitalize\r\n * @returns {string} The capitalized string\r\n */\r\n static capitalize(value) {\r\n return value.replace(\r\n /\\w\\S*/g,\r\n text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()\r\n );\r\n }\r\n\r\n /**\r\n * Get setting value\r\n * @param {string} key The key\r\n * @param {string=null} defaultValue The default value\r\n * @returns {*} The setting value\r\n */\r\n static getSetting(key, defaultValue = null) {\r\n let value = defaultValue ?? null;\r\n try {\r\n value = game.settings.get(MODULE.ID, key);\r\n } catch{\r\n coreModule.api.Logger.debug(`Setting '${key}' not found`);\r\n }\r\n return value;\r\n }\r\n\r\n /**\r\n * Set setting value\r\n * @param {string} key The key\r\n * @param {string} value The value\r\n */\r\n static async setSetting(key, value) {\r\n try {\r\n value = await game.settings.set(MODULE.ID, key, value);\r\n coreModule.api.Logger.debug(`Setting '${key}' set to '${value}'`);\r\n } catch{\r\n coreModule.api.Logger.debug(`Setting '${key}' not found`);\r\n }\r\n }\r\n };\r\n});\r\n","// System Module Imports\r\nimport {\r\n ACTIVATION_TYPE, ACTION_TYPE, CONCENTRATION_ICON, CUSTOM_DND5E, FEATURE_GROUP_IDS,\r\n GROUP, PREPARED_ICON, PROFICIENCY_LEVEL_ICON, RARITY, SPELL_GROUP_IDS\r\n} from \"./constants.js\";\r\nimport { Utils } from \"./utils.js\";\r\n\r\nexport let ActionHandler = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n ActionHandler = class ActionHandler extends coreModule.api.ActionHandler {\r\n // Initialize action variables\r\n featureActions = null;\r\n\r\n inventoryActions = null;\r\n\r\n spellActions = null;\r\n\r\n /**\r\n * Build System Actions\r\n * @override\r\n * @param {Array} groupIds\r\n * @returns {object}\r\n */\r\n async buildSystemActions(groupIds) {\r\n // Set actor and token variables\r\n this.actors = (!this.actor) ? this.#getValidActors() : [this.actor];\r\n this.tokens = (!this.token) ? this.#getValidTokens() : [this.token];\r\n\r\n // Set items variable\r\n if (this.actor) {\r\n this.items = coreModule.api.Utils.sortItemsByName(this.#discardSlowItems(this.actor.items));\r\n }\r\n\r\n // Set settings variables\r\n this.abbreviateSkills = Utils.getSetting(\"abbreviateSkills\");\r\n this.displaySpellInfo = Utils.getSetting(\"displaySpellInfo\");\r\n this.showItemsWithoutActivationCosts = Utils.getSetting(\"showItemsWithoutActivationCosts\");\r\n this.showUnchargedItems = Utils.getSetting(\"showUnchargedItems\");\r\n this.showUnequippedItems = Utils.getSetting(\"showUnequippedItems\");\r\n if (this.actor?.type === \"npc\" && !this.showUnequippedItems) {\r\n this.showUnequippedItems = Utils.getSetting(\"showUnequippedItemsNpcs\");\r\n }\r\n this.showUnpreparedSpells = Utils.getSetting(\"showUnpreparedSpells\");\r\n\r\n this.activationgroupIds = [\r\n \"actions\",\r\n \"bonus-actions\",\r\n \"crew-actions\",\r\n \"lair-actions\",\r\n \"legendary-actions\",\r\n \"reactions\",\r\n \"other-actions\"\r\n ];\r\n\r\n if (this.actor?.type === \"character\" || this.actor?.type === \"npc\") {\r\n this.inventorygroupIds = [\r\n \"equipped\",\r\n \"consumables\",\r\n \"containers\",\r\n \"equipment\",\r\n \"loot\",\r\n \"tools\",\r\n \"weapons\",\r\n \"unequipped\"\r\n ];\r\n\r\n await this.#buildCharacterActions();\r\n } else if (this.actor?.type === \"vehicle\") {\r\n this.inventorygroupIds = [\r\n \"consumables\",\r\n \"equipment\",\r\n \"tools\",\r\n \"weapons\"\r\n ];\r\n\r\n await this.#buildVehicleActions();\r\n } else if (!this.actor) {\r\n await this.#buildMultipleTokenActions();\r\n }\r\n }\r\n\r\n /**\r\n * Build character actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildCharacterActions() {\r\n await Promise.all([\r\n this.#buildConditions(),\r\n this.#buildEffects(),\r\n this.#buildFeatures(),\r\n this.#buildInventory(),\r\n this.#buildSpells()\r\n ]);\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n this.#buildCounters();\r\n this.#buildExhaustion();\r\n this.#buildRests();\r\n this.#buildSkills();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build vehicle actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildVehicleActions() {\r\n await Promise.all([\r\n this.#buildConditions(),\r\n this.#buildEffects(),\r\n this.#buildFeatures(),\r\n this.#buildInventory()\r\n ]);\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build multiple token actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildMultipleTokenActions() {\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n await this.#buildConditions();\r\n this.#buildRests();\r\n this.#buildSkills();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build abilities\r\n * @private\r\n * @param {string} actionType\r\n * @param {string} groupId\r\n */\r\n #buildAbilities(actionType, groupId) {\r\n // Get abilities and exit if none exist\r\n const abilities = this.actor?.system.abilities || CONFIG.DND5E.abilities;\r\n if (abilities.length === 0) return;\r\n\r\n // Get actions\r\n const actions = Object.entries(abilities)\r\n .filter(ability => abilities[ability[0]].value !== 0)\r\n .map(([abilityId, ability]) => {\r\n const name = CONFIG.DND5E.abilities[abilityId].label;\r\n const mod = (groupId === \"saves\") ? ability?.save : ability?.mod;\r\n return {\r\n id: `${actionType}-${abilityId}`,\r\n name: (this.abbreviateSkills) ? Utils.capitalize(abilityId) : name,\r\n icon1: (groupId !== \"checks\") ? this.#getProficiencyIcon(abilities[abilityId].proficient) : \"\",\r\n info1: (this.actor) ? {\r\n text: coreModule.api.Utils.getModifier(mod),\r\n title: `${game.i18n.localize(\"DND5E.ActionAbil\")}: ${coreModule.api.Utils.getModifier(mod)}`\r\n } : null,\r\n info2: (this.actor && groupId === \"abilities\") ? {\r\n text: `(${coreModule.api.Utils.getModifier(ability?.save)})`,\r\n title: `${game.i18n.localize(\"DND5E.SavingThrow\")}: ${coreModule.api.Utils.getModifier(ability?.save)}`\r\n } : null,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, abilityId }\r\n };\r\n });\r\n\r\n // Add actions to action list\r\n this.addActions(actions, { id: groupId });\r\n }\r\n\r\n /**\r\n * Build activations\r\n * @public\r\n * @param {object} data groupData, actionData, actionType\r\n */\r\n async buildActivations(data) {\r\n const { groupData, actionData, actionType = \"item\" } = data;\r\n\r\n // Create map of items according to activation type\r\n const activationItems = new Map();\r\n\r\n // Loop items and add to activationItems\r\n for (const [key, value] of actionData) {\r\n const activationType = value.system?.activities?.contents[0]?.activation?.type;\r\n const groupId = ACTIVATION_TYPE[activationType]?.group ?? \"other\";\r\n if (!activationItems.has(groupId)) activationItems.set(groupId, new Map());\r\n activationItems.get(groupId).set(key, value);\r\n }\r\n\r\n // Loop through action group ids\r\n for (const value of Object.values(ACTIVATION_TYPE)) {\r\n const group = value.group;\r\n\r\n // Skip if no items exist\r\n if (!activationItems.has(group)) continue;\r\n\r\n // Clone and add to group data\r\n const groupDataClone = { ...groupData, id: `${group}+${groupData.id}`, type: \"system-derived\" };\r\n\r\n // Set Equipped and Unequipped groups to not selected by default\r\n if ([\"equipped\", \"unequipped\"].includes(groupData.id)) { groupDataClone.defaultSelected = false; }\r\n\r\n // Create parent group data\r\n const parentgroupData = { id: group, type: \"system\" };\r\n\r\n // Add group to HUD\r\n await this.addGroup(groupDataClone, parentgroupData);\r\n\r\n // Add spell slot info to group\r\n if (actionType === \"spell\") { this.addGroupInfo(groupDataClone); }\r\n\r\n // Build actions\r\n await this.buildActions({\r\n groupData: groupDataClone,\r\n actionData: activationItems.get(group),\r\n actionType\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Build combat\r\n * @private\r\n */\r\n #buildCombat() {\r\n // If token's turn, include endTurn\r\n const combatType = {\r\n initiative: \"tokenActionHud.dnd5e.rollInitiative\",\r\n ...(game.combat?.current?.tokenId !== this.token?.id && { endTurn: \"tokenActionHud.endTurn\" })\r\n };\r\n\r\n const tokens = coreModule.api.Utils.getControlledTokens();\r\n const tokenIds = tokens?.map(token => token.id);\r\n const combatants = (game.combat)\r\n ? game.combat.combatants.filter(combatant => tokenIds.includes(combatant.tokenId))\r\n : [];\r\n\r\n const getInfo1 = id => {\r\n if (id === \"initiative\" && combatants.length === 1) {\r\n const currentInitiative = combatants[0].initiative;\r\n return { class: \"tah-spotlight\", text: currentInitiative };\r\n }\r\n return {};\r\n };\r\n\r\n const getActive = () => { return combatants.length > 0 && (combatants.every(combatant => combatant?.initiative)) ? \" active\" : \"\";};\r\n\r\n // Get actions\r\n const actionType = \"utility\";\r\n const actions = Object.entries(combatType).map(([id, name]) => {\r\n return {\r\n id,\r\n name: game.i18n.localize(name),\r\n info1: getInfo1(id),\r\n cssClass: (id === \"initiative\" ) ? `toggle${getActive()}` : \"\",\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"combat\" });\r\n }\r\n\r\n /**\r\n * Build conditions\r\n * @private\r\n */\r\n async #buildConditions() {\r\n if (this.tokens?.length === 0) return;\r\n\r\n // Get conditions and exit if none exist\r\n const conditions = CONFIG.statusEffects.filter(condition => condition.id !== \"\");\r\n if (conditions.length === 0) return;\r\n\r\n // Get actions\r\n const actionType = \"condition\";\r\n const actions = await Promise.all(conditions.map(async condition => {\r\n const hasCondition = this.actors.every(actor => {\r\n return actor.effects.some(effect => effect.statuses.some(status => status === condition.id)\r\n && !effect?.disabled);\r\n });\r\n const name = game.i18n.localize(condition.label) ?? condition.name;\r\n return {\r\n id: condition.id,\r\n name,\r\n img: coreModule.api.Utils.getImage(condition),\r\n cssClass: `toggle${(hasCondition) ? \" active\" : \"\"}`,\r\n listName: this.#getListName(actionType, name),\r\n tooltip: await this.#getTooltip(await this.#getConditionTooltipData(condition.id, condition.name)),\r\n system: { actionType, actionId: condition.id }\r\n };\r\n }));\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"conditions\" });\r\n }\r\n\r\n /**\r\n * Build counters\r\n * @private\r\n */\r\n async #buildCounters() {\r\n if (!coreModule.api.Utils.isModuleActive(CUSTOM_DND5E.ID)\r\n || !CUSTOM_DND5E.COUNTERS[this.actor?.type]) return;\r\n\r\n const actionType = \"counter\";\r\n\r\n let counters = game.settings.get(CUSTOM_DND5E.ID, CUSTOM_DND5E.COUNTERS[this.actor?.type]) ?? {};\r\n\r\n if (coreModule.api.Utils.isModuleActive(CUSTOM_DND5E.ID) && Object.keys(counters).length) {\r\n counters = Object.entries(counters)\r\n .filter(([_, value]) => value.visible)\r\n .map(([key, value]) => {\r\n value.key = key;\r\n return value;\r\n });\r\n } else {\r\n counters = [\r\n {\r\n name: game.i18n.localize(\"DND5E.DeathSave\"),\r\n type: \"successFailure\",\r\n system: true,\r\n visible: true,\r\n key: \"death-saves\"\r\n },\r\n {\r\n name: game.i18n.localize(\"DND5E.Exhaustion\"),\r\n type: \"number\",\r\n system: true,\r\n visible: true,\r\n key: \"exhaustion\"\r\n },\r\n {\r\n name: game.i18n.localize(\"DND5E.Inspiration\"),\r\n type: \"checkbox\",\r\n system: true,\r\n visible: true,\r\n key: \"inspiration\"\r\n }\r\n ];\r\n }\r\n\r\n // Get actions\r\n const actions = counters.map(counter => {\r\n let active = \"\";\r\n let cssClass = \"\";\r\n let img = \"\";\r\n let info1 = \"\";\r\n if (counter.system) {\r\n switch (counter.key) {\r\n case \"exhaustion\":\r\n active = (this.actor.system.attributes.exhaustion > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/exhaustion.svg\");\r\n info1 = { text: this.actor.system.attributes.exhaustion };\r\n break;\r\n case \"death-saves\":\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/death-saves.svg\");\r\n info1 = { text: `${this.actor.system.attributes.death.success}/${this.actor.system.attributes.death.failure}` };\r\n break;\r\n case \"inspiration\":\r\n active = (this.actor.system.attributes.inspiration) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/inspiration.svg\");\r\n break;\r\n }\r\n } else {\r\n const value = this.actor.getFlag(CUSTOM_DND5E.ID, counter.key);\r\n switch (counter.type) {\r\n case \"checkbox\":\r\n active = (value) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n break;\r\n case \"fraction\":\r\n active = (value.value > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n info1 = { text: `${value.value ?? 0}/${value.max ?? 0}` };\r\n break;\r\n case \"number\":\r\n active = (value > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n info1 = { text: value };\r\n break;\r\n case \"successFailure\":\r\n info1 = { text: `${value?.success ?? 0}/${value?.failure ?? 0}` };\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n id: counter.key,\r\n name: counter.label,\r\n listName: this.#getListName(actionType, counter.name),\r\n cssClass,\r\n img,\r\n info1,\r\n system: { actionType, counterKey: counter.key, counterType: counter.type}\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"counters\" });\r\n }\r\n\r\n /**\r\n * Build effects\r\n * @private\r\n */\r\n async #buildEffects() {\r\n const actionType = \"effect\";\r\n\r\n // Get effects and exit if none exist\r\n const effects = new Map(this.actor.allApplicableEffects().map(effect => [effect.id, effect]));\r\n if (effects.size === 0) return;\r\n\r\n // Map passive and temporary effects to new maps\r\n const passiveEffects = new Map();\r\n const temporaryEffects = new Map();\r\n const statusEffectIds = new Set(CONFIG.statusEffects.map(statusEffect => statusEffect._id));\r\n\r\n // Iterate effects and add to a map based on the isTemporary value\r\n for (const [effectId, effect] of effects.entries()) {\r\n if (effect.isSuppressed) continue;\r\n if (effect.parent?.system?.identified === false && !game.user.isGM) continue;\r\n if (statusEffectIds.has(effect.id)) continue;\r\n\r\n if (effect.isTemporary) { temporaryEffects.set(effectId, effect); }\r\n else { passiveEffects.set(effectId, effect); }\r\n }\r\n\r\n // Build passive and temporary effects\r\n await Promise.all([\r\n this.buildActions({ groupData: { id: \"passive-effects\" }, actionData: passiveEffects, actionType }),\r\n this.buildActions({ groupData: { id: \"temporary-effects\" }, actionData: temporaryEffects, actionType })\r\n ]);\r\n }\r\n\r\n /**\r\n * Build exhaustion\r\n * @private\r\n */\r\n #buildExhaustion() {\r\n // Exit if every actor is not the character type\r\n if (!this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n // Get actions\r\n const actionType = \"exhaustion\";\r\n const active = this.actor.system.attributes.exhaustion > 0 ? \" active\" : \"\";\r\n const actions = [{\r\n id: \"exhaustion\",\r\n name: game.i18n.localize(\"DND5E.Exhaustion\"),\r\n cssClass: `toggle${active}`,\r\n img: coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/exhaustion.svg\"),\r\n info1: { text: this.actor.system.attributes.exhaustion },\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: \"exhaustion\" }\r\n }];\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"exhaustion\" });\r\n }\r\n\r\n /**\r\n * Build features\r\n * @private\r\n */\r\n async #buildFeatures() {\r\n // Filter feats from items and exit if none exist\r\n const feats = new Map([...this.items].filter(([, value]) => value.type === \"feat\"));\r\n if (feats.size === 0) return;\r\n\r\n // Map active and passive features to new maps\r\n const featuresMap = new Map([\r\n [\"activeFeatures\", new Map()],\r\n [\"passiveFeatures\", new Map()]\r\n ]);\r\n\r\n const featureType = {\r\n background: \"backgroundFeatures\",\r\n class: \"classFeatures\",\r\n monster: \"monsterFeatures\",\r\n race: \"raceFeatures\",\r\n feats: \"feats\"\r\n };\r\n\r\n const classFeatureType = {\r\n artificerInfusion: \"artificerInfusions\",\r\n channelDivinity: \"channelDivinity\",\r\n defensiveTactic: \"defensiveTactics\",\r\n eldritchInvocation: \"eldritchInvocations\",\r\n elementalDiscipline: \"elementalDisciplines\",\r\n fightingStyle: \"fightingStyles\",\r\n huntersPrey: \"huntersPrey\",\r\n ki: \"kiAbilities\",\r\n maneuver: \"maneuvers\",\r\n metamagic: \"metamagicOptions\",\r\n multiattack: \"multiattacks\",\r\n pact: \"pactBoons\",\r\n psionicPower: \"psionicPowers\",\r\n rune: \"runes\",\r\n superiorHuntersDefense: \"superiorHuntersDefense\"\r\n };\r\n\r\n for (const [key, value] of feats) {\r\n const activationType = value.system.activities.contents[0]?.type;\r\n const type = value.system.type.value;\r\n const subType = value.system.type?.subtype;\r\n\r\n if (activationType) { featuresMap.get(\"activeFeatures\").set(key, value); }\r\n else { featuresMap.get(\"passiveFeatures\").set(key, value); }\r\n\r\n // Map feature types\r\n if (featureType[type]) {\r\n if (!featuresMap.has(featureType[type])) featuresMap.set(featureType[type], new Map());\r\n featuresMap.get(featureType[type]).set(key, value);\r\n }\r\n\r\n // Map class feature subtypes\r\n if (classFeatureType[subType]) {\r\n if (!featuresMap.has(classFeatureType[subType])) featuresMap.set(classFeatureType[subType], new Map());\r\n featuresMap.get(classFeatureType[subType]).set(key, value);\r\n }\r\n }\r\n\r\n // Loop through inventory groups ids\r\n for (const id of FEATURE_GROUP_IDS) {\r\n const actionData = featuresMap.get(id);\r\n if (!actionData || actionData.size === 0) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: GROUP[id].id,\r\n name: game.i18n.localize(GROUP[id].name) ?? \"\"\r\n };\r\n\r\n // Build actions and activations\r\n const actionType = \"feature\";\r\n await this.buildActions({ groupData, actionData, actionType });\r\n await this.buildActivations({ groupData, actionData, actionType });\r\n }\r\n }\r\n\r\n /**\r\n * Build inventory\r\n * @private\r\n */\r\n async #buildInventory() {\r\n // Exit early if no items exist\r\n if (this.items.size === 0) return;\r\n\r\n // Initialize inventory map categories\r\n const inventoryMap = new Map([\r\n [\"equipped\", new Map()],\r\n [\"unequipped\", new Map()],\r\n [\"consumables\", new Map()],\r\n [\"containers\", new Map()],\r\n [\"equipment\", new Map()],\r\n [\"loot\", new Map()],\r\n [\"tools\", new Map()],\r\n [\"weapons\", new Map()]\r\n ]);\r\n\r\n for (const [key, value] of this.items) {\r\n // Set items into maps\r\n if (value.system?.quantity > 0 && this.#isActiveItem(value)) {\r\n if (value.system.equipped) { inventoryMap.get(\"equipped\").set(key, value); }\r\n else { inventoryMap.get(\"unequipped\").set(key, value); }\r\n\r\n if (this.#isUsableItem(value) && value.type === \"consumable\") inventoryMap.get(\"consumables\").set(key, value);\r\n if (this.#isEquippedItem(value)) {\r\n switch (value.type) {\r\n case \"container\": inventoryMap.get(\"containers\").set(key, value); break;\r\n case \"equipment\": inventoryMap.get(\"equipment\").set(key, value); break;\r\n case \"loot\": inventoryMap.get(\"loot\").set(key, value); break;\r\n case \"tool\": inventoryMap.get(\"tools\").set(key, value); break;\r\n case \"weapon\": inventoryMap.get(\"weapons\").set(key, value); break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Loop through inventory subcateogry ids\r\n for (const groupId of this.inventorygroupIds) {\r\n const actionData = inventoryMap.get(groupId);\r\n if (!actionData || actionData.size === 0) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: groupId,\r\n name: game.i18n.localize(GROUP[groupId].name)\r\n };\r\n\r\n const data = { groupData, actionData };\r\n\r\n // Build actions and activations\r\n await this.buildActions(data);\r\n await this.buildActivations(data);\r\n }\r\n }\r\n\r\n /**\r\n * Build rests\r\n * @private\r\n */\r\n #buildRests() {\r\n // Exit if every actor is not the character type\r\n if (this.actors.length === 0 || !this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n // Get actions\r\n const actionType = \"utility\";\r\n const restTypes = { shortRest: \"DND5E.ShortRest\", longRest: \"DND5E.LongRest\" };\r\n const actions = Object.entries(restTypes).map(([id, name]) => {\r\n name = game.i18n.localize(name);\r\n return {\r\n id,\r\n name,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"rests\" });\r\n }\r\n\r\n /**\r\n * Build skills\r\n * @private\r\n */\r\n #buildSkills() {\r\n // Get skills and exit if none exist\r\n const skills = this.actor?.system.skills || CONFIG.DND5E.skills;\r\n if (skills.length === 0) return;\r\n\r\n // Get actions\r\n const actionType = \"skill\";\r\n const actions = Object.entries(skills).map(([id, skill]) => {\r\n try {\r\n const name = CONFIG.DND5E.skills[id].label;\r\n return {\r\n id,\r\n name: this.abbreviateSkills ? Utils.capitalize(id) : name,\r\n icon1: this.#getProficiencyIcon(skill.value),\r\n info1: (this.actor) ? { text: coreModule.api.Utils.getModifier(skill.total) } : \"\",\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n } catch(error) {\r\n coreModule.api.Logger.error(skill);\r\n return null;\r\n }\r\n }).filter(skill => !!skill);\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"skills\" });\r\n }\r\n\r\n /**\r\n * Build spells\r\n */\r\n async #buildSpells() {\r\n // Filter items for spells and exit if none exist\r\n const spells = new Map([...this.items].filter(([, value]) => value.type === \"spell\"));\r\n if (spells.size === 0) return;\r\n\r\n // Initialize spells map categories\r\n const spellsMap = new Map([\r\n [\"atWillSpells\", new Map()],\r\n [\"innateSpells\", new Map()],\r\n [\"pactSpells\", new Map()],\r\n [\"cantrips\", new Map()],\r\n [\"_1stLevelSpells\", new Map()],\r\n [\"_2ndLevelSpells\", new Map()],\r\n [\"_3rdLevelSpells\", new Map()],\r\n [\"_4thLevelSpells\", new Map()],\r\n [\"_5thLevelSpells\", new Map()],\r\n [\"_6thLevelSpells\", new Map()],\r\n [\"_7thLevelSpells\", new Map()],\r\n [\"_8thLevelSpells\", new Map()],\r\n [\"_9thLevelSpells\", new Map()]\r\n ]);\r\n\r\n // Loop through items\r\n for (const [key, value] of spells) {\r\n if (!this.#isUsableItem(value) || !this.#isUsableSpell(value)) continue;\r\n\r\n switch (value.system.preparation.mode) {\r\n case \"atwill\":\r\n spellsMap.get(\"atWillSpells\").set(key, value); break;\r\n case \"innate\":\r\n spellsMap.get(\"innateSpells\").set(key, value); break;\r\n case \"pact\":\r\n spellsMap.get(\"pactSpells\").set(key, value); break;\r\n default: {\r\n switch (value.system.level) {\r\n case 0:\r\n spellsMap.get(\"cantrips\").set(key, value); break;\r\n case 1:\r\n spellsMap.get(\"_1stLevelSpells\").set(key, value); break;\r\n case 2:\r\n spellsMap.get(\"_2ndLevelSpells\").set(key, value); break;\r\n case 3:\r\n spellsMap.get(\"_3rdLevelSpells\").set(key, value); break;\r\n case 4:\r\n spellsMap.get(\"_4thLevelSpells\").set(key, value); break;\r\n case 5:\r\n spellsMap.get(\"_5thLevelSpells\").set(key, value); break;\r\n case 6:\r\n spellsMap.get(\"_6thLevelSpells\").set(key, value); break;\r\n case 7:\r\n spellsMap.get(\"_7thLevelSpells\").set(key, value); break;\r\n case 8:\r\n spellsMap.get(\"_8thLevelSpells\").set(key, value); break;\r\n case 9:\r\n spellsMap.get(\"_9thLevelSpells\").set(key, value); break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Reverse sort spell slots by level\r\n const systemSpells = Object.entries(this.actor.system.spells).reverse();\r\n\r\n // Set spell slot availability\r\n const spellSlotsMap = new Map();\r\n let spellSlotAvailable = this.showUnchargedItems;\r\n let pactSlotAvailable = this.showUnchargedItems;\r\n let pactSlot = null;\r\n\r\n for (const [key, value] of systemSpells) {\r\n const hasValue = value.value > 0;\r\n const hasMax = value.max > 0;\r\n const hasLevel = value.level > 0;\r\n\r\n if (key === \"pact\") {\r\n pactSlotAvailable = pactSlotAvailable || (hasValue && hasMax && hasLevel);\r\n value.slotAvailable = pactSlotAvailable && hasLevel;\r\n pactSlot = [key, value];\r\n } else if (key.startsWith(\"spell\") && key !== \"spell0\") {\r\n spellSlotAvailable = spellSlotAvailable || (hasValue && hasMax);\r\n value.slotAvailable = spellSlotAvailable;\r\n spellSlotsMap.set(key, value);\r\n } else if (hasValue) {\r\n value.slotsAvailable = true;\r\n spellSlotsMap.set(key, value);\r\n }\r\n }\r\n\r\n // Set equivalent spell slot where pact slot is available\r\n if (pactSlot[1].slotAvailable) {\r\n const spellSlot = spellSlotsMap.get(`spell${pactSlot[1].level}`);\r\n spellSlot.slotsAvailable = true;\r\n }\r\n\r\n const spellSlotModes = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, \"pact\"]);\r\n\r\n for (const id of SPELL_GROUP_IDS) {\r\n // Skip if no spells exist\r\n if (!spellsMap.has(id)) continue;\r\n\r\n const spellMode = GROUP[id].spellMode;\r\n const levelInfo = (spellMode === \"pact\") ? pactSlot[1] : spellSlotsMap.get(`spell${spellMode}`);\r\n const { value: slots = 0, max = 0, slotAvailable = false } = levelInfo || {};\r\n\r\n // Skip if spells require spell slots and none are available\r\n if (!slotAvailable && spellSlotModes.has(spellMode)) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: GROUP[id].id,\r\n name: game.i18n.localize(GROUP[id].name),\r\n info: { info1: { class: \"tah-spotlight\", text: (max > 0) ? `${slots}/${max}` : \"\" } }\r\n };\r\n\r\n // Add spell slot info to group\r\n this.addGroupInfo(groupData);\r\n\r\n const data = { groupData, actionData: spellsMap.get(id), actionType: \"spell\" };\r\n\r\n // Build actions and activations\r\n await this.buildActions(data);\r\n await this.buildActivations(data);\r\n }\r\n }\r\n\r\n /**\r\n * Build utility\r\n * @private\r\n */\r\n #buildUtility() {\r\n // Exit if every actor is not the character type\r\n if (this.actors.length === 0) return;\r\n if (!this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n const actionType = \"utility\";\r\n\r\n // Set utility types\r\n const utilityTypes = {\r\n deathSave: { name: game.i18n.localize(\"DND5E.DeathSave\") },\r\n inspiration: { name: game.i18n.localize(\"DND5E.Inspiration\") }\r\n };\r\n\r\n // Delete 'deathSave' for multiple tokens\r\n if (!this.actor || this.actor.system.attributes.hp.value > 0) delete utilityTypes.deathSave;\r\n\r\n // Get actions\r\n const actions = Object.entries(utilityTypes)\r\n .map(utilityType => {\r\n const id = utilityType[0];\r\n const name = utilityType[1].name;\r\n let cssClass = \"\";\r\n if (utilityType[0] === \"inspiration\") {\r\n const active = this.actors.every(actor => actor.system.attributes?.inspiration)\r\n ? \" active\"\r\n : \"\";\r\n cssClass = `toggle${active}`;\r\n }\r\n return {\r\n id,\r\n name,\r\n cssClass,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Crreate group data\r\n const groupData = { id: \"utility\" };\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, groupData);\r\n }\r\n\r\n /**\r\n * Build actions\r\n * @public\r\n * @param {object} data actionData, groupData, actionType\r\n * @param {object} options\r\n */\r\n async buildActions(data, options) {\r\n const { actionData, groupData, actionType } = data;\r\n\r\n // Exit if there is no action data\r\n if (actionData.size === 0) return;\r\n\r\n // Exit if there is no groupId\r\n const groupId = (typeof groupData === \"string\" ? groupData : groupData?.id);\r\n if (!groupId) return;\r\n\r\n // Get actions\r\n const actions = await Promise.all([...actionData].map(async item => await this.#getAction(item[1], actionType)));\r\n\r\n // Add actions to action list\r\n this.addActions(actions, groupData);\r\n }\r\n\r\n /**\r\n * Get action\r\n * @private\r\n * @param {object} entity The entity\r\n * @param {string} actionType The action type\r\n * @returns {object} The action\r\n */\r\n async #getAction(entity, actionType = \"item\") {\r\n const id = entity.id ?? entity._id;\r\n let name = entity?.name ?? entity?.label;\r\n let cssClass = \"\";\r\n if (Object.hasOwn(entity, \"disabled\")) {\r\n const active = (!entity.disabled) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n }\r\n const info = this.#getItemInfo(entity);\r\n const tooltip = await this.#getTooltip(await this.#getTooltipData(entity));\r\n return {\r\n id,\r\n name,\r\n cssClass,\r\n img: coreModule.api.Utils.getImage(entity),\r\n icon1: this.#getActivationTypeIcon(entity.system?.activities?.contents[0]?.activation.type),\r\n icon2: this.#getPreparedIcon(entity),\r\n icon3: this.#getConcentrationIcon(entity),\r\n info1: info?.info1,\r\n info2: info?.info2,\r\n info3: info?.info3,\r\n listName: this.#getListName(actionType, name),\r\n tooltip,\r\n system: { actionType, actionId: id }\r\n };\r\n }\r\n\r\n /**\r\n * Is active item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is active\r\n */\r\n #isActiveItem(item) {\r\n if (this.showItemsWithoutActivationCosts) return true;\r\n const activationTypes = new Set(Object.keys(CONFIG.DND5E.activityActivationTypes).filter(activationType => activationType !== \"none\"));\r\n const activationType = item.system?.activities?.contents[0]?.activation?.type;\r\n return activationTypes.has(activationType) || item.type === \"tool\";\r\n }\r\n\r\n /**\r\n * Is equipped item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is equipped\r\n */\r\n #isEquippedItem(item) {\r\n const excludedTypes = [\"consumable\", \"spell\", \"feat\"];\r\n return (this.showUnequippedItems && !excludedTypes.includes(item.type))\r\n || (item.system.equipped && item.type !== \"consumable\");\r\n }\r\n\r\n /**\r\n * Is usable item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is usable\r\n */\r\n #isUsableItem(item) {\r\n return this.showUnchargedItems || !!item.system.uses?.value || !item.system.uses?.max;\r\n }\r\n\r\n /**\r\n * Is usable spell\r\n * @private\r\n * @param {object} spell The spell\r\n * @returns {boolean} Whether the spell is usable\r\n */\r\n #isUsableSpell(spell) {\r\n if (this.actor?.type !== \"character\" && this.showUnequippedItems) return true;\r\n if (this.showUnpreparedSpells) return true;\r\n\r\n const preparationModes = new Set(Object.keys(CONFIG.DND5E.spellPreparationModes).filter(preparationMode => preparationMode !== \"prepared\"));\r\n\r\n // Return true if the spell has a preparation mode other than 'prepared' or is prepared\r\n return preparationModes.has(spell.system.preparation.mode) || spell.system.preparation.prepared;\r\n }\r\n\r\n #getListName(actionType, actionName) {\r\n const prefix = `${game.i18n.localize(ACTION_TYPE[actionType])}: ` ?? \"\";\r\n return `${prefix}${actionName}` ?? \"\";\r\n }\r\n\r\n /**\r\n * Get item info\r\n * @private\r\n * @param {object} item\r\n * @returns {object}\r\n */\r\n #getItemInfo(item) {\r\n const info1 = item.type === \"spell\" ? this.#getSpellInfo(item) : this.#getQuantityData(item);\r\n const info2 = this.#getUsesData(item);\r\n const info3 = this.#getConsumeData(item);\r\n\r\n return { info1, info2, info3 };\r\n }\r\n\r\n /**\r\n * Add spell info\r\n * @private\r\n * @param {object} spell The spell\r\n * @returns {object} The spell info\r\n */\r\n #getSpellInfo(spell) {\r\n if (!this.displaySpellInfo) return null;\r\n\r\n const components = spell.system?.properties;\r\n if (!components) return null;\r\n\r\n const info = { text: \"\", title: \"\" };\r\n const componentTypes = {\r\n vocal: \"DND5E.ComponentVerbal\",\r\n somatic: \"DND5E.ComponentSomatic\",\r\n material: \"DND5E.ComponentMaterial\"\r\n };\r\n\r\n\r\n const componentsArray = Object.entries(componentTypes)\r\n .filter(([key]) => components[key])\r\n .map(([key, label]) => {\r\n info.text += game.i18n.localize(`${label}Abbr`);\r\n return game.i18n.localize(label);\r\n });\r\n\r\n // Ritual\r\n if (components.ritual) {\r\n componentsArray.push(`[${game.i18n.localize(\"DND5E.Ritual\")}]`);\r\n info.text += ` [${game.i18n.localize(\"DND5E.RitualAbbr\")}]`;\r\n }\r\n\r\n info.title = componentsArray.join(\", \");\r\n\r\n return info;\r\n }\r\n\r\n /**\r\n * Get valid actors\r\n * @private\r\n * @returns {object}\r\n */\r\n #getValidActors() {\r\n const allowedTypes = [\"character\", \"npc\"];\r\n return this.actors.every(actor => allowedTypes.includes(actor.type)) ? this.actors : [];\r\n }\r\n\r\n /**\r\n * Get valid tokens\r\n * @private\r\n * @returns {object}\r\n */\r\n #getValidTokens() {\r\n const allowedTypes = [\"character\", \"npc\"];\r\n return this.actors.every(actor => allowedTypes.includes(actor.type)) ? this.tokens : [];\r\n }\r\n\r\n /**\r\n * Get quantity\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getQuantityData(item) {\r\n const quantity = item?.system?.quantity ?? 0;\r\n return {\r\n text: (quantity > 1) ? quantity : \"\",\r\n title: `${game.i18n.localize(\"DND5E.Quantity\")}: ${quantity}`\r\n };\r\n }\r\n\r\n /**\r\n * Get uses\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getUsesData(item) {\r\n const uses = item?.system?.uses;\r\n if (!(uses?.max > 0)) return {};\r\n const per = uses.recovery[0]?.period === \"charges\" ? \"\" : ` ${game.i18n.localize(\"DND5E.per\")} `;\r\n const period = CONFIG.DND5E.limitedUsePeriods[uses.recovery[0]?.period]?.label ?? uses.recovery[0]?.period;\r\n const perPeriod = (period) ? `${per}${period}` : \"\";\r\n const remainingUses = uses.max - (uses.spent ?? 0);\r\n const text = `${remainingUses}/${uses.max}`;\r\n const title = `${text}${perPeriod}`;\r\n return { text, title };\r\n }\r\n\r\n /**\r\n * Get consume\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getConsumeData(item) {\r\n // Get consume target and type\r\n const firstActivity = item?.system?.activities?.contents[0];\r\n const firstTarget = firstActivity?.consumption?.targets?.[0];\r\n const consumeId = firstTarget?.target;\r\n const consumeType = firstTarget?.type;\r\n const consumeAmount = firstTarget?.value;\r\n\r\n if (!consumeId || !consumeType || consumeId === item.id) return {};\r\n\r\n // Return resources\r\n if (consumeType === \"attribute\") {\r\n const parentId = consumeId.substr(0, consumeId.lastIndexOf(\".\"));\r\n const target = foundry.utils.getProperty(this.actor.system, parentId);\r\n\r\n if (target) {\r\n const text = `${target.value ?? \"0\"}${target.max ? `/${target.max}` : \"\"}`;\r\n return {\r\n text,\r\n title: `${text} ${target.label ?? \"\"}`\r\n };\r\n }\r\n } else {\r\n const target = this.actor.items?.get(consumeId);\r\n\r\n // Return charges\r\n if (target && consumeType === \"charges\") {\r\n return this.#getUsesData(target);\r\n }\r\n\r\n // Return quantity\r\n if (target?.system?.quantity) {\r\n const text = `${consumeAmount > 1 ? `${consumeAmount} ${game.i18n.localize(\"DND5E.of\")} ` : \"\"}${target.system.quantity}`;\r\n return {\r\n text,\r\n title: `${text} ${target.name}`\r\n };\r\n }\r\n }\r\n\r\n return {};\r\n }\r\n\r\n /**\r\n * Discard slow items\r\n * @private\r\n * @param {Map} items The items\r\n * @returns {Map} The filtered items\r\n */\r\n #discardSlowItems(items) {\r\n // Return all items if slow actions are allowed\r\n if (Utils.getSetting(\"showSlowActions\")) return items;\r\n\r\n // Define slow activation types\r\n const slowActivationTypes = new Set([\"minute\", \"hour\", \"day\"]);\r\n\r\n // Filter out slow items and return the result\r\n return new Map([...items.entries()].filter(([_, item]) => {\r\n const activationType = item.system?.activation?.type;\r\n return !slowActivationTypes.has(activationType);\r\n }));\r\n }\r\n\r\n /**\r\n * Get proficiency icon\r\n * @param {string} level\r\n * @returns {string}\r\n */\r\n #getProficiencyIcon(level) {\r\n const title = CONFIG.DND5E.proficiencyLevels[level] ?? \"\";\r\n const icon = PROFICIENCY_LEVEL_ICON[level];\r\n return (icon) ? `` : \"\";\r\n }\r\n\r\n /**\r\n * Get icon for the activation type\r\n * @private\r\n * @param {object} activationType The activation type\r\n * @returns {string} The icon\r\n */\r\n #getActivationTypeIcon(activationType) {\r\n const title = CONFIG.DND5E.abilityActivationTypes[activationType] ?? \"\";\r\n const icon = ACTIVATION_TYPE[activationType]?.icon;\r\n return (icon) ? `` : \"\";\r\n }\r\n\r\n /**\r\n * Get icon for concentration type\r\n * @private\r\n * @param {object} spell\r\n * @returns {string}\r\n */\r\n #getConcentrationIcon(spell) {\r\n if (spell?.type !== \"spell\" || !this.displaySpellInfo || !spell.system?.properties?.has(\"concentration\")) return null;\r\n const title = game.i18n.localize(\"DND5E.Scroll.RequiresConcentration\");\r\n const icon = CONCENTRATION_ICON;\r\n return ``;\r\n }\r\n\r\n /**\r\n * Get icon for a prepared spell\r\n * @private\r\n * @param {object} spell\r\n * @returns\r\n */\r\n #getPreparedIcon(spell) {\r\n if (spell?.type !== \"spell\" || !this.showUnpreparedSpells) return null;\r\n const level = spell.system.level;\r\n const preparationMode = spell.system.preparation.mode;\r\n const prepared = spell.system.preparation.prepared;\r\n const icon = prepared ? PREPARED_ICON : `${PREPARED_ICON} tah-icon-disabled`;\r\n const title = preparationMode === \"always\" ? game.i18n.localize(\"DND5E.SpellPrepAlways\") : prepared ? game.i18n.localize(\"DND5E.SpellPrepared\") : game.i18n.localize(\"DND5E.SpellUnprepared\");\r\n\r\n // Return icon if the preparation mode is 'prepared' or 'always' and the spell is not a cantrip\r\n return ((preparationMode === \"prepared\" || preparationMode === \"always\") && level !== 0) ? `` : null;\r\n }\r\n\r\n async #getTooltipData(entity) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n\r\n const name = entity?.name ?? \"\";\r\n\r\n if (this.tooltipsSetting === \"nameOnly\") return name;\r\n\r\n const unidentified = entity.system?.identified === false;\r\n const description = (typeof entity?.system?.description === \"string\") ? entity?.system?.description : (unidentified ? entity?.system?.unidentified?.description : entity?.system?.description?.value) ?? \"\";\r\n let modifiers; let properties; let rarity; let traits;\r\n if (!unidentified) {\r\n modifiers = entity?.modifiers ?? null;\r\n properties = [\r\n ...entity.system?.chatProperties ?? [],\r\n ...entity.system?.equippableItemCardProperties ?? [],\r\n entity.system?.parent?.labels?.activation,\r\n entity.system?.parent?.labels?.target,\r\n entity.system?.parent?.labels?.range,\r\n entity.system?.parent?.labels?.duration\r\n ].filter(p => p);\r\n rarity = unidentified ? null : entity?.rarity ?? null;\r\n traits = (entity?.type === \"weapon\") ? this.#getWeaponProperties(entity?.system?.properties) : null;\r\n }\r\n return { name, description, modifiers, properties, rarity, traits };\r\n }\r\n\r\n /**\r\n * Get condition tooltip data\r\n * @param {*} id The condition id\r\n * @param {*} name The condition name\r\n * @returns {object} The tooltip data\r\n */\r\n async #getConditionTooltipData(id, name) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n\r\n const condition = CONFIG.DND5E.conditionTypes[id];\r\n\r\n if (this.tooltipsSetting === \"nameOnly\" || !condition) return name;\r\n\r\n const journalEntry = (condition.reference) ? await fromUuid(condition.reference) : null;\r\n const description = journalEntry?.text?.content ?? \"\";\r\n const relativeTo = journalEntry;\r\n return {\r\n name,\r\n description,\r\n relativeTo\r\n };\r\n }\r\n\r\n /**\r\n * Get tooltip\r\n * @param {object} tooltipData The tooltip data\r\n * @returns {string} The tooltip\r\n */\r\n async #getTooltip(tooltipData) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n if (typeof tooltipData === \"string\") return tooltipData;\r\n\r\n const name = game.i18n.localize(tooltipData.name);\r\n\r\n if (this.tooltipsSetting === \"nameOnly\") return name;\r\n\r\n const nameHtml = `

${name}

`;\r\n\r\n const relativeTo = tooltipData.relativeTo ?? this.actor;\r\n\r\n const description = tooltipData?.descriptionLocalised\r\n ?? await TextEditor.enrichHTML(game.i18n.localize(tooltipData?.description ?? \"\"), { async: true, relativeTo, secrets: true });\r\n\r\n const rarityHtml = tooltipData?.rarity\r\n ? `${game.i18n.localize(RARITY[tooltipData.rarity])}`\r\n : \"\";\r\n\r\n const propertiesHtml = tooltipData?.properties\r\n ? `
${tooltipData.properties.map(property => `${game.i18n.localize(property)}`).join(\"\")}
`\r\n : \"\";\r\n\r\n const traitsHtml = tooltipData?.traits\r\n ? tooltipData.traits.map(trait => `${game.i18n.localize(trait.label ?? trait)}`).join(\"\")\r\n : \"\";\r\n\r\n const traits2Html = tooltipData?.traits2\r\n ? tooltipData.traits2.map(trait => `${game.i18n.localize(trait.label ?? trait)}`).join(\"\")\r\n : \"\";\r\n\r\n const traitsAltHtml = tooltipData?.traitsAlt\r\n ? tooltipData.traitsAlt.map(trait => `${game.i18n.localize(trait.label)}`).join(\"\")\r\n : \"\";\r\n\r\n const modifiersHtml = tooltipData?.modifiers\r\n ? `
${tooltipData.modifiers.filter(modifier => modifier.enabled).map(modifier => {\r\n const label = game.i18n.localize(modifier.label);\r\n const sign = modifier.modifier >= 0 ? \"+\" : \"\";\r\n const mod = `${sign}${modifier.modifier ?? \"\"}`;\r\n return `${label} ${mod}`;\r\n }).join(\"\")}
`\r\n : \"\";\r\n\r\n const tagsJoined = [rarityHtml, traitsHtml, traits2Html, traitsAltHtml].join(\"\");\r\n\r\n const tagsHtml = (tagsJoined) ? `
${tagsJoined}
` : \"\";\r\n\r\n const headerTags = (tagsHtml || modifiersHtml) ? `
${tagsHtml}${modifiersHtml}
` : \"\";\r\n\r\n if (!description && !tagsHtml && !modifiersHtml) return name;\r\n\r\n return `
${nameHtml}${headerTags}${description}${propertiesHtml}
`;\r\n }\r\n\r\n #getWeaponProperties(weaponProperties) {\r\n if (!weaponProperties) return null;\r\n return Object.entries(weaponProperties)\r\n .filter(([id, selected]) => selected && CONFIG.DND5E.validProperties.weapon.has(id))\r\n .map(([id, _]) => game.i18n.localize(CONFIG.DND5E.itemProperties[id]));\r\n }\r\n };\r\n});\r\n","export let MagicItemActionHandlerExtender = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n MagicItemActionHandlerExtender = class MagicItemActionHandlerExtender extends coreModule.api.ActionHandlerExtender {\r\n constructor(actionHandler) {\r\n super();\r\n this.actionHandler = actionHandler;\r\n this.actor = null;\r\n }\r\n\r\n /**\r\n * Extend the action list\r\n */\r\n async extendActionHandler() {\r\n this.actor = this.actionHandler.actor;\r\n if (!this.actor) return;\r\n\r\n const actor = await MagicItems.actor(this.actor.id);\r\n\r\n if (!actor) return;\r\n\r\n const magicItems = actor.items ?? [];\r\n\r\n if (magicItems.length === 0) return;\r\n\r\n const parentGroupId = \"magic-items\";\r\n const parentGroupType = \"system\";\r\n const parentGroupData = {\r\n id: parentGroupId,\r\n type: parentGroupType\r\n };\r\n\r\n magicItems.forEach(magicItem => {\r\n if (magicItem.attuned && !this._isItemAttuned(magicItem)) return;\r\n if (magicItem.equipped && !this._isItemEquipped(magicItem)) return;\r\n\r\n const groupId = `magic-items_${magicItem.id}`;\r\n const groupName = magicItem.name;\r\n const groupType = \"system-derived\";\r\n const groupInfo1 = `${magicItem.uses}/${magicItem.charges}`;\r\n const groupData = {\r\n id: groupId,\r\n name: groupName,\r\n type: groupType,\r\n info1: groupInfo1\r\n };\r\n\r\n // Add group to HUD\r\n this.actionHandler.addGroup(groupData, parentGroupData);\r\n\r\n const actions = magicItem.ownedEntries.map(entry => {\r\n const effect = entry.item;\r\n const id = effect.id;\r\n const name = effect.name;\r\n const img = coreModule.api.Utils.getImage(effect);\r\n const info1 = effect.consumption;\r\n const info2 = (effect.baseLevel) ? `${coreModule.api.Utils.i18n(\"DND5E.AbbreviationLevel\")} ${effect.baseLevel}` : \"\";\r\n return {\r\n id,\r\n name,\r\n encodedValue,\r\n img,\r\n info1,\r\n info2,\r\n selected: true,\r\n system: { actionType: \"magicItem\", itemId: magicItem.id, effectId: id}\r\n };\r\n });\r\n\r\n // Add actions to action list\r\n this.actionHandler.addActions(actions, groupData);\r\n });\r\n }\r\n\r\n /**\r\n * Whether the magic item is equipped or not\r\n * @param {object} magicItem The item\r\n * @returns {boolean}\r\n */\r\n _isItemEquipped(magicItem) {\r\n return magicItem.item.system.equipped;\r\n }\r\n\r\n /**\r\n * Whether the magic items is attuned or not\r\n * @param {object} magicItem The item\r\n * @returns {boolean}\r\n */\r\n _isItemAttuned(magicItem) {\r\n const attunement = magicItem.item.system.attunment;\r\n const attunementRequired = CONFIG.DND5E.attunementTypes?.REQUIRED ?? 1;\r\n\r\n if (attunement === attunementRequired) return false;\r\n\r\n return true;\r\n }\r\n };\r\n});\r\n","import { CUSTOM_DND5E } from \"./constants.js\";\r\n\r\nexport let RollHandler = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n RollHandler = class RollHandler extends coreModule.api.RollHandler {\r\n /**\r\n * Handle action click\r\n * @override\r\n * @param {object} event\r\n */\r\n async handleActionClick(event) {\r\n const { actionType, actionId } = this.action.system;\r\n\r\n if (!this.actor) {\r\n for (const token of coreModule.api.Utils.getControlledTokens()) {\r\n const actor = token.actor;\r\n await this.handleAction(event, actionType, actor, token, actionId);\r\n }\r\n } else {\r\n await this.handleAction(event, actionType, this.actor, this.token, actionId);\r\n }\r\n }\r\n\r\n /**\r\n * Handle action\r\n * @private\r\n * @param {object} event\r\n * @param {string} actionType\r\n * @param {object} actor\r\n * @param {object} token\r\n * @param {string} actionId\r\n */\r\n async handleAction(event, actionType, actor, token, actionId) {\r\n switch (actionType) {\r\n case \"ability\":\r\n this.rollAbility(event, actor, actionId); break;\r\n case \"check\":\r\n this.rollAbilityTest(event, actor, actionId); break;\r\n case \"save\":\r\n this.rollAbilitySave(event, actor, actionId); break;\r\n case \"condition\":\r\n if (!token) return;\r\n await this.toggleCondition(actor, token, actionId); break;\r\n case \"counter\":\r\n await this.modifyCounter(event, actor); break;\r\n case \"effect\":\r\n await this.toggleEffect(actor, actionId); break;\r\n case \"exhaustion\":\r\n await this.modifyExhaustion(event, actor); break;\r\n case \"feature\":\r\n case \"item\":\r\n case \"spell\":\r\n case \"weapon\":\r\n if (this.isRenderItem()) this.renderItem(actor, actionId);\r\n else this.useItem(event, actor, actionId);\r\n break;\r\n case \"magicItem\":\r\n await this.rollMagicItem(actor, actionId); break;\r\n case \"skill\":\r\n this.rollSkill(event, actor, actionId); break;\r\n case \"utility\":\r\n await this.performUtilityAction(event, actor, token, actionId); break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Modify Counter\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n */\r\n async modifyCounter(event, actor) {\r\n switch (this.action?.system?.counterKey) {\r\n case \"death-saves\":\r\n this.rollDeathSave(event, actor); break;\r\n case \"exhaustion\":\r\n await this.modifyExhaustion(actor); break;\r\n case \"inspiration\":\r\n await this.modifyInspiration(actor); break;\r\n default:\r\n await this.modifyCustomCounter(actor); break;\r\n }\r\n }\r\n\r\n /**\r\n * Modify Exhaustion\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyExhaustion(actor) {\r\n const currentExhaustion = actor.system.attributes.exhaustion;\r\n const newExhaustion = currentExhaustion + (this.isRightClick ? -1 : 1);\r\n if (newExhaustion >= 0 && newExhaustion !== currentExhaustion) {\r\n actor.update({ \"system.attributes.exhaustion\": newExhaustion });\r\n }\r\n }\r\n\r\n /**\r\n * Modify Inspiration\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyInspiration(actor) {\r\n const update = !actor.system.attributes.inspiration;\r\n actor.update({ \"system.attributes.inspiration\": update });\r\n }\r\n\r\n /**\r\n * Modify Custom Counter\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyCustomCounter(actor) {\r\n const { counterKey, counterType } = this.action.system;\r\n\r\n let value = actor.getFlag(CUSTOM_DND5E.ID, counterKey) || {};\r\n\r\n const setFlag = async (key, currentValue, newValue) => {\r\n if (newValue !== currentValue) {\r\n await actor.setFlag(CUSTOM_DND5E.ID, key, newValue);\r\n }\r\n };\r\n\r\n const adjustValue = (key, currentValue = 0, increment = 1) => {\r\n const newValue = this.isRightClick ? Math.max(0, currentValue - increment) : currentValue + increment;\r\n setFlag(key, currentValue, newValue);\r\n };\r\n\r\n switch (counterType) {\r\n case \"checkbox\":\r\n await setFlag(id, !value);\r\n break;\r\n\r\n case \"fraction\":\r\n if (this.isRightClick || (value.max && value.value < value.max) || !value.max) {\r\n adjustValue(`${id}.value`, value.value);\r\n }\r\n break;\r\n\r\n case \"number\":\r\n adjustValue(id, value);\r\n break;\r\n\r\n case \"successFailure\":\r\n value.success = value?.success ?? 0;\r\n value.failure = value?.failure ?? 0;\r\n if (this.isCtrl) {\r\n adjustValue(`${id}.failure`, value.failure);\r\n } else {\r\n adjustValue(`${id}.success`, value.success);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Roll Ability\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbility(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbility(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Ability Save\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbilitySave(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbilitySave(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Ability Test\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbilityTest(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbilityTest(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Death Save\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n */\r\n rollDeathSave(event, actor) {\r\n actor.rollDeathSave({ event });\r\n }\r\n\r\n /**\r\n * Roll Magic Item\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async rollMagicItem(actor) {\r\n const { itemId, effectId } = this.action.system;\r\n\r\n const magicItemActor = await MagicItems.actor(actor.id);\r\n if (!magicItemActor) return;\r\n\r\n // Magicitems module 3.0.0 does not support Item5e#use\r\n magicItemActor.roll(itemId, effectId);\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Roll Skill\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollSkill(event, actor, actionId) {\r\n if (!actor.system?.skills) return;\r\n actor.rollSkill(actionId, { event });\r\n }\r\n\r\n /**\r\n * Use Item\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n useItem(event, actor, actionId) {\r\n const item = coreModule.api.Utils.getItem(actor, actionId);\r\n\r\n if (this.#needsRecharge(item)) {\r\n item.rollRecharge();\r\n } else {\r\n item.use({ event, legacy: false });\r\n }\r\n }\r\n\r\n /**\r\n * Needs Recharge\r\n * @private\r\n * @param {object} item\r\n * @returns {boolean}\r\n */\r\n #needsRecharge(item) {\r\n return (item?.system?.uses?.period === \"recharge\" && !(item?.system?.uses?.value > 0));\r\n }\r\n\r\n /**\r\n * Perform utility action\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {object} token The token\r\n * @param {string} actionId The action id\r\n */\r\n async performUtilityAction(event, actor, token, actionId) {\r\n switch (actionId) {\r\n case \"deathSave\":\r\n this.rollDeathSave(event, actor); break;\r\n case \"endTurn\":\r\n if (!token || game.combat?.current?.tokenId !== token.id) break;\r\n await game.combat?.nextTurn(); break;\r\n case \"initiative\":\r\n await this.rollInitiative(actor); break;\r\n case \"inspiration\":\r\n await this.modifyInspiration(actor); break;\r\n case \"longRest\":\r\n actor.longRest(); break;\r\n case \"shortRest\":\r\n actor.shortRest(); break;\r\n }\r\n\r\n // Update HUD\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Roll Initiative\r\n * @param {object} actor The actor\r\n * @private\r\n */\r\n async rollInitiative(actor) {\r\n if (!actor) return;\r\n await actor.rollInitiative({ createCombatants: true });\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Toggle Condition\r\n * @private\r\n * @param {object} actor The actor\r\n * @param {object} token The token\r\n * @param {string} actionId The action id\r\n */\r\n async toggleCondition(actor, token, actionId) {\r\n if (!token) return;\r\n\r\n const statusEffect = CONFIG.statusEffects.find(statusEffect => statusEffect.id === actionId);\r\n const isConvenient = statusEffect?.flags?.[\"dfreds-convenient-effects\"]?.isConvenient\r\n ?? actionId.startsWith(\"Convenient Effect\");\r\n\r\n if (game.dfreds && isConvenient) {\r\n const effectName = statusEffect.name ?? statusEffect.label;\r\n await game.dfreds.effectInterface.toggleEffect(effectName, { overlay: !!this.isRightClick });\r\n } else {\r\n const condition = this.#findCondition(actionId);\r\n if (!condition) return;\r\n\r\n const effect = this.#findEffect(actor, actionId);\r\n if (effect?.disabled) { await effect.delete(); }\r\n\r\n await actor.toggleStatusEffect(condition.id, { overlay: !!this.isRightClick });\r\n }\r\n\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Find condition\r\n * @private\r\n * @param {string} actionId The action id\r\n * @returns {object} The condition\r\n */\r\n #findCondition(actionId) {\r\n return CONFIG.statusEffects.find(effect => effect.id === actionId);\r\n }\r\n\r\n /**\r\n * Find effect\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n * @returns {object} The effect\r\n */\r\n #findEffect(actor, actionId) {\r\n return actor.effects.find(effect => effect.statuses.every(status => status === actionId));\r\n }\r\n\r\n /**\r\n * Toggle Effect\r\n * @private\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n async toggleEffect(actor, actionId) {\r\n const effect = actor.allApplicableEffects().find(effect => effect.id === actionId);\r\n if (!effect) return;\r\n\r\n if (this.isRightClick && !effect.transfer) {\r\n await effect.delete();\r\n } else {\r\n await effect.update({ disabled: !effect.disabled });\r\n }\r\n\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Handle action hover\r\n * @override\r\n * @param {object} event\r\n */\r\n async handleActionHover(event) {\r\n const types = [\"feature\", \"item\", \"spell\", \"weapon\", \"magicItem\"];\r\n const { actionType, actionId } = this.action.system;\r\n\r\n if (!types.includes(actionType)) return;\r\n\r\n const item = coreModule.api.Utils.getItem(this.actor, actionId);\r\n\r\n if (this.isHover) {\r\n Hooks.call(\"tokenActionHudSystemActionHoverOn\", event, item);\r\n } else {\r\n Hooks.call(\"tokenActionHudSystemActionHoverOff\", event, item);\r\n }\r\n }\r\n };\r\n});\r\n","import { GROUP } from \"./constants.js\";\r\n\r\n/**\r\n * Default categories and groups\r\n */\r\nexport let DEFAULTS = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n const groups = GROUP;\r\n Object.values(groups).forEach(group => {\r\n group.name = coreModule.api.Utils.i18n(group.name);\r\n group.listName = `Group: ${coreModule.api.Utils.i18n(group.name)}`;\r\n });\r\n const groupsArray = Object.values(groups);\r\n DEFAULTS = {\r\n layout: [\r\n {\r\n nestId: \"inventory\",\r\n id: \"inventory\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Inventory\"),\r\n groups: [\r\n { ...groups.weapons, nestId: \"inventory_weapons\" },\r\n { ...groups.equipment, nestId: \"inventory_equipment\" },\r\n { ...groups.consumables, nestId: \"inventory_consumables\" },\r\n { ...groups.tools, nestId: \"inventory_tools\" },\r\n { ...groups.containers, nestId: \"inventory_containers\" },\r\n { ...groups.loot, nestId: \"inventory_loot\" }\r\n ]\r\n },\r\n {\r\n nestId: \"features\",\r\n id: \"features\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Features\"),\r\n groups: [\r\n { ...groups.activeFeatures, nestId: \"features_active-features\" },\r\n { ...groups.passiveFeatures, nestId: \"features_passive-features\" }\r\n ]\r\n },\r\n {\r\n nestId: \"spells\",\r\n id: \"spells\",\r\n name: coreModule.api.Utils.i18n(\"TYPES.Item.spellPl\"),\r\n groups: [\r\n { ...groups.atWillSpells, nestId: \"spells_at-will-spells\" },\r\n { ...groups.innateSpells, nestId: \"spells_innate-spells\" },\r\n { ...groups.pactSpells, nestId: \"spells_pact-spells\" },\r\n { ...groups.cantrips, nestId: \"spells_cantrips\" },\r\n { ...groups._1stLevelSpells, nestId: \"spells_1st-level-spells\" },\r\n { ...groups._2ndLevelSpells, nestId: \"spells_2nd-level-spells\" },\r\n { ...groups._3rdLevelSpells, nestId: \"spells_3rd-level-spells\" },\r\n { ...groups._4thLevelSpells, nestId: \"spells_4th-level-spells\" },\r\n { ...groups._5thLevelSpells, nestId: \"spells_5th-level-spells\" },\r\n { ...groups._6thLevelSpells, nestId: \"spells_6th-level-spells\" },\r\n { ...groups._7thLevelSpells, nestId: \"spells_7th-level-spells\" },\r\n { ...groups._8thLevelSpells, nestId: \"spells_8th-level-spells\" },\r\n { ...groups._9thLevelSpells, nestId: \"spells_9th-level-spells\" }\r\n ]\r\n },\r\n {\r\n nestId: \"attributes\",\r\n id: \"attributes\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Attributes\"),\r\n groups: [\r\n { ...groups.abilities, nestId: \"attributes_abilities\" },\r\n { ...groups.skills, nestId: \"attributes_skills\" }\r\n ]\r\n },\r\n {\r\n nestId: \"effects\",\r\n id: \"effects\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Effects\"),\r\n groups: [\r\n { ...groups.temporaryEffects, nestId: \"effects_temporary-effects\" },\r\n { ...groups.passiveEffects, nestId: \"effects_passive-effects\" },\r\n { ...groups.conditions, nestId: \"effects_conditions\" }\r\n ]\r\n },\r\n {\r\n nestId: \"utility\",\r\n id: \"utility\",\r\n name: coreModule.api.Utils.i18n(\"tokenActionHud.utility\"),\r\n groups: [\r\n { ...groups.combat, nestId: \"utility_combat\" },\r\n { ...groups.token, nestId: \"utility_token\" },\r\n { ...groups.rests, nestId: \"utility_rests\" },\r\n { ...groups.utility, nestId: \"utility_utility\" }\r\n ]\r\n }\r\n ],\r\n groups: groupsArray\r\n };\r\n});\r\n","import { MODULE } from \"./constants.js\";\r\n\r\n/**\r\n *\r\n * @param updateFunc\r\n */\r\nexport function register(updateFunc) {\r\n game.settings.register(MODULE.ID, \"abbreviateSkills\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.abbreviateSkills.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.abbreviateSkills.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showSlowActions\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showSlowActions.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showSlowActions.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"displaySpellInfo\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.displaySpellInfo.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.displaySpellInfo.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnchargedItems\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnchargedItems.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnchargedItems.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnequippedItems\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItems.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItems.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnequippedItemsNpcs\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnpreparedSpells\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnpreparedSpells.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnpreparedSpells.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showItemsWithoutActivationCosts\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n}\r\n","// System Module Imports\r\nimport { ActionHandler } from \"./action-handler.js\";\r\nimport { MagicItemActionHandlerExtender } from \"./magic-items-extender.js\";\r\nimport { RollHandler as Core } from \"./roll-handler.js\";\r\nimport { DEFAULTS } from \"./defaults.js\";\r\nimport * as systemSettings from \"./settings.js\";\r\n\r\nexport let SystemManager = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n SystemManager = class SystemManager extends coreModule.api.SystemManager {\r\n /** @override */\r\n getActionHandler() {\r\n const actionHandler = new ActionHandler();\r\n if (coreModule.api.Utils.isModuleActive(\"magic-items-2\")\r\n || coreModule.api.Utils.isModuleActive(\"magicitems\")) {\r\n actionHandler.addActionHandlerExtender(new MagicItemActionHandlerExtender(actionHandler));\r\n }\r\n return actionHandler;\r\n }\r\n\r\n /** @override */\r\n getAvailableRollHandlers() {\r\n let coreTitle = \"Core D&D5e\";\r\n\r\n if (coreModule.api.Utils.isModuleActive(\"midi-qol\")) {\r\n coreTitle += ` [supports ${coreModule.api.Utils.getModuleTitle(\"midi-qol\")}]`;\r\n }\r\n\r\n const choices = { core: coreTitle };\r\n return choices;\r\n }\r\n\r\n /** @override */\r\n getRollHandler(rollHandlerId) {\r\n let rollHandler;\r\n switch (rollHandlerId) {\r\n case \"core\":\r\n default:\r\n rollHandler = new Core();\r\n break;\r\n }\r\n\r\n return rollHandler;\r\n }\r\n\r\n /** @override */\r\n registerSettings(onChangeFunction) {\r\n systemSettings.register(onChangeFunction);\r\n }\r\n\r\n /** @override */\r\n async registerDefaults() {\r\n const defaults = DEFAULTS;\r\n // If the 'Magic Items' module is active, then add a group for it\r\n if (game.modules.get(\"magicitems\")?.active || game.modules.get(\"magic-items-2\")?.active) {\r\n const name = coreModule.api.Utils.i18n(\"tokenActionHud.dnd5e.magicItems\");\r\n defaults.groups.push(\r\n {\r\n id: \"magic-items\",\r\n name,\r\n listName: `Group: ${name}`,\r\n type: \"system\"\r\n }\r\n );\r\n defaults.groups.sort((a, b) => a.id.localeCompare(b.id));\r\n }\r\n return defaults;\r\n }\r\n };\r\n});\r\n","import { SystemManager } from \"./system-manager.js\";\r\nimport { MODULE, REQUIRED_CORE_MODULE_VERSION } from \"./constants.js\";\r\n\r\nHooks.on(\"tokenActionHudCoreApiReady\", async () => {\r\n const module = game.modules.get(MODULE.ID);\r\n module.api = {\r\n requiredCoreModuleVersion: REQUIRED_CORE_MODULE_VERSION,\r\n SystemManager\r\n };\r\n Hooks.call(\"tokenActionHudSystemReady\", module);\r\n});\r\n"],"names":["MODULE","ID","CORE_MODULE","REQUIRED_CORE_MODULE_VERSION","ACTION_TYPE","ability","check","condition","counter","effect","exhaustion","feature","item","save","skill","spell","utility","ACTIVATION_TYPE","action","group","bonus","icon","crew","day","hour","lair","minute","legendary","reaction","reactiondamage","reactionmanual","special","other","CONCENTRATION_ICON","CUSTOM_DND5E","COUNTERS","character","npc","FEATURE_GROUP_IDS","GROUP","_1stLevelSpells","id","name","spellMode","type","_2ndLevelSpells","_3rdLevelSpells","_4thLevelSpells","_5thLevelSpells","_6thLevelSpells","_7thLevelSpells","_8thLevelSpells","_9thLevelSpells","abilities","actions","activeFeatures","artificerInfusions","atWillSpells","backgroundFeatures","bonusActions","cantrips","channelDivinity","checks","classFeatures","combat","conditions","consumables","containers","counters","crewActions","defensiveTactics","eldritchInvocations","elementalDisciplines","equipment","equipped","feats","fightingStyles","huntersPrey","innateSpells","kiAbilities","lairActions","legendaryActions","loot","maneuvers","metamagicOptions","monsterFeatures","multiattacks","otherActions","pactBoons","pactSpells","passiveEffects","passiveFeatures","psionicPowers","raceFeatures","reactions","rests","runes","saves","skills","superiorHuntersDefense","temporaryEffects","token","tools","unequipped","weapons","PREPARED_ICON","PROFICIENCY_LEVEL_ICON","RARITY","common","uncommon","rare","veryRare","artifact","RITUAL_ICON","SPELL_GROUP_IDS","Utils","Hooks","once","async","capitalize","value","replace","text","charAt","toUpperCase","substring","toLowerCase","getSetting","key","defaultValue","game","settings","get","coreModule","api","Logger","debug","setSetting","set","ActionHandler","featureActions","inventoryActions","spellActions","buildSystemActions","groupIds","this","actors","actor","getValidActors","tokens","getValidTokens","items","sortItemsByName","discardSlowItems","abbreviateSkills","displaySpellInfo","showItemsWithoutActivationCosts","showUnchargedItems","showUnequippedItems","showUnpreparedSpells","activationgroupIds","inventorygroupIds","buildCharacterActions","buildVehicleActions","buildMultipleTokenActions","Promise","all","buildConditions","buildEffects","buildFeatures","buildInventory","buildSpells","buildAbilities","buildCombat","buildCounters","buildExhaustion","buildRests","buildSkills","buildUtility","actionType","groupId","system","CONFIG","DND5E","length","Object","entries","filter","map","abilityId","label","mod","icon1","getProficiencyIcon","proficient","info1","getModifier","title","i18n","localize","info2","listName","getListName","addActions","buildActivations","data","groupData","actionData","activationItems","Map","activationType","activities","contents","activation","has","values","groupDataClone","includes","defaultSelected","parentgroupData","addGroup","addGroupInfo","buildActions","combatType","initiative","current","tokenId","endTurn","getControlledTokens","tokenIds","combatants","combatant","getInfo1","class","cssClass","every","actionId","statusEffects","hasCondition","effects","some","statuses","status","disabled","img","getImage","tooltip","getTooltip","getConditionTooltipData","isModuleActive","keys","_","visible","active","attributes","death","success","failure","getFlag","max","counterKey","counterType","allApplicableEffects","size","statusEffectIds","Set","statusEffect","_id","effectId","isSuppressed","parent","identified","user","isGM","isTemporary","featuresMap","featureType","background","monster","race","classFeatureType","artificerInfusion","defensiveTactic","eldritchInvocation","elementalDiscipline","fightingStyle","ki","maneuver","metamagic","multiattack","pact","psionicPower","rune","subType","subtype","inventoryMap","quantity","isActiveItem","isUsableItem","isEquippedItem","shortRest","longRest","total","error","spells","spellsMap","isUsableSpell","preparation","mode","level","systemSpells","reverse","spellSlotsMap","spellSlotAvailable","pactSlotAvailable","pactSlot","hasValue","hasMax","hasLevel","slotAvailable","startsWith","slotsAvailable","spellSlotModes","levelInfo","slots","info","utilityTypes","deathSave","inspiration","hp","utilityType","options","getAction","entity","hasOwn","getItemInfo","getTooltipData","getActivationTypeIcon","icon2","getPreparedIcon","icon3","getConcentrationIcon","info3","activationTypes","activityActivationTypes","uses","spellPreparationModes","preparationMode","prepared","actionName","getSpellInfo","getQuantityData","getUsesData","getConsumeData","components","properties","componentsArray","vocal","somatic","material","ritual","push","join","allowedTypes","per","recovery","period","limitedUsePeriods","perPeriod","spent","firstActivity","firstTarget","consumption","targets","consumeId","target","consumeType","consumeAmount","parentId","substr","lastIndexOf","foundry","utils","getProperty","slowActivationTypes","proficiencyLevels","abilityActivationTypes","tooltipsSetting","unidentified","description","modifiers","rarity","traits","chatProperties","equippableItemCardProperties","labels","range","duration","p","getWeaponProperties","conditionTypes","journalEntry","fromUuid","reference","content","relativeTo","tooltipData","nameHtml","descriptionLocalised","TextEditor","enrichHTML","secrets","rarityHtml","propertiesHtml","property","traitsHtml","trait","traits2Html","traits2","traitsAltHtml","traitsAlt","modifiersHtml","modifier","enabled","tagsJoined","tagsHtml","weaponProperties","selected","validProperties","weapon","itemProperties","MagicItemActionHandlerExtender","ActionHandlerExtender","constructor","actionHandler","super","extendActionHandler","MagicItems","magicItems","parentGroupData","forEach","magicItem","attuned","_isItemAttuned","_isItemEquipped","charges","ownedEntries","entry","baseLevel","encodedValue","itemId","attunment","attunementTypes","REQUIRED","RollHandler","handleActionClick","event","handleAction","rollAbility","rollAbilityTest","rollAbilitySave","toggleCondition","modifyCounter","toggleEffect","modifyExhaustion","isRenderItem","renderItem","useItem","rollMagicItem","rollSkill","performUtilityAction","rollDeathSave","modifyInspiration","modifyCustomCounter","currentExhaustion","newExhaustion","isRightClick","update","setFlag","currentValue","newValue","adjustValue","increment","Math","isCtrl","magicItemActor","roll","callAll","getItem","needsRecharge","rollRecharge","use","legacy","nextTurn","rollInitiative","createCombatants","find","isConvenient","flags","dfreds","effectName","effectInterface","overlay","findCondition","findEffect","delete","toggleStatusEffect","transfer","handleActionHover","isHover","call","DEFAULTS","register","updateFunc","hint","scope","config","Boolean","default","onChange","groups","groupsArray","layout","nestId","SystemManager","getActionHandler","addActionHandlerExtender","getAvailableRollHandlers","coreTitle","getModuleTitle","core","getRollHandler","rollHandlerId","rollHandler","Core","registerSettings","onChangeFunction","systemSettings.register","registerDefaults","defaults","modules","sort","a","b","localeCompare","on","module","requiredCoreModuleVersion"],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"token-action-hud-dnd5e.min.js","sources":["constants.js","utils.js","action-handler.js","magic-items-extender.js","roll-handler.js","defaults.js","settings.js","system-manager.js","init.js"],"sourcesContent":["/**\r\n * Module-based constants\r\n */\r\nexport const MODULE = {\r\n ID: \"token-action-hud-dnd5e\"\r\n};\r\n\r\n/**\r\n * Core module\r\n */\r\nexport const CORE_MODULE = {\r\n ID: \"token-action-hud-core\"\r\n};\r\n\r\n/**\r\n * Core module version required by the system module\r\n */\r\nexport const REQUIRED_CORE_MODULE_VERSION = \"2.0\";\r\n\r\n/**\r\n * Action type\r\n */\r\nexport const ACTION_TYPE = {\r\n ability: \"DND5E.Ability\",\r\n check: \"tokenActionHud.dnd5e.check\",\r\n condition: \"tokenActionHud.dnd5e.condition\",\r\n counter: \"tokenActionHud.dnd5e.counter\",\r\n effect: \"DND5E.Effect\",\r\n exhaustion: \"DND5E.Exhaustion\",\r\n feature: \"TYPES.Item.feat\",\r\n item: \"tokenActionHud.dnd5e.item\",\r\n save: \"DND5E.SAVE.Title.one\",\r\n skill: \"tokenActionHud.dnd5e.skill\",\r\n spell: \"TYPES.Item.spell\",\r\n utility: \"DND5E.ActionUtil\"\r\n};\r\n\r\n/**\r\n * Activation types\r\n */\r\nexport const ACTIVATION_TYPE = {\r\n action: { group: \"actions\" },\r\n bonus: { group: \"bonus-actions\", icon: \"fas fa-plus\" },\r\n crew: { group: \"crew-actions\", icon: \"fas fa-users\" },\r\n day: { icon: \"fas fa-hourglass-end\" },\r\n hour: { icon: \"fas fa-hourglass-half\" },\r\n lair: { group: \"lair-actions\", icon: \"fas fa-home\" },\r\n minute: { icon: \"fas fa-hourglass-start\" },\r\n legendary: { group: \"legendary-actions\", icon: \"fas fas fa-dragon\" },\r\n reaction: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n reactiondamage: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n reactionmanual: { group: \"reactions\", icon: \"fas fa-bolt\" },\r\n special: { group: \"special-actions\", icon: \"fas fa-star\" },\r\n other: { group: \"other-actions\" }\r\n};\r\n\r\n/**\r\n * Concentration icon\r\n */\r\nexport const CONCENTRATION_ICON = \"systems/dnd5e/icons/svg/statuses/concentrating.svg\";\r\n\r\nexport const CUSTOM_DND5E = {\r\n ID: \"custom-dnd5e\",\r\n COUNTERS: {\r\n character: \"character-counters\",\r\n group: \"group-counters\",\r\n npc: \"npc-counters\"\r\n }\r\n};\r\n\r\n/**\r\n * Feature Group IDs\r\n */\r\nexport const FEATURE_GROUP_IDS = [\r\n \"activeFeatures\",\r\n \"passiveFeatures\",\r\n \"backgroundFeatures\",\r\n \"classFeatures\",\r\n \"feats\",\r\n \"monsterFeatures\",\r\n \"raceFeatures\",\r\n \"artificerInfusions\",\r\n \"channelDivinity\",\r\n \"defensiveTactics\",\r\n \"eldritchInvocations\",\r\n \"elementalDisciplines\",\r\n \"fightingStyles\",\r\n \"huntersPrey\",\r\n \"kiAbilities\",\r\n \"maneuvers\",\r\n \"metamagicOptions\",\r\n \"multiattacks\",\r\n \"pactBoons\",\r\n \"psionicPowers\",\r\n \"runes\",\r\n \"superiorHuntersDefense\"\r\n];\r\n\r\n/**\r\n * Groups\r\n */\r\nexport const GROUP = {\r\n _1stLevelSpells: { id: \"1st-level-spells\", name: \"tokenActionHud.dnd5e.1stLevelSpells\", spellMode: 1, type: \"system\" },\r\n _2ndLevelSpells: { id: \"2nd-level-spells\", name: \"tokenActionHud.dnd5e.2ndLevelSpells\", spellMode: 2, type: \"system\" },\r\n _3rdLevelSpells: { id: \"3rd-level-spells\", name: \"tokenActionHud.dnd5e.3rdLevelSpells\", spellMode: 3, type: \"system\" },\r\n _4thLevelSpells: { id: \"4th-level-spells\", name: \"tokenActionHud.dnd5e.4thLevelSpells\", spellMode: 4, type: \"system\" },\r\n _5thLevelSpells: { id: \"5th-level-spells\", name: \"tokenActionHud.dnd5e.5thLevelSpells\", spellMode: 5, type: \"system\" },\r\n _6thLevelSpells: { id: \"6th-level-spells\", name: \"tokenActionHud.dnd5e.6thLevelSpells\", spellMode: 6, type: \"system\" },\r\n _7thLevelSpells: { id: \"7th-level-spells\", name: \"tokenActionHud.dnd5e.7thLevelSpells\", spellMode: 7, type: \"system\" },\r\n _8thLevelSpells: { id: \"8th-level-spells\", name: \"tokenActionHud.dnd5e.8thLevelSpells\", spellMode: 8, type: \"system\" },\r\n _9thLevelSpells: { id: \"9th-level-spells\", name: \"tokenActionHud.dnd5e.9thLevelSpells\", spellMode: 9, type: \"system\" },\r\n abilities: { id: \"abilities\", name: \"tokenActionHud.dnd5e.abilities\", type: \"system\" },\r\n actions: { id: \"actions\", name: \"DND5E.ActionPl\", type: \"system\" },\r\n activeFeatures: { id: \"active-features\", name: \"tokenActionHud.dnd5e.activeFeatures\", type: \"system\" },\r\n artificerInfusions: { id: \"artificer-infusions\", name: \"tokenActionHud.dnd5e.artificerInfusions\", type: \"system\" },\r\n atWillSpells: { id: \"at-will-spells\", name: \"tokenActionHud.dnd5e.atWillSpells\", spellMode: \"atwill\", type: \"system\" },\r\n backgroundFeatures: { id: \"background-features\", name: \"tokenActionHud.dnd5e.backgroundFeatures\", type: \"system\" },\r\n bonusActions: { id: \"bonus-actions\", name: \"tokenActionHud.dnd5e.bonusActions\", type: \"system\" },\r\n cantrips: { id: \"cantrips\", name: \"tokenActionHud.dnd5e.cantrips\", spellMode: 0, type: \"system\" },\r\n channelDivinity: { id: \"channel-divinity\", name: \"tokenActionHud.dnd5e.channelDivinity\", type: \"system\" },\r\n checks: { id: \"checks\", name: \"tokenActionHud.dnd5e.checks\", type: \"system\" },\r\n classFeatures: { id: \"class-features\", name: \"tokenActionHud.dnd5e.classFeatures\", type: \"system\" },\r\n combat: { id: \"combat\", name: \"tokenActionHud.combat\", type: \"system\" },\r\n conditions: { id: \"conditions\", name: \"tokenActionHud.dnd5e.conditions\", type: \"system\" },\r\n consumables: { id: \"consumables\", name: \"TYPES.Item.consumablePl\", type: \"system\" },\r\n containers: { id: \"containers\", name: \"TYPES.Item.containerPl\", type: \"system\" },\r\n counters: { id: \"counters\", name: \"tokenActionHud.dnd5e.counters\", type: \"system\" },\r\n crewActions: { id: \"crew-actions\", name: \"tokenActionHud.dnd5e.crewActions\", type: \"system\" },\r\n defensiveTactics: { id: \"defensive-tactics\", name: \"tokenActionHud.dnd5e.defensiveTactics\", type: \"system\" },\r\n eldritchInvocations: { id: \"eldritch-invocations\", name: \"tokenActionHud.dnd5e.eldritchInvocations\", type: \"system\" },\r\n elementalDisciplines: { id: \"elemental-disciplines\", name: \"tokenActionHud.dnd5e.elementalDisciplines\", type: \"system\" },\r\n equipment: { id: \"equipment\", name: \"TYPES.Item.equipmentPl\", type: \"system\" },\r\n equipped: { id: \"equipped\", name: \"DND5E.Equipped\", type: \"system\" },\r\n exhaustion: { id: \"exhaustion\", name: \"DND5E.Exhaustion\", type: \"system\" },\r\n feats: { id: \"feats\", name: \"tokenActionHud.dnd5e.feats\", type: \"system\" },\r\n fightingStyles: { id: \"fighting-styles\", name: \"tokenActionHud.dnd5e.fightingStyles\", type: \"system\" },\r\n huntersPrey: { id: \"hunters-prey\", name: \"tokenActionHud.dnd5e.huntersPrey\", type: \"system\" },\r\n innateSpells: { id: \"innate-spells\", name: \"tokenActionHud.dnd5e.innateSpells\", spellMode: \"innate\", type: \"system\" },\r\n kiAbilities: { id: \"ki-abilities\", name: \"tokenActionHud.dnd5e.kiAbilities\", type: \"system\" },\r\n lairActions: { id: \"lair-actions\", name: \"tokenActionHud.dnd5e.lairActions\", type: \"system\" },\r\n legendaryActions: { id: \"legendary-actions\", name: \"tokenActionHud.dnd5e.legendaryActions\", type: \"system\" },\r\n loot: { id: \"loot\", name: \"TYPES.Item.lootPl\", type: \"system\" },\r\n maneuvers: { id: \"maneuvers\", name: \"tokenActionHud.dnd5e.maneuvers\", type: \"system\" },\r\n metamagicOptions: { id: \"metamagic-options\", name: \"tokenActionHud.dnd5e.metamagicOptions\", type: \"system\" },\r\n monsterFeatures: { id: \"monster-features\", name: \"tokenActionHud.dnd5e.monsterFeatures\", type: \"system\" },\r\n multiattacks: { id: \"multiattacks\", name: \"tokenActionHud.dnd5e.multiattacks\", type: \"system\" },\r\n otherActions: { id: \"other-actions\", name: \"tokenActionHud.dnd5e.otherActions\", type: \"system\" },\r\n pactBoons: { id: \"pact-boons\", name: \"tokenActionHud.dnd5e.pactBoons\", type: \"system\" },\r\n pactSpells: { id: \"pact-spells\", name: \"tokenActionHud.dnd5e.pactSpells\", spellMode: \"pact\", type: \"system\" },\r\n passiveEffects: { id: \"passive-effects\", name: \"DND5E.EffectPassive\", type: \"system\" },\r\n passiveFeatures: { id: \"passive-features\", name: \"tokenActionHud.dnd5e.passiveFeatures\", type: \"system\" },\r\n psionicPowers: { id: \"psionic-powers\", name: \"tokenActionHud.dnd5e.psionicPowers\", type: \"system\" },\r\n raceFeatures: { id: \"race-features\", name: \"tokenActionHud.dnd5e.raceFeatures\", type: \"system\" },\r\n reactions: { id: \"reactions\", name: \"DND5E.ReactionPl\", type: \"system\" },\r\n rests: { id: \"rests\", name: \"tokenActionHud.dnd5e.rests\", type: \"system\" },\r\n runes: { id: \"runes\", name: \"tokenActionHud.dnd5e.runes\", type: \"system\" },\r\n saves: { id: \"saves\", name: \"DND5E.ClassSaves\", type: \"system\" },\r\n skills: { id: \"skills\", name: \"tokenActionHud.dnd5e.skills\", type: \"system\" },\r\n superiorHuntersDefense: { id: \"superior-hunters-defense\", name: \"tokenActionHud.dnd5e.superiorHuntersDefense\", type: \"system\" },\r\n temporaryEffects: { id: \"temporary-effects\", name: \"DND5E.EffectTemporary\", type: \"system\" },\r\n token: { id: \"token\", name: \"tokenActionHud.token\", type: \"system\" },\r\n tools: { id: \"tools\", name: \"TYPES.Item.toolPl\", type: \"system\" },\r\n unequipped: { id: \"unequipped\", name: \"DND5E.Unequipped\", type: \"system\" },\r\n utility: { id: \"utility\", name: \"tokenActionHud.utility\", type: \"system\" },\r\n weapons: { id: \"weapons\", name: \"TYPES.Item.weaponPl\", type: \"system\" }\r\n};\r\n\r\n/**\r\n * Prepared icon\r\n */\r\nexport const PREPARED_ICON = \"fas fa-sun\";\r\n\r\n/**\r\n * Proficiency level icons\r\n */\r\nexport const PROFICIENCY_LEVEL_ICON = {\r\n 0: \"fa-regular fa-circle\",\r\n 0.5: \"fa-regular fa-circle-half-stroke\",\r\n 1: \"fa-solid fa-circle\",\r\n 2: \"fa-regular fa-circle-dot\"\r\n};\r\n\r\n/**\r\n * Rarity\r\n */\r\nexport const RARITY = {\r\n common: \"tokenActionHud.dnd5e.common\",\r\n uncommon: \"tokenActionHud.dnd5e.uncommon\",\r\n rare: \"tokenActionHud.dnd5e.rare\",\r\n veryRare: \"tokenActionHud.dnd5e.veryRare\",\r\n legendary: \"tokenActionHud.dnd5e.legendary\",\r\n artifact: \"tokenActionHud.dnd5e.artifact\"\r\n};\r\n\r\n/**\r\n * Ritual icon\r\n */\r\nexport const RITUAL_ICON = \"fas fa-circle-r\";\r\n\r\n/**\r\n * Spell Group IDs\r\n */\r\nexport const SPELL_GROUP_IDS = [\r\n \"cantrips\",\r\n \"_1stLevelSpells\",\r\n \"_2ndLevelSpells\",\r\n \"_3rdLevelSpells\",\r\n \"_4thLevelSpells\",\r\n \"_5thLevelSpells\",\r\n \"_6thLevelSpells\",\r\n \"_7thLevelSpells\",\r\n \"_8thLevelSpells\",\r\n \"_9thLevelSpells\",\r\n \"atWillSpells\",\r\n \"innateSpells\",\r\n \"pactSpells\"\r\n];\r\n","import { MODULE } from \"./constants.js\";\r\n\r\nexport let Utils = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n Utils = class Utils {\r\n /**\r\n * Capitalize the first letter of every word\r\n * @param {string} value The string to capitalize\r\n * @returns {string} The capitalized string\r\n */\r\n static capitalize(value) {\r\n return value.replace(\r\n /\\w\\S*/g,\r\n text => text.charAt(0).toUpperCase() + text.substring(1).toLowerCase()\r\n );\r\n }\r\n\r\n /**\r\n * Get setting value\r\n * @param {string} key The key\r\n * @param {string=null} defaultValue The default value\r\n * @returns {*} The setting value\r\n */\r\n static getSetting(key, defaultValue = null) {\r\n let value = defaultValue ?? null;\r\n try {\r\n value = game.settings.get(MODULE.ID, key);\r\n } catch{\r\n coreModule.api.Logger.debug(`Setting '${key}' not found`);\r\n }\r\n return value;\r\n }\r\n\r\n /**\r\n * Set setting value\r\n * @param {string} key The key\r\n * @param {string} value The value\r\n */\r\n static async setSetting(key, value) {\r\n try {\r\n value = await game.settings.set(MODULE.ID, key, value);\r\n coreModule.api.Logger.debug(`Setting '${key}' set to '${value}'`);\r\n } catch{\r\n coreModule.api.Logger.debug(`Setting '${key}' not found`);\r\n }\r\n }\r\n };\r\n});\r\n","// System Module Imports\r\nimport {\r\n ACTIVATION_TYPE, ACTION_TYPE, CONCENTRATION_ICON, CUSTOM_DND5E, FEATURE_GROUP_IDS,\r\n GROUP, PREPARED_ICON, PROFICIENCY_LEVEL_ICON, RARITY, SPELL_GROUP_IDS\r\n} from \"./constants.js\";\r\nimport { Utils } from \"./utils.js\";\r\n\r\nexport let ActionHandler = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n ActionHandler = class ActionHandler extends coreModule.api.ActionHandler {\r\n // Initialize action variables\r\n featureActions = null;\r\n\r\n inventoryActions = null;\r\n\r\n spellActions = null;\r\n\r\n /**\r\n * Build System Actions\r\n * @override\r\n * @param {Array} groupIds\r\n * @returns {object}\r\n */\r\n async buildSystemActions(groupIds) {\r\n // Set actor and token variables\r\n this.actors = (!this.actor) ? this.#getValidActors() : [this.actor];\r\n this.tokens = (!this.token) ? this.#getValidTokens() : [this.token];\r\n\r\n // Set items variable\r\n if (this.actor) {\r\n this.items = coreModule.api.Utils.sortItemsByName(this.#discardSlowItems(this.actor.items));\r\n }\r\n\r\n // Set settings variables\r\n this.abbreviateSkills = Utils.getSetting(\"abbreviateSkills\");\r\n this.displaySpellInfo = Utils.getSetting(\"displaySpellInfo\");\r\n this.showItemsWithoutActivationCosts = Utils.getSetting(\"showItemsWithoutActivationCosts\");\r\n this.showUnchargedItems = Utils.getSetting(\"showUnchargedItems\");\r\n this.showUnequippedItems = Utils.getSetting(\"showUnequippedItems\");\r\n if (this.actor?.type === \"npc\" && !this.showUnequippedItems) {\r\n this.showUnequippedItems = Utils.getSetting(\"showUnequippedItemsNpcs\");\r\n }\r\n this.showUnpreparedSpells = Utils.getSetting(\"showUnpreparedSpells\");\r\n\r\n this.activationgroupIds = [\r\n \"actions\",\r\n \"bonus-actions\",\r\n \"crew-actions\",\r\n \"lair-actions\",\r\n \"legendary-actions\",\r\n \"reactions\",\r\n \"other-actions\"\r\n ];\r\n\r\n if (this.actor?.type === \"character\" || this.actor?.type === \"npc\") {\r\n this.inventorygroupIds = [\r\n \"equipped\",\r\n \"consumables\",\r\n \"containers\",\r\n \"equipment\",\r\n \"loot\",\r\n \"tools\",\r\n \"weapons\",\r\n \"unequipped\"\r\n ];\r\n\r\n await this.#buildCharacterActions();\r\n } else if (this.actor?.type === \"vehicle\") {\r\n this.inventorygroupIds = [\r\n \"consumables\",\r\n \"equipment\",\r\n \"tools\",\r\n \"weapons\"\r\n ];\r\n\r\n await this.#buildVehicleActions();\r\n } else if (!this.actor) {\r\n await this.#buildMultipleTokenActions();\r\n }\r\n }\r\n\r\n /**\r\n * Build character actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildCharacterActions() {\r\n await Promise.all([\r\n this.#buildConditions(),\r\n this.#buildEffects(),\r\n this.#buildFeatures(),\r\n this.#buildInventory(),\r\n this.#buildSpells()\r\n ]);\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n this.#buildCounters();\r\n this.#buildExhaustion();\r\n this.#buildRests();\r\n this.#buildSkills();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build vehicle actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildVehicleActions() {\r\n await Promise.all([\r\n this.#buildConditions(),\r\n this.#buildEffects(),\r\n this.#buildFeatures(),\r\n this.#buildInventory()\r\n ]);\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build multiple token actions\r\n * @private\r\n * @returns {object}\r\n */\r\n async #buildMultipleTokenActions() {\r\n this.#buildAbilities(\"ability\", \"abilities\");\r\n this.#buildAbilities(\"check\", \"checks\");\r\n this.#buildAbilities(\"save\", \"saves\");\r\n this.#buildCombat();\r\n await this.#buildConditions();\r\n this.#buildRests();\r\n this.#buildSkills();\r\n this.#buildUtility();\r\n }\r\n\r\n /**\r\n * Build abilities\r\n * @private\r\n * @param {string} actionType\r\n * @param {string} groupId\r\n */\r\n #buildAbilities(actionType, groupId) {\r\n // Get abilities and exit if none exist\r\n const abilities = this.actor?.system.abilities || CONFIG.DND5E.abilities;\r\n if (abilities.length === 0) return;\r\n\r\n // Get actions\r\n const actions = Object.entries(abilities)\r\n .filter(ability => abilities[ability[0]].value !== 0)\r\n .map(([abilityId, ability]) => {\r\n const name = CONFIG.DND5E.abilities[abilityId].label;\r\n const mod = (groupId === \"saves\") ? ability?.save : ability?.mod;\r\n return {\r\n id: `${actionType}-${abilityId}`,\r\n name: (this.abbreviateSkills) ? Utils.capitalize(abilityId) : name,\r\n icon1: (groupId !== \"checks\") ? this.#getProficiencyIcon(abilities[abilityId].proficient) : \"\",\r\n info1: (this.actor) ? {\r\n text: coreModule.api.Utils.getModifier(mod),\r\n title: `${game.i18n.localize(\"DND5E.ActionAbil\")}: ${coreModule.api.Utils.getModifier(mod)}`\r\n } : null,\r\n info2: (this.actor && groupId === \"abilities\") ? {\r\n text: `(${coreModule.api.Utils.getModifier(ability?.save)})`,\r\n title: `${game.i18n.localize(\"DND5E.SavingThrow\")}: ${coreModule.api.Utils.getModifier(ability?.save)}`\r\n } : null,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: abilityId }\r\n };\r\n });\r\n\r\n // Add actions to action list\r\n this.addActions(actions, { id: groupId });\r\n }\r\n\r\n /**\r\n * Build activations\r\n * @public\r\n * @param {object} data groupData, actionData, actionType\r\n */\r\n async buildActivations(data) {\r\n const { groupData, actionData, actionType = \"item\" } = data;\r\n\r\n // Create map of items according to activation type\r\n const activationItems = new Map();\r\n\r\n // Loop items and add to activationItems\r\n for (const [key, value] of actionData) {\r\n const activationType = value.system?.activities?.contents[0]?.activation?.type;\r\n const groupId = ACTIVATION_TYPE[activationType]?.group ?? \"other\";\r\n if (!activationItems.has(groupId)) activationItems.set(groupId, new Map());\r\n activationItems.get(groupId).set(key, value);\r\n }\r\n\r\n // Loop through action group ids\r\n for (const value of Object.values(ACTIVATION_TYPE)) {\r\n const group = value.group;\r\n\r\n // Skip if no items exist\r\n if (!activationItems.has(group)) continue;\r\n\r\n // Clone and add to group data\r\n const groupDataClone = { ...groupData, id: `${group}+${groupData.id}`, type: \"system-derived\" };\r\n\r\n // Set Equipped and Unequipped groups to not selected by default\r\n if ([\"equipped\", \"unequipped\"].includes(groupData.id)) { groupDataClone.defaultSelected = false; }\r\n\r\n // Create parent group data\r\n const parentgroupData = { id: group, type: \"system\" };\r\n\r\n // Add group to HUD\r\n await this.addGroup(groupDataClone, parentgroupData);\r\n\r\n // Add spell slot info to group\r\n if (actionType === \"spell\") { this.addGroupInfo(groupDataClone); }\r\n\r\n // Build actions\r\n await this.buildActions({\r\n groupData: groupDataClone,\r\n actionData: activationItems.get(group),\r\n actionType\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * Build combat\r\n * @private\r\n */\r\n #buildCombat() {\r\n // If token's turn, include endTurn\r\n const combatType = {\r\n initiative: \"tokenActionHud.dnd5e.rollInitiative\",\r\n ...(game.combat?.current?.tokenId === this.token?.id && { endTurn: \"tokenActionHud.endTurn\" })\r\n };\r\n\r\n const tokens = coreModule.api.Utils.getControlledTokens();\r\n const tokenIds = tokens?.map(token => token.id);\r\n const combatants = (game.combat)\r\n ? game.combat.combatants.filter(combatant => tokenIds.includes(combatant.tokenId))\r\n : [];\r\n\r\n const getInfo1 = id => {\r\n if (id === \"initiative\" && combatants.length === 1) {\r\n const currentInitiative = combatants[0].initiative;\r\n return { class: \"tah-spotlight\", text: currentInitiative };\r\n }\r\n return {};\r\n };\r\n\r\n const getActive = () => { return combatants.length > 0 && (combatants.every(combatant => combatant?.initiative)) ? \" active\" : \"\";};\r\n\r\n // Get actions\r\n const actionType = \"utility\";\r\n const actions = Object.entries(combatType).map(([id, name]) => {\r\n return {\r\n id,\r\n name: game.i18n.localize(name),\r\n info1: getInfo1(id),\r\n cssClass: (id === \"initiative\" ) ? `toggle${getActive()}` : \"\",\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"combat\" });\r\n }\r\n\r\n /**\r\n * Build conditions\r\n * @private\r\n */\r\n async #buildConditions() {\r\n if (this.tokens?.length === 0) return;\r\n\r\n // Get conditions and exit if none exist\r\n const conditions = CONFIG.statusEffects.filter(condition => condition.id !== \"\");\r\n if (conditions.length === 0) return;\r\n\r\n // Get actions\r\n const actionType = \"condition\";\r\n const actions = await Promise.all(conditions.map(async condition => {\r\n const hasCondition = this.actors.every(actor => {\r\n return actor.effects.some(effect => effect.statuses.some(status => status === condition.id)\r\n && !effect?.disabled);\r\n });\r\n const name = game.i18n.localize(condition.label) ?? condition.name;\r\n return {\r\n id: condition.id,\r\n name,\r\n img: coreModule.api.Utils.getImage(condition),\r\n cssClass: `toggle${(hasCondition) ? \" active\" : \"\"}`,\r\n listName: this.#getListName(actionType, name),\r\n tooltip: await this.#getTooltip(await this.#getConditionTooltipData(condition.id, condition.name)),\r\n system: { actionType, actionId: condition.id }\r\n };\r\n }));\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"conditions\" });\r\n }\r\n\r\n /**\r\n * Build counters\r\n * @private\r\n */\r\n async #buildCounters() {\r\n if (!coreModule.api.Utils.isModuleActive(CUSTOM_DND5E.ID)\r\n || !CUSTOM_DND5E.COUNTERS[this.actor?.type]) return;\r\n\r\n const actionType = \"counter\";\r\n\r\n let counters = game.settings.get(CUSTOM_DND5E.ID, CUSTOM_DND5E.COUNTERS[this.actor?.type]) ?? {};\r\n\r\n if (coreModule.api.Utils.isModuleActive(CUSTOM_DND5E.ID) && Object.keys(counters).length) {\r\n counters = Object.entries(counters)\r\n .filter(([_, value]) => value.visible)\r\n .map(([key, value]) => {\r\n value.key = key;\r\n return value;\r\n });\r\n } else {\r\n counters = [\r\n {\r\n name: game.i18n.localize(\"DND5E.DeathSave\"),\r\n type: \"successFailure\",\r\n system: true,\r\n visible: true,\r\n key: \"death-saves\"\r\n },\r\n {\r\n name: game.i18n.localize(\"DND5E.Exhaustion\"),\r\n type: \"number\",\r\n system: true,\r\n visible: true,\r\n key: \"exhaustion\"\r\n },\r\n {\r\n name: game.i18n.localize(\"DND5E.Inspiration\"),\r\n type: \"checkbox\",\r\n system: true,\r\n visible: true,\r\n key: \"inspiration\"\r\n }\r\n ];\r\n }\r\n\r\n // Get actions\r\n const actions = counters.map(counter => {\r\n let active = \"\";\r\n let cssClass = \"\";\r\n let img = \"\";\r\n let info1 = \"\";\r\n if (counter.system) {\r\n switch (counter.key) {\r\n case \"exhaustion\":\r\n active = (this.actor.system.attributes.exhaustion > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/exhaustion.svg\");\r\n info1 = { text: this.actor.system.attributes.exhaustion };\r\n break;\r\n case \"death-saves\":\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/death-saves.svg\");\r\n info1 = { text: `${this.actor.system.attributes.death.success}/${this.actor.system.attributes.death.failure}` };\r\n break;\r\n case \"inspiration\":\r\n active = (this.actor.system.attributes.inspiration) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n img = coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/inspiration.svg\");\r\n break;\r\n }\r\n } else {\r\n const value = this.actor.getFlag(CUSTOM_DND5E.ID, counter.key);\r\n switch (counter.type) {\r\n case \"checkbox\":\r\n active = (value) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n break;\r\n case \"fraction\":\r\n active = (value.value > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n info1 = { text: `${value.value ?? 0}/${value.max ?? 0}` };\r\n break;\r\n case \"number\":\r\n active = (value > 0) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n info1 = { text: value };\r\n break;\r\n case \"successFailure\":\r\n info1 = { text: `${value?.success ?? 0}/${value?.failure ?? 0}` };\r\n break;\r\n }\r\n }\r\n\r\n return {\r\n id: counter.key,\r\n name: counter.label,\r\n listName: this.#getListName(actionType, counter.name),\r\n cssClass,\r\n img,\r\n info1,\r\n system: { actionType, counterKey: counter.key, counterType: counter.type}\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"counters\" });\r\n }\r\n\r\n /**\r\n * Build effects\r\n * @private\r\n */\r\n async #buildEffects() {\r\n const actionType = \"effect\";\r\n\r\n // Get effects and exit if none exist\r\n const effects = new Map(this.actor.allApplicableEffects().map(effect => [effect.id, effect]));\r\n if (effects.size === 0) return;\r\n\r\n // Map passive and temporary effects to new maps\r\n const passiveEffects = new Map();\r\n const temporaryEffects = new Map();\r\n const statusEffectIds = new Set(CONFIG.statusEffects.map(statusEffect => statusEffect._id));\r\n\r\n // Iterate effects and add to a map based on the isTemporary value\r\n for (const [effectId, effect] of effects.entries()) {\r\n if (effect.isSuppressed) continue;\r\n if (effect.parent?.system?.identified === false && !game.user.isGM) continue;\r\n if (statusEffectIds.has(effect.id)) continue;\r\n\r\n if (effect.isTemporary) { temporaryEffects.set(effectId, effect); }\r\n else { passiveEffects.set(effectId, effect); }\r\n }\r\n\r\n // Build passive and temporary effects\r\n await Promise.all([\r\n this.buildActions({ groupData: { id: \"passive-effects\" }, actionData: passiveEffects, actionType }),\r\n this.buildActions({ groupData: { id: \"temporary-effects\" }, actionData: temporaryEffects, actionType })\r\n ]);\r\n }\r\n\r\n /**\r\n * Build exhaustion\r\n * @private\r\n */\r\n #buildExhaustion() {\r\n // Exit if every actor is not the character type\r\n if (!this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n // Get actions\r\n const actionType = \"exhaustion\";\r\n const active = this.actor.system.attributes.exhaustion > 0 ? \" active\" : \"\";\r\n const actions = [{\r\n id: \"exhaustion\",\r\n name: game.i18n.localize(\"DND5E.Exhaustion\"),\r\n cssClass: `toggle${active}`,\r\n img: coreModule.api.Utils.getImage(\"modules/token-action-hud-dnd5e/icons/exhaustion.svg\"),\r\n info1: { text: this.actor.system.attributes.exhaustion },\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: \"exhaustion\" }\r\n }];\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"exhaustion\" });\r\n }\r\n\r\n /**\r\n * Build features\r\n * @private\r\n */\r\n async #buildFeatures() {\r\n // Filter feats from items and exit if none exist\r\n const feats = new Map([...this.items].filter(([, value]) => value.type === \"feat\"));\r\n if (feats.size === 0) return;\r\n\r\n // Map active and passive features to new maps\r\n const featuresMap = new Map([\r\n [\"activeFeatures\", new Map()],\r\n [\"passiveFeatures\", new Map()]\r\n ]);\r\n\r\n const featureType = {\r\n background: \"backgroundFeatures\",\r\n class: \"classFeatures\",\r\n monster: \"monsterFeatures\",\r\n race: \"raceFeatures\",\r\n feats: \"feats\"\r\n };\r\n\r\n const classFeatureType = {\r\n artificerInfusion: \"artificerInfusions\",\r\n channelDivinity: \"channelDivinity\",\r\n defensiveTactic: \"defensiveTactics\",\r\n eldritchInvocation: \"eldritchInvocations\",\r\n elementalDiscipline: \"elementalDisciplines\",\r\n fightingStyle: \"fightingStyles\",\r\n huntersPrey: \"huntersPrey\",\r\n ki: \"kiAbilities\",\r\n maneuver: \"maneuvers\",\r\n metamagic: \"metamagicOptions\",\r\n multiattack: \"multiattacks\",\r\n pact: \"pactBoons\",\r\n psionicPower: \"psionicPowers\",\r\n rune: \"runes\",\r\n superiorHuntersDefense: \"superiorHuntersDefense\"\r\n };\r\n\r\n for (const [key, value] of feats) {\r\n const activationType = value.system.activities.contents[0]?.type;\r\n const type = value.system.type.value;\r\n const subType = value.system.type?.subtype;\r\n\r\n if (activationType) { featuresMap.get(\"activeFeatures\").set(key, value); }\r\n else { featuresMap.get(\"passiveFeatures\").set(key, value); }\r\n\r\n // Map feature types\r\n if (featureType[type]) {\r\n if (!featuresMap.has(featureType[type])) featuresMap.set(featureType[type], new Map());\r\n featuresMap.get(featureType[type]).set(key, value);\r\n }\r\n\r\n // Map class feature subtypes\r\n if (classFeatureType[subType]) {\r\n if (!featuresMap.has(classFeatureType[subType])) featuresMap.set(classFeatureType[subType], new Map());\r\n featuresMap.get(classFeatureType[subType]).set(key, value);\r\n }\r\n }\r\n\r\n // Loop through inventory groups ids\r\n for (const id of FEATURE_GROUP_IDS) {\r\n const actionData = featuresMap.get(id);\r\n if (!actionData || actionData.size === 0) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: GROUP[id].id,\r\n name: game.i18n.localize(GROUP[id].name) ?? \"\"\r\n };\r\n\r\n // Build actions and activations\r\n const actionType = \"feature\";\r\n await this.buildActions({ groupData, actionData, actionType });\r\n await this.buildActivations({ groupData, actionData, actionType });\r\n }\r\n }\r\n\r\n /**\r\n * Build inventory\r\n * @private\r\n */\r\n async #buildInventory() {\r\n // Exit early if no items exist\r\n if (this.items.size === 0) return;\r\n\r\n // Initialize inventory map categories\r\n const inventoryMap = new Map([\r\n [\"equipped\", new Map()],\r\n [\"unequipped\", new Map()],\r\n [\"consumables\", new Map()],\r\n [\"containers\", new Map()],\r\n [\"equipment\", new Map()],\r\n [\"loot\", new Map()],\r\n [\"tools\", new Map()],\r\n [\"weapons\", new Map()]\r\n ]);\r\n\r\n for (const [key, value] of this.items) {\r\n // Set items into maps\r\n if (value.system?.quantity > 0 && this.#isActiveItem(value)) {\r\n if (value.system.equipped) { inventoryMap.get(\"equipped\").set(key, value); }\r\n else { inventoryMap.get(\"unequipped\").set(key, value); }\r\n\r\n if (this.#isUsableItem(value) && value.type === \"consumable\") inventoryMap.get(\"consumables\").set(key, value);\r\n if (this.#isEquippedItem(value)) {\r\n switch (value.type) {\r\n case \"container\": inventoryMap.get(\"containers\").set(key, value); break;\r\n case \"equipment\": inventoryMap.get(\"equipment\").set(key, value); break;\r\n case \"loot\": inventoryMap.get(\"loot\").set(key, value); break;\r\n case \"tool\": inventoryMap.get(\"tools\").set(key, value); break;\r\n case \"weapon\": inventoryMap.get(\"weapons\").set(key, value); break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Loop through inventory subcateogry ids\r\n for (const groupId of this.inventorygroupIds) {\r\n const actionData = inventoryMap.get(groupId);\r\n if (!actionData || actionData.size === 0) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: groupId,\r\n name: game.i18n.localize(GROUP[groupId].name)\r\n };\r\n\r\n const data = { groupData, actionData };\r\n\r\n // Build actions and activations\r\n await this.buildActions(data);\r\n await this.buildActivations(data);\r\n }\r\n }\r\n\r\n /**\r\n * Build rests\r\n * @private\r\n */\r\n #buildRests() {\r\n // Exit if every actor is not the character type\r\n if (this.actors.length === 0 || !this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n // Get actions\r\n const actionType = \"utility\";\r\n const restTypes = { shortRest: \"DND5E.ShortRest\", longRest: \"DND5E.LongRest\" };\r\n const actions = Object.entries(restTypes).map(([id, name]) => {\r\n name = game.i18n.localize(name);\r\n return {\r\n id,\r\n name,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"rests\" });\r\n }\r\n\r\n /**\r\n * Build skills\r\n * @private\r\n */\r\n #buildSkills() {\r\n // Get skills and exit if none exist\r\n const skills = this.actor?.system.skills || CONFIG.DND5E.skills;\r\n if (skills.length === 0) return;\r\n\r\n // Get actions\r\n const actionType = \"skill\";\r\n const actions = Object.entries(skills).map(([id, skill]) => {\r\n try {\r\n const name = CONFIG.DND5E.skills[id].label;\r\n return {\r\n id,\r\n name: this.abbreviateSkills ? Utils.capitalize(id) : name,\r\n icon1: this.#getProficiencyIcon(skill.value),\r\n info1: (this.actor) ? { text: coreModule.api.Utils.getModifier(skill.total) } : \"\",\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n } catch(error) {\r\n coreModule.api.Logger.error(skill);\r\n return null;\r\n }\r\n }).filter(skill => !!skill);\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, { id: \"skills\" });\r\n }\r\n\r\n /**\r\n * Build spells\r\n */\r\n async #buildSpells() {\r\n // Filter items for spells and exit if none exist\r\n const spells = new Map([...this.items].filter(([, value]) => value.type === \"spell\"));\r\n if (spells.size === 0) return;\r\n\r\n // Initialize spells map categories\r\n const spellsMap = new Map([\r\n [\"atWillSpells\", new Map()],\r\n [\"innateSpells\", new Map()],\r\n [\"pactSpells\", new Map()],\r\n [\"cantrips\", new Map()],\r\n [\"_1stLevelSpells\", new Map()],\r\n [\"_2ndLevelSpells\", new Map()],\r\n [\"_3rdLevelSpells\", new Map()],\r\n [\"_4thLevelSpells\", new Map()],\r\n [\"_5thLevelSpells\", new Map()],\r\n [\"_6thLevelSpells\", new Map()],\r\n [\"_7thLevelSpells\", new Map()],\r\n [\"_8thLevelSpells\", new Map()],\r\n [\"_9thLevelSpells\", new Map()]\r\n ]);\r\n\r\n // Loop through items\r\n for (const [key, value] of spells) {\r\n if (!this.#isUsableItem(value) || !this.#isUsableSpell(value)) continue;\r\n\r\n switch (value.system.preparation.mode) {\r\n case \"atwill\":\r\n spellsMap.get(\"atWillSpells\").set(key, value); break;\r\n case \"innate\":\r\n spellsMap.get(\"innateSpells\").set(key, value); break;\r\n case \"pact\":\r\n spellsMap.get(\"pactSpells\").set(key, value); break;\r\n default: {\r\n switch (value.system.level) {\r\n case 0:\r\n spellsMap.get(\"cantrips\").set(key, value); break;\r\n case 1:\r\n spellsMap.get(\"_1stLevelSpells\").set(key, value); break;\r\n case 2:\r\n spellsMap.get(\"_2ndLevelSpells\").set(key, value); break;\r\n case 3:\r\n spellsMap.get(\"_3rdLevelSpells\").set(key, value); break;\r\n case 4:\r\n spellsMap.get(\"_4thLevelSpells\").set(key, value); break;\r\n case 5:\r\n spellsMap.get(\"_5thLevelSpells\").set(key, value); break;\r\n case 6:\r\n spellsMap.get(\"_6thLevelSpells\").set(key, value); break;\r\n case 7:\r\n spellsMap.get(\"_7thLevelSpells\").set(key, value); break;\r\n case 8:\r\n spellsMap.get(\"_8thLevelSpells\").set(key, value); break;\r\n case 9:\r\n spellsMap.get(\"_9thLevelSpells\").set(key, value); break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Reverse sort spell slots by level\r\n const systemSpells = Object.entries(this.actor.system.spells).reverse();\r\n\r\n // Set spell slot availability\r\n const spellSlotsMap = new Map();\r\n let spellSlotAvailable = this.showUnchargedItems;\r\n let pactSlotAvailable = this.showUnchargedItems;\r\n let pactSlot = null;\r\n\r\n for (const [key, value] of systemSpells) {\r\n const hasValue = value.value > 0;\r\n const hasMax = value.max > 0;\r\n const hasLevel = value.level > 0;\r\n\r\n if (key === \"pact\") {\r\n pactSlotAvailable = pactSlotAvailable || (hasValue && hasMax && hasLevel);\r\n value.slotAvailable = pactSlotAvailable && hasLevel;\r\n pactSlot = [key, value];\r\n } else if (key.startsWith(\"spell\") && key !== \"spell0\") {\r\n spellSlotAvailable = spellSlotAvailable || (hasValue && hasMax);\r\n value.slotAvailable = spellSlotAvailable;\r\n spellSlotsMap.set(key, value);\r\n } else if (hasValue) {\r\n value.slotsAvailable = true;\r\n spellSlotsMap.set(key, value);\r\n }\r\n }\r\n\r\n // Set equivalent spell slot where pact slot is available\r\n if (pactSlot[1].slotAvailable) {\r\n const spellSlot = spellSlotsMap.get(`spell${pactSlot[1].level}`);\r\n spellSlot.slotsAvailable = true;\r\n }\r\n\r\n const spellSlotModes = new Set([1, 2, 3, 4, 5, 6, 7, 8, 9, \"pact\"]);\r\n\r\n for (const id of SPELL_GROUP_IDS) {\r\n // Skip if no spells exist\r\n if (!spellsMap.has(id)) continue;\r\n\r\n const spellMode = GROUP[id].spellMode;\r\n const levelInfo = (spellMode === \"pact\") ? pactSlot[1] : spellSlotsMap.get(`spell${spellMode}`);\r\n const { value: slots = 0, max = 0, slotAvailable = false } = levelInfo || {};\r\n\r\n // Skip if spells require spell slots and none are available\r\n if (!slotAvailable && spellSlotModes.has(spellMode)) continue;\r\n\r\n // Create group data\r\n const groupData = {\r\n id: GROUP[id].id,\r\n name: game.i18n.localize(GROUP[id].name),\r\n info: { info1: { class: \"tah-spotlight\", text: (max > 0) ? `${slots}/${max}` : \"\" } }\r\n };\r\n\r\n // Add spell slot info to group\r\n this.addGroupInfo(groupData);\r\n\r\n const data = { groupData, actionData: spellsMap.get(id), actionType: \"spell\" };\r\n\r\n // Build actions and activations\r\n await this.buildActions(data);\r\n await this.buildActivations(data);\r\n }\r\n }\r\n\r\n /**\r\n * Build utility\r\n * @private\r\n */\r\n #buildUtility() {\r\n // Exit if every actor is not the character type\r\n if (this.actors.length === 0) return;\r\n if (!this.actors.every(actor => actor.type === \"character\")) return;\r\n\r\n const actionType = \"utility\";\r\n\r\n // Set utility types\r\n const utilityTypes = {\r\n deathSave: { name: game.i18n.localize(\"DND5E.DeathSave\") },\r\n inspiration: { name: game.i18n.localize(\"DND5E.Inspiration\") }\r\n };\r\n\r\n // Delete 'deathSave' for multiple tokens\r\n if (!this.actor || this.actor.system.attributes.hp.value > 0) delete utilityTypes.deathSave;\r\n\r\n // Get actions\r\n const actions = Object.entries(utilityTypes)\r\n .map(utilityType => {\r\n const id = utilityType[0];\r\n const name = utilityType[1].name;\r\n let cssClass = \"\";\r\n if (utilityType[0] === \"inspiration\") {\r\n const active = this.actors.every(actor => actor.system.attributes?.inspiration)\r\n ? \" active\"\r\n : \"\";\r\n cssClass = `toggle${active}`;\r\n }\r\n return {\r\n id,\r\n name,\r\n cssClass,\r\n listName: this.#getListName(actionType, name),\r\n system: { actionType, actionId: id }\r\n };\r\n });\r\n\r\n // Crreate group data\r\n const groupData = { id: \"utility\" };\r\n\r\n // Add actions to HUD\r\n this.addActions(actions, groupData);\r\n }\r\n\r\n /**\r\n * Build actions\r\n * @public\r\n * @param {object} data actionData, groupData, actionType\r\n * @param {object} options\r\n */\r\n async buildActions(data, options) {\r\n const { actionData, groupData, actionType } = data;\r\n\r\n // Exit if there is no action data\r\n if (actionData.size === 0) return;\r\n\r\n // Exit if there is no groupId\r\n const groupId = (typeof groupData === \"string\" ? groupData : groupData?.id);\r\n if (!groupId) return;\r\n\r\n // Get actions\r\n const actions = await Promise.all([...actionData].map(async item => await this.#getAction(item[1], actionType)));\r\n\r\n // Add actions to action list\r\n this.addActions(actions, groupData);\r\n }\r\n\r\n /**\r\n * Get action\r\n * @private\r\n * @param {object} entity The entity\r\n * @param {string} actionType The action type\r\n * @returns {object} The action\r\n */\r\n async #getAction(entity, actionType = \"item\") {\r\n const id = entity.id ?? entity._id;\r\n let name = entity?.name ?? entity?.label;\r\n let cssClass = \"\";\r\n if (Object.hasOwn(entity, \"disabled\")) {\r\n const active = (!entity.disabled) ? \" active\" : \"\";\r\n cssClass = `toggle${active}`;\r\n }\r\n const info = this.#getItemInfo(entity);\r\n const tooltip = await this.#getTooltip(await this.#getTooltipData(entity));\r\n return {\r\n id,\r\n name,\r\n cssClass,\r\n img: coreModule.api.Utils.getImage(entity),\r\n icon1: this.#getActivationTypeIcon(entity.system?.activities?.contents[0]?.activation.type),\r\n icon2: this.#getPreparedIcon(entity),\r\n icon3: this.#getConcentrationIcon(entity),\r\n info1: info?.info1,\r\n info2: info?.info2,\r\n info3: info?.info3,\r\n listName: this.#getListName(actionType, name),\r\n tooltip,\r\n system: { actionType, actionId: id }\r\n };\r\n }\r\n\r\n /**\r\n * Is active item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is active\r\n */\r\n #isActiveItem(item) {\r\n if (this.showItemsWithoutActivationCosts) return true;\r\n const activationTypes = new Set(Object.keys(CONFIG.DND5E.activityActivationTypes).filter(activationType => activationType !== \"none\"));\r\n const activationType = item.system?.activities?.contents[0]?.activation?.type;\r\n return activationTypes.has(activationType) || item.type === \"tool\";\r\n }\r\n\r\n /**\r\n * Is equipped item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is equipped\r\n */\r\n #isEquippedItem(item) {\r\n const excludedTypes = [\"consumable\", \"spell\", \"feat\"];\r\n return (this.showUnequippedItems && !excludedTypes.includes(item.type))\r\n || (item.system.equipped && item.type !== \"consumable\");\r\n }\r\n\r\n /**\r\n * Is usable item\r\n * @private\r\n * @param {object} item The item\r\n * @returns {boolean} Whether the item is usable\r\n */\r\n #isUsableItem(item) {\r\n return this.showUnchargedItems || !!item.system.uses?.value || !item.system.uses?.max;\r\n }\r\n\r\n /**\r\n * Is usable spell\r\n * @private\r\n * @param {object} spell The spell\r\n * @returns {boolean} Whether the spell is usable\r\n */\r\n #isUsableSpell(spell) {\r\n if (this.actor?.type !== \"character\" && this.showUnequippedItems) return true;\r\n if (this.showUnpreparedSpells) return true;\r\n\r\n const preparationModes = new Set(Object.keys(CONFIG.DND5E.spellPreparationModes).filter(preparationMode => preparationMode !== \"prepared\"));\r\n\r\n // Return true if the spell has a preparation mode other than 'prepared' or is prepared\r\n return preparationModes.has(spell.system.preparation.mode) || spell.system.preparation.prepared;\r\n }\r\n\r\n #getListName(actionType, actionName) {\r\n const prefix = `${game.i18n.localize(ACTION_TYPE[actionType])}: ` ?? \"\";\r\n return `${prefix}${actionName}` ?? \"\";\r\n }\r\n\r\n /**\r\n * Get item info\r\n * @private\r\n * @param {object} item\r\n * @returns {object}\r\n */\r\n #getItemInfo(item) {\r\n const info1 = item.type === \"spell\" ? this.#getSpellInfo(item) : this.#getQuantityData(item);\r\n const info2 = this.#getUsesData(item);\r\n const info3 = this.#getConsumeData(item);\r\n\r\n return { info1, info2, info3 };\r\n }\r\n\r\n /**\r\n * Add spell info\r\n * @private\r\n * @param {object} spell The spell\r\n * @returns {object} The spell info\r\n */\r\n #getSpellInfo(spell) {\r\n if (!this.displaySpellInfo) return null;\r\n\r\n const components = spell.system?.properties;\r\n if (!components) return null;\r\n\r\n const info = { text: \"\", title: \"\" };\r\n const componentTypes = {\r\n vocal: \"DND5E.ComponentVerbal\",\r\n somatic: \"DND5E.ComponentSomatic\",\r\n material: \"DND5E.ComponentMaterial\"\r\n };\r\n\r\n\r\n const componentsArray = Object.entries(componentTypes)\r\n .filter(([key]) => components[key])\r\n .map(([key, label]) => {\r\n info.text += game.i18n.localize(`${label}Abbr`);\r\n return game.i18n.localize(label);\r\n });\r\n\r\n // Ritual\r\n if (components.ritual) {\r\n componentsArray.push(`[${game.i18n.localize(\"DND5E.Ritual\")}]`);\r\n info.text += ` [${game.i18n.localize(\"DND5E.RitualAbbr\")}]`;\r\n }\r\n\r\n info.title = componentsArray.join(\", \");\r\n\r\n return info;\r\n }\r\n\r\n /**\r\n * Get valid actors\r\n * @private\r\n * @returns {object}\r\n */\r\n #getValidActors() {\r\n const allowedTypes = [\"character\", \"npc\"];\r\n return this.actors.every(actor => allowedTypes.includes(actor.type)) ? this.actors : [];\r\n }\r\n\r\n /**\r\n * Get valid tokens\r\n * @private\r\n * @returns {object}\r\n */\r\n #getValidTokens() {\r\n const allowedTypes = [\"character\", \"npc\"];\r\n return this.actors.every(actor => allowedTypes.includes(actor.type)) ? this.tokens : [];\r\n }\r\n\r\n /**\r\n * Get quantity\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getQuantityData(item) {\r\n const quantity = item?.system?.quantity ?? 0;\r\n return {\r\n text: (quantity > 1) ? quantity : \"\",\r\n title: `${game.i18n.localize(\"DND5E.Quantity\")}: ${quantity}`\r\n };\r\n }\r\n\r\n /**\r\n * Get uses\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getUsesData(item) {\r\n const uses = item?.system?.uses;\r\n if (!(uses?.max > 0)) return {};\r\n const per = uses.recovery[0]?.period === \"charges\" ? \"\" : ` ${game.i18n.localize(\"DND5E.per\")} `;\r\n const period = CONFIG.DND5E.limitedUsePeriods[uses.recovery[0]?.period]?.label ?? uses.recovery[0]?.period;\r\n const perPeriod = (period) ? `${per}${period}` : \"\";\r\n const remainingUses = uses.max - (uses.spent ?? 0);\r\n const text = `${remainingUses}/${uses.max}`;\r\n const title = `${text}${perPeriod}`;\r\n return { text, title };\r\n }\r\n\r\n /**\r\n * Get consume\r\n * @private\r\n * @param {object} item\r\n * @returns {string}\r\n */\r\n #getConsumeData(item) {\r\n // Get consume target and type\r\n const firstActivity = item?.system?.activities?.contents[0];\r\n const firstTarget = firstActivity?.consumption?.targets?.[0];\r\n const consumeId = firstTarget?.target;\r\n const consumeType = firstTarget?.type;\r\n const consumeAmount = firstTarget?.value;\r\n\r\n if (!consumeId || !consumeType || consumeId === item.id) return {};\r\n\r\n // Return resources\r\n if (consumeType === \"attribute\") {\r\n const parentId = consumeId.substr(0, consumeId.lastIndexOf(\".\"));\r\n const target = foundry.utils.getProperty(this.actor.system, parentId);\r\n\r\n if (target) {\r\n const text = `${target.value ?? \"0\"}${target.max ? `/${target.max}` : \"\"}`;\r\n return {\r\n text,\r\n title: `${text} ${target.label ?? \"\"}`\r\n };\r\n }\r\n } else {\r\n const target = this.actor.items?.get(consumeId);\r\n\r\n // Return charges\r\n if (target && consumeType === \"charges\") {\r\n return this.#getUsesData(target);\r\n }\r\n\r\n // Return quantity\r\n if (target?.system?.quantity) {\r\n const text = `${consumeAmount > 1 ? `${consumeAmount} ${game.i18n.localize(\"DND5E.of\")} ` : \"\"}${target.system.quantity}`;\r\n return {\r\n text,\r\n title: `${text} ${target.name}`\r\n };\r\n }\r\n }\r\n\r\n return {};\r\n }\r\n\r\n /**\r\n * Discard slow items\r\n * @private\r\n * @param {Map} items The items\r\n * @returns {Map} The filtered items\r\n */\r\n #discardSlowItems(items) {\r\n // Return all items if slow actions are allowed\r\n if (Utils.getSetting(\"showSlowActions\")) return items;\r\n\r\n // Define slow activation types\r\n const slowActivationTypes = new Set([\"minute\", \"hour\", \"day\"]);\r\n\r\n // Filter out slow items and return the result\r\n return new Map([...items.entries()].filter(([_, item]) => {\r\n const activationType = item.system?.activation?.type;\r\n return !slowActivationTypes.has(activationType);\r\n }));\r\n }\r\n\r\n /**\r\n * Get proficiency icon\r\n * @param {string} level\r\n * @returns {string}\r\n */\r\n #getProficiencyIcon(level) {\r\n const title = CONFIG.DND5E.proficiencyLevels[level] ?? \"\";\r\n const icon = PROFICIENCY_LEVEL_ICON[level];\r\n return (icon) ? `` : \"\";\r\n }\r\n\r\n /**\r\n * Get icon for the activation type\r\n * @private\r\n * @param {object} activationType The activation type\r\n * @returns {string} The icon\r\n */\r\n #getActivationTypeIcon(activationType) {\r\n const title = CONFIG.DND5E.abilityActivationTypes[activationType] ?? \"\";\r\n const icon = ACTIVATION_TYPE[activationType]?.icon;\r\n return (icon) ? `` : \"\";\r\n }\r\n\r\n /**\r\n * Get icon for concentration type\r\n * @private\r\n * @param {object} spell\r\n * @returns {string}\r\n */\r\n #getConcentrationIcon(spell) {\r\n if (spell?.type !== \"spell\" || !this.displaySpellInfo || !spell.system?.properties?.has(\"concentration\")) return null;\r\n const title = game.i18n.localize(\"DND5E.Scroll.RequiresConcentration\");\r\n const icon = CONCENTRATION_ICON;\r\n return ``;\r\n }\r\n\r\n /**\r\n * Get icon for a prepared spell\r\n * @private\r\n * @param {object} spell\r\n * @returns\r\n */\r\n #getPreparedIcon(spell) {\r\n if (spell?.type !== \"spell\" || !this.showUnpreparedSpells) return null;\r\n const level = spell.system.level;\r\n const preparationMode = spell.system.preparation.mode;\r\n const prepared = spell.system.preparation.prepared;\r\n const icon = prepared ? PREPARED_ICON : `${PREPARED_ICON} tah-icon-disabled`;\r\n const title = preparationMode === \"always\" ? game.i18n.localize(\"DND5E.SpellPrepAlways\") : prepared ? game.i18n.localize(\"DND5E.SpellPrepared\") : game.i18n.localize(\"DND5E.SpellUnprepared\");\r\n\r\n // Return icon if the preparation mode is 'prepared' or 'always' and the spell is not a cantrip\r\n return ((preparationMode === \"prepared\" || preparationMode === \"always\") && level !== 0) ? `` : null;\r\n }\r\n\r\n async #getTooltipData(entity) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n\r\n const name = entity?.name ?? \"\";\r\n\r\n if (this.tooltipsSetting === \"nameOnly\") return name;\r\n\r\n const unidentified = entity.system?.identified === false;\r\n const description = (typeof entity?.system?.description === \"string\") ? entity?.system?.description : (unidentified ? entity?.system?.unidentified?.description : entity?.system?.description?.value) ?? \"\";\r\n let modifiers; let properties; let rarity; let traits;\r\n if (!unidentified) {\r\n modifiers = entity?.modifiers ?? null;\r\n properties = [\r\n ...entity.system?.chatProperties ?? [],\r\n ...entity.system?.equippableItemCardProperties ?? [],\r\n entity.system?.parent?.labels?.activation,\r\n entity.system?.parent?.labels?.target,\r\n entity.system?.parent?.labels?.range,\r\n entity.system?.parent?.labels?.duration\r\n ].filter(p => p);\r\n rarity = unidentified ? null : entity?.rarity ?? null;\r\n traits = (entity?.type === \"weapon\") ? this.#getWeaponProperties(entity?.system?.properties) : null;\r\n }\r\n return { name, description, modifiers, properties, rarity, traits };\r\n }\r\n\r\n /**\r\n * Get condition tooltip data\r\n * @param {*} id The condition id\r\n * @param {*} name The condition name\r\n * @returns {object} The tooltip data\r\n */\r\n async #getConditionTooltipData(id, name) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n\r\n const condition = CONFIG.DND5E.conditionTypes[id];\r\n\r\n if (this.tooltipsSetting === \"nameOnly\" || !condition) return name;\r\n\r\n const journalEntry = (condition.reference) ? await fromUuid(condition.reference) : null;\r\n const description = journalEntry?.text?.content ?? \"\";\r\n const relativeTo = journalEntry;\r\n return {\r\n name,\r\n description,\r\n relativeTo\r\n };\r\n }\r\n\r\n /**\r\n * Get tooltip\r\n * @param {object} tooltipData The tooltip data\r\n * @returns {string} The tooltip\r\n */\r\n async #getTooltip(tooltipData) {\r\n if (this.tooltipsSetting === \"none\") return \"\";\r\n if (typeof tooltipData === \"string\") return tooltipData;\r\n\r\n const name = game.i18n.localize(tooltipData.name);\r\n\r\n if (this.tooltipsSetting === \"nameOnly\") return name;\r\n\r\n const nameHtml = `

${name}

`;\r\n\r\n const relativeTo = tooltipData.relativeTo ?? this.actor;\r\n\r\n const description = tooltipData?.descriptionLocalised\r\n ?? await TextEditor.enrichHTML(game.i18n.localize(tooltipData?.description ?? \"\"), { async: true, relativeTo, secrets: true });\r\n\r\n const rarityHtml = tooltipData?.rarity\r\n ? `${game.i18n.localize(RARITY[tooltipData.rarity])}`\r\n : \"\";\r\n\r\n const propertiesHtml = tooltipData?.properties\r\n ? `
${tooltipData.properties.map(property => `${game.i18n.localize(property)}`).join(\"\")}
`\r\n : \"\";\r\n\r\n const traitsHtml = tooltipData?.traits\r\n ? tooltipData.traits.map(trait => `${game.i18n.localize(trait.label ?? trait)}`).join(\"\")\r\n : \"\";\r\n\r\n const traits2Html = tooltipData?.traits2\r\n ? tooltipData.traits2.map(trait => `${game.i18n.localize(trait.label ?? trait)}`).join(\"\")\r\n : \"\";\r\n\r\n const traitsAltHtml = tooltipData?.traitsAlt\r\n ? tooltipData.traitsAlt.map(trait => `${game.i18n.localize(trait.label)}`).join(\"\")\r\n : \"\";\r\n\r\n const modifiersHtml = tooltipData?.modifiers\r\n ? `
${tooltipData.modifiers.filter(modifier => modifier.enabled).map(modifier => {\r\n const label = game.i18n.localize(modifier.label);\r\n const sign = modifier.modifier >= 0 ? \"+\" : \"\";\r\n const mod = `${sign}${modifier.modifier ?? \"\"}`;\r\n return `${label} ${mod}`;\r\n }).join(\"\")}
`\r\n : \"\";\r\n\r\n const tagsJoined = [rarityHtml, traitsHtml, traits2Html, traitsAltHtml].join(\"\");\r\n\r\n const tagsHtml = (tagsJoined) ? `
${tagsJoined}
` : \"\";\r\n\r\n const headerTags = (tagsHtml || modifiersHtml) ? `
${tagsHtml}${modifiersHtml}
` : \"\";\r\n\r\n if (!description && !tagsHtml && !modifiersHtml) return name;\r\n\r\n return `
${nameHtml}${headerTags}${description}${propertiesHtml}
`;\r\n }\r\n\r\n #getWeaponProperties(weaponProperties) {\r\n if (!weaponProperties) return null;\r\n return Object.entries(weaponProperties)\r\n .filter(([id, selected]) => selected && CONFIG.DND5E.validProperties.weapon.has(id))\r\n .map(([id, _]) => game.i18n.localize(CONFIG.DND5E.itemProperties[id]));\r\n }\r\n };\r\n});\r\n","export let MagicItemActionHandlerExtender = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n MagicItemActionHandlerExtender = class MagicItemActionHandlerExtender extends coreModule.api.ActionHandlerExtender {\r\n constructor(actionHandler) {\r\n super();\r\n this.actionHandler = actionHandler;\r\n this.actor = null;\r\n }\r\n\r\n /**\r\n * Extend the action list\r\n */\r\n async extendActionHandler() {\r\n this.actor = this.actionHandler.actor;\r\n if (!this.actor) return;\r\n\r\n const actor = await MagicItems.actor(this.actor.id);\r\n\r\n if (!actor) return;\r\n\r\n const magicItems = actor.items ?? [];\r\n\r\n if (magicItems.length === 0) return;\r\n\r\n const parentGroupId = \"magic-items\";\r\n const parentGroupType = \"system\";\r\n const parentGroupData = {\r\n id: parentGroupId,\r\n type: parentGroupType\r\n };\r\n\r\n magicItems.forEach(magicItem => {\r\n if (magicItem.attuned && !this._isItemAttuned(magicItem)) return;\r\n if (magicItem.equipped && !this._isItemEquipped(magicItem)) return;\r\n\r\n const groupId = `magic-items_${magicItem.id}`;\r\n const groupName = magicItem.name;\r\n const groupType = \"system-derived\";\r\n const groupInfo1 = `${magicItem.uses}/${magicItem.charges}`;\r\n const groupData = {\r\n id: groupId,\r\n name: groupName,\r\n type: groupType,\r\n info1: groupInfo1\r\n };\r\n\r\n // Add group to HUD\r\n this.actionHandler.addGroup(groupData, parentGroupData);\r\n\r\n const actions = magicItem.ownedEntries.map(entry => {\r\n const effect = entry.item;\r\n const id = effect.id;\r\n const name = effect.name;\r\n const img = coreModule.api.Utils.getImage(effect);\r\n const info1 = effect.consumption;\r\n const info2 = (effect.baseLevel) ? `${coreModule.api.Utils.i18n(\"DND5E.AbbreviationLevel\")} ${effect.baseLevel}` : \"\";\r\n return {\r\n id,\r\n name,\r\n encodedValue,\r\n img,\r\n info1,\r\n info2,\r\n selected: true,\r\n system: { actionType: \"magicItem\", itemId: magicItem.id, effectId: id}\r\n };\r\n });\r\n\r\n // Add actions to action list\r\n this.actionHandler.addActions(actions, groupData);\r\n });\r\n }\r\n\r\n /**\r\n * Whether the magic item is equipped or not\r\n * @param {object} magicItem The item\r\n * @returns {boolean}\r\n */\r\n _isItemEquipped(magicItem) {\r\n return magicItem.item.system.equipped;\r\n }\r\n\r\n /**\r\n * Whether the magic items is attuned or not\r\n * @param {object} magicItem The item\r\n * @returns {boolean}\r\n */\r\n _isItemAttuned(magicItem) {\r\n const attunement = magicItem.item.system.attunment;\r\n const attunementRequired = CONFIG.DND5E.attunementTypes?.REQUIRED ?? 1;\r\n\r\n if (attunement === attunementRequired) return false;\r\n\r\n return true;\r\n }\r\n };\r\n});\r\n","import { CUSTOM_DND5E } from \"./constants.js\";\r\n\r\nexport let RollHandler = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n RollHandler = class RollHandler extends coreModule.api.RollHandler {\r\n /**\r\n * Handle action click\r\n * @override\r\n * @param {object} event\r\n */\r\n async handleActionClick(event) {\r\n const { actionType, actionId } = this.action.system;\r\n\r\n if (!this.actor) {\r\n for (const token of coreModule.api.Utils.getControlledTokens()) {\r\n const actor = token.actor;\r\n await this.handleAction(event, actionType, actor, token, actionId);\r\n }\r\n } else {\r\n await this.handleAction(event, actionType, this.actor, this.token, actionId);\r\n }\r\n }\r\n\r\n /**\r\n * Handle action\r\n * @private\r\n * @param {object} event\r\n * @param {string} actionType\r\n * @param {object} actor\r\n * @param {object} token\r\n * @param {string} actionId\r\n */\r\n async handleAction(event, actionType, actor, token, actionId) {\r\n switch (actionType) {\r\n case \"ability\":\r\n this.rollAbility(event, actor, actionId); break;\r\n case \"check\":\r\n this.rollAbilityTest(event, actor, actionId); break;\r\n case \"save\":\r\n this.rollAbilitySave(event, actor, actionId); break;\r\n case \"condition\":\r\n if (!token) return;\r\n await this.toggleCondition(actor, token, actionId); break;\r\n case \"counter\":\r\n await this.modifyCounter(event, actor); break;\r\n case \"effect\":\r\n await this.toggleEffect(actor, actionId); break;\r\n case \"exhaustion\":\r\n await this.modifyExhaustion(event, actor); break;\r\n case \"feature\":\r\n case \"item\":\r\n case \"spell\":\r\n case \"weapon\":\r\n if (this.isRenderItem()) this.renderItem(actor, actionId);\r\n else this.useItem(event, actor, actionId);\r\n break;\r\n case \"magicItem\":\r\n await this.rollMagicItem(actor, actionId); break;\r\n case \"skill\":\r\n this.rollSkill(event, actor, actionId); break;\r\n case \"utility\":\r\n await this.performUtilityAction(event, actor, token, actionId); break;\r\n default:\r\n break;\r\n }\r\n }\r\n\r\n /**\r\n * Modify Counter\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n */\r\n async modifyCounter(event, actor) {\r\n switch (this.action?.system?.counterKey) {\r\n case \"death-saves\":\r\n this.rollDeathSave(event, actor); break;\r\n case \"exhaustion\":\r\n await this.modifyExhaustion(actor); break;\r\n case \"inspiration\":\r\n await this.modifyInspiration(actor); break;\r\n default:\r\n await this.modifyCustomCounter(actor); break;\r\n }\r\n }\r\n\r\n /**\r\n * Modify Exhaustion\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyExhaustion(actor) {\r\n const currentExhaustion = actor.system.attributes.exhaustion;\r\n const newExhaustion = currentExhaustion + (this.isRightClick ? -1 : 1);\r\n if (newExhaustion >= 0 && newExhaustion !== currentExhaustion) {\r\n actor.update({ \"system.attributes.exhaustion\": newExhaustion });\r\n }\r\n }\r\n\r\n /**\r\n * Modify Inspiration\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyInspiration(actor) {\r\n const update = !actor.system.attributes.inspiration;\r\n actor.update({ \"system.attributes.inspiration\": update });\r\n }\r\n\r\n /**\r\n * Modify Custom Counter\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async modifyCustomCounter(actor) {\r\n const { counterKey, counterType } = this.action.system;\r\n\r\n let value = actor.getFlag(CUSTOM_DND5E.ID, counterKey) || {};\r\n\r\n const setFlag = async (key, currentValue, newValue) => {\r\n if (newValue !== currentValue) {\r\n await actor.setFlag(CUSTOM_DND5E.ID, key, newValue);\r\n }\r\n };\r\n\r\n const adjustValue = (key, currentValue = 0, increment = 1) => {\r\n const newValue = this.isRightClick ? Math.max(0, currentValue - increment) : currentValue + increment;\r\n setFlag(key, currentValue, newValue);\r\n };\r\n\r\n switch (counterType) {\r\n case \"checkbox\":\r\n await setFlag(id, !value);\r\n break;\r\n\r\n case \"fraction\":\r\n if (this.isRightClick || (value.max && value.value < value.max) || !value.max) {\r\n adjustValue(`${id}.value`, value.value);\r\n }\r\n break;\r\n\r\n case \"number\":\r\n adjustValue(id, value);\r\n break;\r\n\r\n case \"successFailure\":\r\n value.success = value?.success ?? 0;\r\n value.failure = value?.failure ?? 0;\r\n if (this.isCtrl) {\r\n adjustValue(`${id}.failure`, value.failure);\r\n } else {\r\n adjustValue(`${id}.success`, value.success);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Roll Ability\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbility(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbility(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Ability Save\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbilitySave(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbilitySave(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Ability Test\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollAbilityTest(event, actor, actionId) {\r\n if (!actor.system?.abilities) return;\r\n actor.rollAbilityTest(actionId, { event });\r\n }\r\n\r\n /**\r\n * Roll Death Save\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n */\r\n rollDeathSave(event, actor) {\r\n actor.rollDeathSave({ event });\r\n }\r\n\r\n /**\r\n * Roll Magic Item\r\n * @private\r\n * @param {object} actor The actor\r\n */\r\n async rollMagicItem(actor) {\r\n const { itemId, effectId } = this.action.system;\r\n\r\n const magicItemActor = await MagicItems.actor(actor.id);\r\n if (!magicItemActor) return;\r\n\r\n // Magicitems module 3.0.0 does not support Item5e#use\r\n magicItemActor.roll(itemId, effectId);\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Roll Skill\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n rollSkill(event, actor, actionId) {\r\n if (!actor.system?.skills) return;\r\n actor.rollSkill(actionId, { event });\r\n }\r\n\r\n /**\r\n * Use Item\r\n * @private\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n useItem(event, actor, actionId) {\r\n const item = coreModule.api.Utils.getItem(actor, actionId);\r\n\r\n if (this.#needsRecharge(item)) {\r\n item.rollRecharge();\r\n } else {\r\n item.use({ event, legacy: false });\r\n }\r\n }\r\n\r\n /**\r\n * Needs Recharge\r\n * @private\r\n * @param {object} item\r\n * @returns {boolean}\r\n */\r\n #needsRecharge(item) {\r\n return (item?.system?.uses?.period === \"recharge\" && !(item?.system?.uses?.value > 0));\r\n }\r\n\r\n /**\r\n * Perform utility action\r\n * @param {object} event The event\r\n * @param {object} actor The actor\r\n * @param {object} token The token\r\n * @param {string} actionId The action id\r\n */\r\n async performUtilityAction(event, actor, token, actionId) {\r\n switch (actionId) {\r\n case \"deathSave\":\r\n this.rollDeathSave(event, actor); break;\r\n case \"endTurn\":\r\n if (!token || game.combat?.current?.tokenId !== token.id) break;\r\n await game.combat?.nextTurn(); break;\r\n case \"initiative\":\r\n await this.rollInitiative(actor); break;\r\n case \"inspiration\":\r\n await this.modifyInspiration(actor); break;\r\n case \"longRest\":\r\n actor.longRest(); break;\r\n case \"shortRest\":\r\n actor.shortRest(); break;\r\n }\r\n\r\n // Update HUD\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Roll Initiative\r\n * @param {object} actor The actor\r\n * @private\r\n */\r\n async rollInitiative(actor) {\r\n if (!actor) return;\r\n await actor.rollInitiative({ createCombatants: true });\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Toggle Condition\r\n * @private\r\n * @param {object} actor The actor\r\n * @param {object} token The token\r\n * @param {string} actionId The action id\r\n */\r\n async toggleCondition(actor, token, actionId) {\r\n if (!token) return;\r\n\r\n const statusEffect = CONFIG.statusEffects.find(statusEffect => statusEffect.id === actionId);\r\n const isConvenient = statusEffect?.flags?.[\"dfreds-convenient-effects\"]?.isConvenient\r\n ?? actionId.startsWith(\"Convenient Effect\");\r\n\r\n if (game.dfreds && isConvenient) {\r\n const effectName = statusEffect.name ?? statusEffect.label;\r\n await game.dfreds.effectInterface.toggleEffect(effectName, { overlay: !!this.isRightClick });\r\n } else {\r\n const condition = this.#findCondition(actionId);\r\n if (!condition) return;\r\n\r\n const effect = this.#findEffect(actor, actionId);\r\n if (effect?.disabled) { await effect.delete(); }\r\n\r\n await actor.toggleStatusEffect(condition.id, { overlay: !!this.isRightClick });\r\n }\r\n\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Find condition\r\n * @private\r\n * @param {string} actionId The action id\r\n * @returns {object} The condition\r\n */\r\n #findCondition(actionId) {\r\n return CONFIG.statusEffects.find(effect => effect.id === actionId);\r\n }\r\n\r\n /**\r\n * Find effect\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n * @returns {object} The effect\r\n */\r\n #findEffect(actor, actionId) {\r\n return actor.effects.find(effect => effect.statuses.every(status => status === actionId));\r\n }\r\n\r\n /**\r\n * Toggle Effect\r\n * @private\r\n * @param {object} actor The actor\r\n * @param {string} actionId The action id\r\n */\r\n async toggleEffect(actor, actionId) {\r\n const effect = actor.allApplicableEffects().find(effect => effect.id === actionId);\r\n if (!effect) return;\r\n\r\n if (this.isRightClick && !effect.transfer) {\r\n await effect.delete();\r\n } else {\r\n await effect.update({ disabled: !effect.disabled });\r\n }\r\n\r\n Hooks.callAll(\"forceUpdateTokenActionHud\");\r\n }\r\n\r\n /**\r\n * Handle action hover\r\n * @override\r\n * @param {object} event\r\n */\r\n async handleActionHover(event) {\r\n const types = [\"feature\", \"item\", \"spell\", \"weapon\", \"magicItem\"];\r\n const { actionType, actionId } = this.action.system;\r\n\r\n if (!types.includes(actionType)) return;\r\n\r\n const item = coreModule.api.Utils.getItem(this.actor, actionId);\r\n\r\n if (this.isHover) {\r\n Hooks.call(\"tokenActionHudSystemActionHoverOn\", event, item);\r\n } else {\r\n Hooks.call(\"tokenActionHudSystemActionHoverOff\", event, item);\r\n }\r\n }\r\n };\r\n});\r\n","import { GROUP } from \"./constants.js\";\r\n\r\n/**\r\n * Default categories and groups\r\n */\r\nexport let DEFAULTS = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n const groups = GROUP;\r\n Object.values(groups).forEach(group => {\r\n group.name = coreModule.api.Utils.i18n(group.name);\r\n group.listName = `Group: ${coreModule.api.Utils.i18n(group.name)}`;\r\n });\r\n const groupsArray = Object.values(groups);\r\n DEFAULTS = {\r\n layout: [\r\n {\r\n nestId: \"inventory\",\r\n id: \"inventory\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Inventory\"),\r\n groups: [\r\n { ...groups.weapons, nestId: \"inventory_weapons\" },\r\n { ...groups.equipment, nestId: \"inventory_equipment\" },\r\n { ...groups.consumables, nestId: \"inventory_consumables\" },\r\n { ...groups.tools, nestId: \"inventory_tools\" },\r\n { ...groups.containers, nestId: \"inventory_containers\" },\r\n { ...groups.loot, nestId: \"inventory_loot\" }\r\n ]\r\n },\r\n {\r\n nestId: \"features\",\r\n id: \"features\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Features\"),\r\n groups: [\r\n { ...groups.activeFeatures, nestId: \"features_active-features\" },\r\n { ...groups.passiveFeatures, nestId: \"features_passive-features\" }\r\n ]\r\n },\r\n {\r\n nestId: \"spells\",\r\n id: \"spells\",\r\n name: coreModule.api.Utils.i18n(\"TYPES.Item.spellPl\"),\r\n groups: [\r\n { ...groups.atWillSpells, nestId: \"spells_at-will-spells\" },\r\n { ...groups.innateSpells, nestId: \"spells_innate-spells\" },\r\n { ...groups.pactSpells, nestId: \"spells_pact-spells\" },\r\n { ...groups.cantrips, nestId: \"spells_cantrips\" },\r\n { ...groups._1stLevelSpells, nestId: \"spells_1st-level-spells\" },\r\n { ...groups._2ndLevelSpells, nestId: \"spells_2nd-level-spells\" },\r\n { ...groups._3rdLevelSpells, nestId: \"spells_3rd-level-spells\" },\r\n { ...groups._4thLevelSpells, nestId: \"spells_4th-level-spells\" },\r\n { ...groups._5thLevelSpells, nestId: \"spells_5th-level-spells\" },\r\n { ...groups._6thLevelSpells, nestId: \"spells_6th-level-spells\" },\r\n { ...groups._7thLevelSpells, nestId: \"spells_7th-level-spells\" },\r\n { ...groups._8thLevelSpells, nestId: \"spells_8th-level-spells\" },\r\n { ...groups._9thLevelSpells, nestId: \"spells_9th-level-spells\" }\r\n ]\r\n },\r\n {\r\n nestId: \"attributes\",\r\n id: \"attributes\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Attributes\"),\r\n groups: [\r\n { ...groups.abilities, nestId: \"attributes_abilities\" },\r\n { ...groups.skills, nestId: \"attributes_skills\" }\r\n ]\r\n },\r\n {\r\n nestId: \"effects\",\r\n id: \"effects\",\r\n name: coreModule.api.Utils.i18n(\"DND5E.Effects\"),\r\n groups: [\r\n { ...groups.temporaryEffects, nestId: \"effects_temporary-effects\" },\r\n { ...groups.passiveEffects, nestId: \"effects_passive-effects\" },\r\n { ...groups.conditions, nestId: \"effects_conditions\" }\r\n ]\r\n },\r\n {\r\n nestId: \"utility\",\r\n id: \"utility\",\r\n name: coreModule.api.Utils.i18n(\"tokenActionHud.utility\"),\r\n groups: [\r\n { ...groups.combat, nestId: \"utility_combat\" },\r\n { ...groups.token, nestId: \"utility_token\" },\r\n { ...groups.rests, nestId: \"utility_rests\" },\r\n { ...groups.utility, nestId: \"utility_utility\" }\r\n ]\r\n }\r\n ],\r\n groups: groupsArray\r\n };\r\n});\r\n","import { MODULE } from \"./constants.js\";\r\n\r\n/**\r\n *\r\n * @param updateFunc\r\n */\r\nexport function register(updateFunc) {\r\n game.settings.register(MODULE.ID, \"abbreviateSkills\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.abbreviateSkills.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.abbreviateSkills.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showSlowActions\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showSlowActions.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showSlowActions.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"displaySpellInfo\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.displaySpellInfo.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.displaySpellInfo.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnchargedItems\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnchargedItems.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnchargedItems.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnequippedItems\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItems.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItems.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnequippedItemsNpcs\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnequippedItemsNpcs.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: true,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showUnpreparedSpells\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnpreparedSpells.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showUnpreparedSpells.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n\r\n game.settings.register(MODULE.ID, \"showItemsWithoutActivationCosts\", {\r\n name: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.name\"\r\n ),\r\n hint: game.i18n.localize(\r\n \"tokenActionHud.dnd5e.settings.showItemsWithoutActivationCosts.hint\"\r\n ),\r\n scope: \"client\",\r\n config: true,\r\n type: Boolean,\r\n default: false,\r\n onChange: value => {\r\n updateFunc(value);\r\n }\r\n });\r\n}\r\n","// System Module Imports\r\nimport { ActionHandler } from \"./action-handler.js\";\r\nimport { MagicItemActionHandlerExtender } from \"./magic-items-extender.js\";\r\nimport { RollHandler as Core } from \"./roll-handler.js\";\r\nimport { DEFAULTS } from \"./defaults.js\";\r\nimport * as systemSettings from \"./settings.js\";\r\n\r\nexport let SystemManager = null;\r\n\r\nHooks.once(\"tokenActionHudCoreApiReady\", async coreModule => {\r\n SystemManager = class SystemManager extends coreModule.api.SystemManager {\r\n /** @override */\r\n getActionHandler() {\r\n const actionHandler = new ActionHandler();\r\n if (coreModule.api.Utils.isModuleActive(\"magic-items-2\")\r\n || coreModule.api.Utils.isModuleActive(\"magicitems\")) {\r\n actionHandler.addActionHandlerExtender(new MagicItemActionHandlerExtender(actionHandler));\r\n }\r\n return actionHandler;\r\n }\r\n\r\n /** @override */\r\n getAvailableRollHandlers() {\r\n let coreTitle = \"Core D&D5e\";\r\n\r\n if (coreModule.api.Utils.isModuleActive(\"midi-qol\")) {\r\n coreTitle += ` [supports ${coreModule.api.Utils.getModuleTitle(\"midi-qol\")}]`;\r\n }\r\n\r\n const choices = { core: coreTitle };\r\n return choices;\r\n }\r\n\r\n /** @override */\r\n getRollHandler(rollHandlerId) {\r\n let rollHandler;\r\n switch (rollHandlerId) {\r\n case \"core\":\r\n default:\r\n rollHandler = new Core();\r\n break;\r\n }\r\n\r\n return rollHandler;\r\n }\r\n\r\n /** @override */\r\n registerSettings(onChangeFunction) {\r\n systemSettings.register(onChangeFunction);\r\n }\r\n\r\n /** @override */\r\n async registerDefaults() {\r\n const defaults = DEFAULTS;\r\n // If the 'Magic Items' module is active, then add a group for it\r\n if (game.modules.get(\"magicitems\")?.active || game.modules.get(\"magic-items-2\")?.active) {\r\n const name = coreModule.api.Utils.i18n(\"tokenActionHud.dnd5e.magicItems\");\r\n defaults.groups.push(\r\n {\r\n id: \"magic-items\",\r\n name,\r\n listName: `Group: ${name}`,\r\n type: \"system\"\r\n }\r\n );\r\n defaults.groups.sort((a, b) => a.id.localeCompare(b.id));\r\n }\r\n return defaults;\r\n }\r\n };\r\n});\r\n","import { SystemManager } from \"./system-manager.js\";\r\nimport { MODULE, REQUIRED_CORE_MODULE_VERSION } from \"./constants.js\";\r\n\r\nHooks.on(\"tokenActionHudCoreApiReady\", async () => {\r\n const module = game.modules.get(MODULE.ID);\r\n module.api = {\r\n requiredCoreModuleVersion: REQUIRED_CORE_MODULE_VERSION,\r\n SystemManager\r\n };\r\n Hooks.call(\"tokenActionHudSystemReady\", module);\r\n});\r\n"],"names":["MODULE","ID","CORE_MODULE","REQUIRED_CORE_MODULE_VERSION","ACTION_TYPE","ability","check","condition","counter","effect","exhaustion","feature","item","save","skill","spell","utility","ACTIVATION_TYPE","action","group","bonus","icon","crew","day","hour","lair","minute","legendary","reaction","reactiondamage","reactionmanual","special","other","CONCENTRATION_ICON","CUSTOM_DND5E","COUNTERS","character","npc","FEATURE_GROUP_IDS","GROUP","_1stLevelSpells","id","name","spellMode","type","_2ndLevelSpells","_3rdLevelSpells","_4thLevelSpells","_5thLevelSpells","_6thLevelSpells","_7thLevelSpells","_8thLevelSpells","_9thLevelSpells","abilities","actions","activeFeatures","artificerInfusions","atWillSpells","backgroundFeatures","bonusActions","cantrips","channelDivinity","checks","classFeatures","combat","conditions","consumables","containers","counters","crewActions","defensiveTactics","eldritchInvocations","elementalDisciplines","equipment","equipped","feats","fightingStyles","huntersPrey","innateSpells","kiAbilities","lairActions","legendaryActions","loot","maneuvers","metamagicOptions","monsterFeatures","multiattacks","otherActions","pactBoons","pactSpells","passiveEffects","passiveFeatures","psionicPowers","raceFeatures","reactions","rests","runes","saves","skills","superiorHuntersDefense","temporaryEffects","token","tools","unequipped","weapons","PREPARED_ICON","PROFICIENCY_LEVEL_ICON","RARITY","common","uncommon","rare","veryRare","artifact","RITUAL_ICON","SPELL_GROUP_IDS","Utils","Hooks","once","async","capitalize","value","replace","text","charAt","toUpperCase","substring","toLowerCase","getSetting","key","defaultValue","game","settings","get","coreModule","api","Logger","debug","setSetting","set","ActionHandler","featureActions","inventoryActions","spellActions","buildSystemActions","groupIds","this","actors","actor","getValidActors","tokens","getValidTokens","items","sortItemsByName","discardSlowItems","abbreviateSkills","displaySpellInfo","showItemsWithoutActivationCosts","showUnchargedItems","showUnequippedItems","showUnpreparedSpells","activationgroupIds","inventorygroupIds","buildCharacterActions","buildVehicleActions","buildMultipleTokenActions","Promise","all","buildConditions","buildEffects","buildFeatures","buildInventory","buildSpells","buildAbilities","buildCombat","buildCounters","buildExhaustion","buildRests","buildSkills","buildUtility","actionType","groupId","system","CONFIG","DND5E","length","Object","entries","filter","map","abilityId","label","mod","icon1","getProficiencyIcon","proficient","info1","getModifier","title","i18n","localize","info2","listName","getListName","actionId","addActions","buildActivations","data","groupData","actionData","activationItems","Map","activationType","activities","contents","activation","has","values","groupDataClone","includes","defaultSelected","parentgroupData","addGroup","addGroupInfo","buildActions","combatType","initiative","current","tokenId","endTurn","getControlledTokens","tokenIds","combatants","combatant","getInfo1","class","cssClass","every","statusEffects","hasCondition","effects","some","statuses","status","disabled","img","getImage","tooltip","getTooltip","getConditionTooltipData","isModuleActive","keys","_","visible","active","attributes","death","success","failure","getFlag","max","counterKey","counterType","allApplicableEffects","size","statusEffectIds","Set","statusEffect","_id","effectId","isSuppressed","parent","identified","user","isGM","isTemporary","featuresMap","featureType","background","monster","race","classFeatureType","artificerInfusion","defensiveTactic","eldritchInvocation","elementalDiscipline","fightingStyle","ki","maneuver","metamagic","multiattack","pact","psionicPower","rune","subType","subtype","inventoryMap","quantity","isActiveItem","isUsableItem","isEquippedItem","shortRest","longRest","total","error","spells","spellsMap","isUsableSpell","preparation","mode","level","systemSpells","reverse","spellSlotsMap","spellSlotAvailable","pactSlotAvailable","pactSlot","hasValue","hasMax","hasLevel","slotAvailable","startsWith","slotsAvailable","spellSlotModes","levelInfo","slots","info","utilityTypes","deathSave","inspiration","hp","utilityType","options","getAction","entity","hasOwn","getItemInfo","getTooltipData","getActivationTypeIcon","icon2","getPreparedIcon","icon3","getConcentrationIcon","info3","activationTypes","activityActivationTypes","uses","spellPreparationModes","preparationMode","prepared","actionName","getSpellInfo","getQuantityData","getUsesData","getConsumeData","components","properties","componentsArray","vocal","somatic","material","ritual","push","join","allowedTypes","per","recovery","period","limitedUsePeriods","perPeriod","spent","firstActivity","firstTarget","consumption","targets","consumeId","target","consumeType","consumeAmount","parentId","substr","lastIndexOf","foundry","utils","getProperty","slowActivationTypes","proficiencyLevels","abilityActivationTypes","tooltipsSetting","unidentified","description","modifiers","rarity","traits","chatProperties","equippableItemCardProperties","labels","range","duration","p","getWeaponProperties","conditionTypes","journalEntry","fromUuid","reference","content","relativeTo","tooltipData","nameHtml","descriptionLocalised","TextEditor","enrichHTML","secrets","rarityHtml","propertiesHtml","property","traitsHtml","trait","traits2Html","traits2","traitsAltHtml","traitsAlt","modifiersHtml","modifier","enabled","tagsJoined","tagsHtml","weaponProperties","selected","validProperties","weapon","itemProperties","MagicItemActionHandlerExtender","ActionHandlerExtender","constructor","actionHandler","super","extendActionHandler","MagicItems","magicItems","parentGroupData","forEach","magicItem","attuned","_isItemAttuned","_isItemEquipped","charges","ownedEntries","entry","baseLevel","encodedValue","itemId","attunment","attunementTypes","REQUIRED","RollHandler","handleActionClick","event","handleAction","rollAbility","rollAbilityTest","rollAbilitySave","toggleCondition","modifyCounter","toggleEffect","modifyExhaustion","isRenderItem","renderItem","useItem","rollMagicItem","rollSkill","performUtilityAction","rollDeathSave","modifyInspiration","modifyCustomCounter","currentExhaustion","newExhaustion","isRightClick","update","setFlag","currentValue","newValue","adjustValue","increment","Math","isCtrl","magicItemActor","roll","callAll","getItem","needsRecharge","rollRecharge","use","legacy","nextTurn","rollInitiative","createCombatants","find","isConvenient","flags","dfreds","effectName","effectInterface","overlay","findCondition","findEffect","delete","toggleStatusEffect","transfer","handleActionHover","isHover","call","DEFAULTS","register","updateFunc","hint","scope","config","Boolean","default","onChange","groups","groupsArray","layout","nestId","SystemManager","getActionHandler","addActionHandlerExtender","getAvailableRollHandlers","coreTitle","getModuleTitle","core","getRollHandler","rollHandlerId","rollHandler","Core","registerSettings","onChangeFunction","systemSettings.register","registerDefaults","defaults","modules","sort","a","b","localeCompare","on","module","requiredCoreModuleVersion"],"mappings":"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"} \ No newline at end of file