local Srendarr = _G['Srendarr'] local L = Srendarr:GetLocale() local ATTRIBUTE_VISUAL_POWER_SHIELDING = ATTRIBUTE_VISUAL_POWER_SHIELDING local EVENT_PLAYER_DEAD = EVENT_PLAYER_DEAD local IsSlotUsed = IsSlotUsed local GetSlotName = GetSlotName local GetSlotTexture = GetSlotTexture local GetSlotBoundId = GetSlotBoundId local GetSlotItemSound = GetSlotItemSound local GetAbilityDuration = GetAbilityDuration local GetAbilityCastInfo = GetAbilityCastInfo local GetGameTimeMilliseconds = GetGameTimeMilliseconds local db, auraFrameLong, auraFrameShort, auraFrameDebuffs -- HOTBAR WATCHLIST -- local watchlist = { [3] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [4] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [5] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [6] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [7] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [8] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, [9] = {name = false, buff = false, debuff = false, cast = 0, texture = '', isShield = false, abilityId = 0}, } local triggeredSlots = {} function Srendarr:GetTriggeredSlotNum(name) return triggeredSlots[name] end do -- BUTTON HOOKS FOR CAST DETECTION local CostFail = HasCostFailure local ReqFail = HasRequirementFailure local WeaponFail = HasWeaponSlotFailure local TargetFail = HasTargetFailure local RangeFail = HasRangeFailure local StatusFail = HasStatusEffectFailure local FallingFail = HasFallingFailure local SwimmingFail = HasSwimmingFailure local MountedFail = HasMountedFailure local RezFail = HasReincarnatingFailure local GetSlotCooldownInfo = GetSlotCooldownInfo local zomax = zo_max local B_PRESSED = BSTATE_PRESSED local B_NORMAL = BSTATE_NORMAL local SPAM_THRESHOLD = Srendarr.SPAM_THRESHOLD local buffFrame, debuffFrame local ActionButton_SetState_Orig local QuickSlotButton_SetState_Orig local flags = { [3] = false, [4] = false, [5] = false, [6] = false, [7] = false, [8] = false, [9] = false, } local lastCast = { [3] = 0, [4] = 0, [5] = 0, [6] = 0, [7] = 0, [8] = 0, [9] = 0, } local watched = {} local function ActionFailed(slot) if (CostFail(slot) or ReqFail(slot) or WeaponFail(slot) or TargetFail(slot) or RangeFail(slot) or StatusFail(slot) or FallingFail(slot) or SwimmingFail(slot) or MountedFail(slot) or RezFail(slot) ) then return true end return false end local function ActionButton_SetState_Hook(self, state, locked) ActionButton_SetState_Orig(self, state, locked) -- Trigger event for target debuff list Srendarr:OnTargetChanged() local slot = self.slotNum if (watched[slot]) then -- only proceed if this button is being watched if (state == B_PRESSED) then flags[slot] = true elseif (state == B_NORMAL) then if (flags[slot]) then -- button was just pressed, this is a cast attempt local start = GetGameTimeMilliseconds() / 1000 if (not ActionFailed(slot) and (start > lastCast[slot] + SPAM_THRESHOLD)) then -- avoid failure and button mashing local casting = watchlist[slot] local proc = Srendarr:HasProc(casting.name) --for now just Crystal Fragments if proc then if buffFrame.k_auraActive[proc] then casting.cast = 0 end end -- @todo Here Buff / Debuff section if (casting.buff) then -- buff in this slot buffFrame:AddAura(1, 1, casting.name, casting.texture, (start + casting.cast), (start + casting.cast + casting.buff), casting.isShield, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_BUFF) end if (casting.debuff) then -- debuff in this slot debuffFrame:AddAura(1, 2, casting.name, casting.texture, (start + casting.cast), (start + casting.cast + casting.debuff), casting.isShield, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_DEBUFF) end lastCast[slot] = start --check for class passive effects local name, buff, debuff, texture, abilityId = Srendarr:GetClassPassiveSkillEffect(casting.name) if (name) then if (buff) then buffFrame:AddAura(1, 1, name, texture, (start + casting.cast), (start + casting.cast) + buff, false, nil, nil, abilityId, BUFF_EFFECT_TYPE_BUFF) end if (debuff) then debuffFrame:AddAura(1, 2, name, casting.texture, (start + casting.cast), (start + casting.cast) + debuff, false, nil, nil, abilityId, BUFF_EFFECT_TYPE_DEBUFF) end end end end flags[slot] = false end end end local function QuickSlotButton_SetState_Hook(self, state, locked) QuickSlotButton_SetState_Orig(self, state, locked) if (watched[9]) then local start = GetGameTimeMilliseconds() / 1000 if (start > lastCast[9]) then local button = ZO_ActionBar_GetButton(9) local slotNum = button:GetSlot() if button.useable then local timeLeft = GetSlotCooldownInfo(slotNum) lastCast[9] = start + zomax((timeLeft / 1000), SPAM_THRESHOLD) local casting = watchlist[9] if (casting.buff) then buffFrame:AddAura(1, 1, casting.name, casting.texture, start, start + casting.buff, false, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_BUFF) end if (casting.debuff) then debuffFrame:AddAura(1, 2, casting.name, casting.texture, start, start + casting.debuff, false, nil, nil, casting.abilityId, BUFF_EFFECT_TYPE_DEBUFF) end end end end end function Srendarr:SetupActionButtonHooks() buffFrame = Srendarr.auraFrames[1] -- short term always go to the first frame debuffFrame = Srendarr.auraFrames[3] -- debuffs always go to the third frame ActionButton_SetState_Orig = ActionButton3Button.SetState ActionButton3Button.SetState = ActionButton_SetState_Hook ActionButton4Button.SetState = ActionButton_SetState_Hook ActionButton5Button.SetState = ActionButton_SetState_Hook ActionButton6Button.SetState = ActionButton_SetState_Hook ActionButton7Button.SetState = ActionButton_SetState_Hook --ultimate ActionButton8Button.SetState = ActionButton_SetState_Hook --quickslot QuickSlotButton_SetState_Orig = ActionButton9Button.SetState ActionButton9Button.SetState = QuickSlotButton_SetState_Hook end function Srendarr:ConfigureActionButtonWatcher(slotNum) watched[slotNum] = (watchlist[slotNum].name) and true or false end end function Srendarr.OnActionSlotChanged(evt, slotNum) if (slotNum < 3 or slotNum > 8) then return end local actionButton if slotNum ~= 8 then for ability, slot in pairs(triggeredSlots) do if (slot == slotNum) then triggeredSlots[ability] = nil end end actionButton = ZO_ActionBar_GetButton(slotNum) if Srendarr:IsPlayingProcAnimation(actionButton) then Srendarr:StopProcAnimations(actionButton) end end if (IsSlotUsed(slotNum)) then local ability = GetSlotName(slotNum) local abilityId = GetSlotBoundId(slotNum) local texture = GetSlotTexture(slotNum) local buff, debuff, cast, corrections = Srendarr:GetAuraData(ability) --corrections local duration = GetAbilityDuration(abilityId) if (duration > 0 and corrections ~= 3) then if (buff and buff > 0 and (not corrections or corrections == 1)) then buff = duration / 1000 end if (debuff and debuff > 0 and (not corrections or corrections == 2)) then debuff = duration / 1000 end end local channeled, castTime, channelTime = GetAbilityCastInfo(abilityId) if (castTime > 0) then cast = castTime / 1000 end if (not Srendarr.db.showDebuff) then debuff = false -- if not showing debuffs, then don't track end if (buff or debuff) then local data = watchlist[slotNum] data.name = ability data.buff = buff data.debuff = debuff data.cast = cast data.texture = texture data.isShield = Srendarr:IsDamageShield(ability) data.abilityId = abilityId else watchlist[slotNum].name = false end --proc animaitons if slotNum ~= 8 then local proc = Srendarr:HasProc(ability) if Srendarr:IsProc(ability) then Srendarr:PlayProcAnimations(actionButton) elseif proc then triggeredSlots[proc] = slotNum local aura = auraFrameShort.k_auraActive[proc] if aura then local remaining = (aura.k_finish * 1000) - GetGameTimeMilliseconds() if remaining > 0 then Srendarr:PlayProcAnimations(actionButton, true) end end end end else watchlist[slotNum].name = false end Srendarr:ConfigureActionButtonWatcher(slotNum) end function Srendarr.OnActionSlotsFullUpdate(evt, isHotbarSwap) for slotNum = 3, 8 do Srendarr.OnActionSlotChanged(evt, slotNum) end end function Srendarr.OnQuickSlotChanged(evt, slotNum) if (IsSlotUsed(slotNum) and GetSlotItemSound(slotNum) == ITEM_SOUND_CATEGORY_POTION) then --only care about potions local ability = GetSlotName(slotNum) local abilityId = GetSlotBoundId(slotNum) local texture = GetSlotTexture(slotNum) local buff, debuff = Srendarr:GetPotionData(ability, abilityId) --corrections if (buff and buff > 0) then buff = buff * Srendarr:GetMedicinalUseCoefficient() end if (debuff and debuff > 0) then debuff = debuff * Srendarr:GetMedicinalUseCoefficient() end if (not Srendarr.db.showDebuff) then debuff = false -- if not showing debuffs, then don't track end if (buff or debuff) then local data = watchlist[9] data.name = ability data.buff = buff data.debuff = debuff data.cast = 0 data.texture = texture data.isShield = false data.abilityId = abilityId else watchlist[9].name = false end else watchlist[9].name = false end Srendarr:ConfigureActionButtonWatcher(9) end do --triggered effects animations local AM = ANIMATION_MANAGER local WM = WINDOW_MANAGER local PlaySound = PlaySound local function CreateProcAnimations(actionButton) if not actionButton.procBurstTimeline then actionButton.procBurstTexture = WM:CreateControl("$(parent)Burst", actionButton.slot, CT_TEXTURE) actionButton.procBurstTexture:SetAnchor(TOPLEFT, actionButton.slot:GetNamedChild("FlipCard")) actionButton.procBurstTexture:SetAnchor(BOTTOMRIGHT, actionButton.slot:GetNamedChild("FlipCard")) actionButton.procBurstTexture:SetTexture("EsoUI/Art/ActionBar/coolDown_completeEFX.dds") actionButton.procBurstTexture:SetBlendMode(TEX_BLEND_MODE_ADD) actionButton.procBurstTexture:SetDrawLevel(2) actionButton.procBurstTexture:SetHidden(true) actionButton.procLoopTexture = WM:CreateControl("$(parent)Loop", actionButton.slot, CT_TEXTURE) actionButton.procLoopTexture:SetAnchor(TOPLEFT, actionButton.slot:GetNamedChild("FlipCard")) actionButton.procLoopTexture:SetAnchor(BOTTOMRIGHT, actionButton.slot:GetNamedChild("FlipCard")) actionButton.procLoopTexture:SetTexture("EsoUI/Art/ActionBar/abilityHighlight_mage_med.dds") actionButton.procLoopTexture:SetBlendMode(TEX_BLEND_MODE_ADD) actionButton.procLoopTexture:SetDrawLevel(2) actionButton.procLoopTexture:SetHidden(true) actionButton.procBurstTimeline = AM:CreateTimelineFromVirtual("UltimateReadyBurst", actionButton.procBurstTexture) actionButton.procLoopTimeline = AM:CreateTimelineFromVirtual("UltimateReadyLoop", actionButton.procLoopTexture) actionButton.procBurstTimeline:SetHandler("OnPlay", function() PlaySound(SOUNDS.DEATH_RECAP_KILLING_BLOW_SHOWN) end) local function OnStop(self) if(self:GetProgress() == 1) then actionButton.procBurstTexture:SetHidden(true) actionButton.procLoopTimeline:PlayFromStart() actionButton.procLoopTexture:SetHidden(false) end end actionButton.procBurstTimeline:SetHandler("OnStop", OnStop) actionButton.procLoopTimeline:SetHandler("OnStop", function() actionButton.procLoopTexture:SetHidden(true) end) end end function Srendarr:PlayProcAnimations(actionButton, isActive) CreateProcAnimations(actionButton) if actionButton.procBurstTimeline then if not actionButton.procBurstTimeline:IsPlaying() and not actionButton.procLoopTimeline:IsPlaying() then if isActive then actionButton.procLoopTimeline:PlayFromStart() actionButton.procLoopTexture:SetHidden(false) else actionButton.procBurstTimeline:PlayFromStart() actionButton.procBurstTexture:SetHidden(false) end end end end function Srendarr:StopProcAnimations(actionButton) if actionButton.procBurstTimeline then actionButton.procBurstTexture:SetHidden(true) actionButton.procLoopTexture:SetHidden(true) actionButton.procBurstTimeline:Stop() actionButton.procLoopTimeline:Stop() end end function Srendarr:IsPlayingProcAnimation(actionButton) if actionButton.procBurstTimeline then return actionButton.procBurstTimeline:IsPlaying() or actionButton.procLoopTimeline:IsPlaying() end end end function Srendarr.OnEffectChanged(_, change, buff, name, unit, start, finish, stack, icon, _, effectType, abilityType, statusEffectType, unitName, unitId, abilityId) if (unit ~= 'player') then return end -- Trigger event for target debuff list Srendarr:OnTargetChanged() -- Skip Minor Buffs if (Srendarr.db.hideMinorBuffs and Srendarr.MinorBuffs[abilityId] ~= nil) then return end -- Skip Major Buffs if (Srendarr.db.hideMajorBuffs and Srendarr.MajorBuffs[abilityId] ~= nil) then return end if (change == EFFECT_RESULT_FADED) then -- losing an aura if (auraFrameLong.k_auraActive[name]) then if (auraFrameLong.k_auraActive[name].k_type < 3) then -- timed, ghost it auraFrameLong.k_auraActive[name]:Ghost() else -- non timed, kill it auraFrameLong:RemoveAura(name) end end if(effectType == BUFF_EFFECT_TYPE_DEBUFF) then if (auraFrameDebuffs.k_auraActive[name]) then if (auraFrameDebuffs.k_auraActive[name].k_type < 1) then -- timed, ghost it auraFrameDebuffs.k_auraActive[name]:Ghost() else -- non timed, kill it auraFrameDebuffs:RemoveAura(name) end end else if (auraFrameShort.k_auraActive[name]) then if (auraFrameShort.k_auraActive[name].k_type < 1) then -- timed, ghost it auraFrameShort.k_auraActive[name]:Ghost() else -- non timed, kill it auraFrameShort:RemoveAura(name) end end end if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then local slotNum = triggeredSlots[name] if slotNum then local actionButton = ZO_ActionBar_GetButton(slotNum) Srendarr:StopProcAnimations(actionButton) end end else -- adding or updating an aura local isShield = abilityType == ABILITY_TYPE_DAMAGESHIELD if (finish > start) then -- timed ability if(effectType == BUFF_EFFECT_TYPE_DEBUFF) then d('abilityId', abilityId) d('abilityName', name) d('buff', buff) d('effectType', effectType) d('statufEffectType', statusEffectType) if (Srendarr:IsWatchedTimed(name)) then auraFrameDebuffs:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType) end else if (finish - start < db.shortBuffThreshold) then if (Srendarr:IsWatchedTimed(name)) then auraFrameShort:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType) end else if (Srendarr:IsWatchedTimed(name)) then auraFrameLong:AddAura(2, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType) end end end elseif (Srendarr:IsToggled(name)) then -- toggled ability if (db.showToggle) then -- showing toggled auraFrameLong:AddAura(3, 1, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType) end else -- passive (assumption: passives have start = finish) if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then local duration = Srendarr:GetAuraData(name) or 0 auraFrameShort:AddAura(1, 1, name, icon, start, start + duration, isShield, abilityType, buff, abilityId, effectType) elseif (Srendarr:IsWatchedPassive(name, abilityType)) then auraFrameLong:AddAura(4, 1, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType) end end if (abilityType == ABILITY_TYPE_REGISTERTRIGGER) then local slotNum = triggeredSlots[name] if slotNum then local actionButton = ZO_ActionBar_GetButton(slotNum) Srendarr:PlayProcAnimations(actionButton) end end if (name == L.Passive_MedicinalUse) then Srendarr:SetMedicinalUseCoefficient(abilityId) end end end do --shields local GetUnitAttributeVisualizerEffectInfo = GetUnitAttributeVisualizerEffectInfo local callLater = zo_callLater local function RemoveShields() local value = GetUnitAttributeVisualizerEffectInfo('player', ATTRIBUTE_VISUAL_POWER_SHIELDING, STAT_MITIGATION, ATTRIBUTE_HEALTH, POWERTYPE_HEALTH) or 0 if (value <= 0) then -- shields are always 'short', remove from [1] if present for _, aura in pairs(auraFrameShort.k_auraActive) do if (aura.k_isShield) then aura:Ghost() end end end end function Srendarr.OnVisualRemoved(_, unit, visual, ...) if (unit == 'player' and visual == ATTRIBUTE_VISUAL_POWER_SHIELDING) then callLater(RemoveShields, 5) end end end function Srendarr.OnPlayerDeath(event) if (event == EVENT_PLAYER_DEAD) then -- player died Srendarr:StripAuras() else -- player lives again Srendarr:UpdateAuras() end end do local equippedArmor = { [EQUIP_SLOT_CHEST] = ARMORTYPE_NONE, [EQUIP_SLOT_FEET] = ARMORTYPE_NONE, [EQUIP_SLOT_HAND] = ARMORTYPE_NONE, [EQUIP_SLOT_HEAD] = ARMORTYPE_NONE, [EQUIP_SLOT_LEGS] = ARMORTYPE_NONE, [EQUIP_SLOT_SHOULDERS] = ARMORTYPE_NONE, [EQUIP_SLOT_WAIST] = ARMORTYPE_NONE, } function Srendarr:GetNumArmorPieces(desiredArmorType) local numPieces = 0 for equipSlot, armorType in pairs(equippedArmor) do if armorType == desiredArmorType then numPieces = numPieces + 1 end end return numPieces end function Srendarr.InventorySlotUpdated(event, bagId, slotId, isNewItem, itemSoundCategory, updateReason) if bagId == BAG_WORN and updateReason == INVENTORY_UPDATE_REASON_DEFAULT and equippedArmor[slotId] then local newArmorType = GetItemArmorType(bagId, slotId) if newArmorType ~= equippedArmor[slotId] then equippedArmor[slotId] = newArmorType Srendarr:SetupPassiveSkillEffects() end end end function Srendarr:InitializeArmorWatcher() for equipSlot in pairs(equippedArmor) do equippedArmor[equipSlot] = GetItemArmorType(BAG_WORN, equipSlot) end Srendarr:SetupPassiveSkillEffects() end end function Srendarr.OnCombatState(event, inCombat) if (inCombat) then if (db.onlyInCombat) then for i = 1, 3 do --hide all auras except of long term buffs (4) Srendarr.auraSceneFragments[i]:SetHiddenForReason("combatstate", false) end end else Srendarr:ClearTimerType(2) -- end all potential debuffs Srendarr.auraFrames[3]:RemoveAllAuras() -- end all potential debuffs if (db.onlyInCombat) then for i = 1, 3 do Srendarr.auraSceneFragments[i]:SetHiddenForReason("combatstate", true) end end end end function Srendarr.OnPlayerActivated() Srendarr:UpdateAuras() end do local GetNumBuffs = GetNumBuffs local GetUnitBuffInfo = GetUnitBuffInfo local DoesUnitExist = DoesUnitExist local frame, db, frameDebuff function Srendarr.OnTargetChanged() if (Srendarr.db.showTargetAurasDebuff == false) then return end -- cleanse out previous auras frame:RemoveAllAuras() frameDebuff:RemoveAllAuras() Srendarr:ClearTimerType(3) Srendarr:ClearTimerType(4) if (DoesUnitExist('reticleover')) then -- have a target if (db.onlyInCombat and not Srendarr.ui_InCombat) then return end -- showing only in combat, but not local numAuras = GetNumBuffs('reticleover') if (numAuras > 0) then for x = 1, numAuras do local name, start, finish, buff, stack, icon, _, effectType, abilityType, statusEffectType, abilityId, _ = GetUnitBuffInfo('reticleover', x) local isShield = abilityType == ABILITY_TYPE_DAMAGESHIELD -- Skip Minor Buffs if (Srendarr.db.hideMinorBuffs and Srendarr.MinorBuffs[abilityId] ~= nil) then return end -- Skip Major Buffs if (Srendarr.db.hideMajorBuffs and Srendarr.MajorBuffs[abilityId] ~= nil) then return end if (finish > start) then if (Srendarr:IsWatchedTimedTarget(name) and effectType == BUFF_EFFECT_TYPE_DEBUFF) then frameDebuff:AddAura(1, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType) elseif (Srendarr:IsWatchedTimedTarget(name) and effectType == BUFF_EFFECT_TYPE_BUFF) then frame:AddAura(2, 1, name, icon, start, finish, isShield, abilityType, buff, abilityId, effectType) end elseif (Srendarr:IsToggled(name)) then -- toggled if (db.showToggleTarget) then frame:AddAura(3, 3, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType) end else -- passive if (Srendarr:IsWatchedPassiveTarget(name, abilityType)) then frame:AddAura(4, 3, name, icon, 1, 1, isShield, abilityType, buff, abilityId, effectType) end end end frame:UpdateDisplay() frameDebuff:UpdateDisplay() end end end function Srendarr:InitializeOnTargetChanged() db, frame = self.db, self.auraFrames[4] db, frameDebuff = self.db, self.auraFrames[5] end end function Srendarr:ConfigureEvents() if (db.combineBuff) then auraFrameLong = self.auraFrames[1] else auraFrameLong = self.auraFrames[2] end if (db.showTargetAuras or db.showTargetAurasDebuff) then EVENT_MANAGER:RegisterForEvent(self.name, EVENT_RETICLE_TARGET_CHANGED, self.OnTargetChanged) else EVENT_MANAGER:UnregisterForEvent(self.name, EVENT_RETICLE_TARGET_CHANGED) end end function Srendarr:InitializeEvents() db = self.db auraFrameShort = self.auraFrames[1] auraFrameDebuffs = self.auraFrames[3] -- register events EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTION_SLOTS_FULL_UPDATE, self.OnActionSlotsFullUpdate) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTION_SLOT_UPDATED, self.OnActionSlotChanged) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_ACTIVE_QUICKSLOT_CHANGED, self.OnQuickSlotChanged) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_EFFECT_CHANGED, self.OnEffectChanged) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_DEAD, self.OnPlayerDeath) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ALIVE, self.OnPlayerDeath) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_UNIT_ATTRIBUTE_VISUAL_REMOVED, self.OnVisualRemoved) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_COMBAT_STATE, self.OnCombatState) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_PLAYER_ACTIVATED, self.OnPlayerActivated) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_INVENTORY_SINGLE_SLOT_UPDATE, self.InventorySlotUpdated) EVENT_MANAGER:RegisterForEvent(self.name, EVENT_SKILLS_FULL_UPDATE, function() Srendarr:SetupPassiveSkillEffects() end) EVENT_MANAGER:AddFilterForEvent(self.name, EVENT_EFFECT_CHANGED, REGISTER_FILTER_UNIT_TAG, 'player') EVENT_MANAGER:AddFilterForEvent(self.name, EVENT_UNIT_ATTRIBUTE_VISUAL_REMOVED, REGISTER_FILTER_UNIT_TAG, 'player') self:ConfigureEvents() self:InitializeArmorWatcher() self.OnActionSlotsFullUpdate() -- call on load to record initial hotbar data self.OnQuickSlotChanged(nil, GetCurrentQuickslot()) self:SetupActionButtonHooks() -- configure hooks, never call this again! self:InitializeOnTargetChanged() self.OnCombatState(nil, IsUnitInCombat("player")) end