Mercurial > wow > buffalo2
changeset 97:5476337198ec
- apply default anchors when docking modules
- Arifact Power tracker: totals AP items in bags and bank, and forecasts progress on each weapon. Requires user to shift-click each weapon at least once to get initial XP data.
author | Nenue |
---|---|
date | Mon, 16 Jan 2017 20:24:12 -0500 |
parents | bb38bc0e787f |
children | dadddb8a551f |
files | Modules/ArtifactPower.lua Modules/ArtifactPower.xml Modules/BuffFrame.lua Modules/BuffFrame.xml Modules/WorldState.lua Templates.xml Veneer.lua Veneer.toc |
diffstat | 8 files changed, 494 insertions(+), 21 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/ArtifactPower.lua Mon Jan 16 20:24:12 2017 -0500 @@ -0,0 +1,392 @@ +-- Veneer +-- ArtifactPower.lua +-- Created: 1/15/2017 11:44 PM +-- %file-revision% +-- + +local print = DEVIAN_WORKSPACE and function(...) print('VnAP', ...) end or nop +VeneerArtifactPowerMixin = { + + anchorPoint = 'TOP', + anchorFrom = 'TOP', +} +local ap = VeneerArtifactPowerMixin +local BAGS_TO_SCAN = {BACKPACK_CONTAINER } +local TOOLTIP_NAME = 'VeneerAPScanner' + +function ap:OnLoad() + self:RegisterEvent('BAG_UPDATE') -- use to obtain bag IDs to scan + self:RegisterEvent('BAG_UPDATE_DELAYED') -- use to trigger actual scan activity + self:RegisterEvent('BANKFRAME_OPENED') -- determine when bank info is available + self:RegisterEvent('BANKFRAME_CLOSED') -- " " " + self:RegisterEvent('ARTIFACT_UPDATE') -- when artifact data has changed + self:RegisterEvent('ARTIFACT_UPDATE_XP') -- when artifact xp has changed (but not necessarily data) + self:RegisterEvent('MODIFIER_STATE_CHANGED') + self:RegisterEvent('PLAYER_REGEN_ENABLED') + self:RegisterEvent('PLAYER_REGEN_DISABLED') + Veneer:AddHandler(self, self.anchorPoint, true) + SLASH_VENEER_AP1 = "/vap" + SLASH_VENEER_AP2 = "/veneerap" + SlashCmdList.VENEER_AP = function() + self:Show() + end + + self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') + +end + +local defaultSettings = { +} + +function ap:Setup() + print(self:GetName()..':Setup()') + local guid = UnitGUID('player') + VeneerData.ArtifactPower = VeneerData.ArtifactPower or defaultSettings + VeneerData.ArtifactPower[guid] = VeneerData.ArtifactPower[guid] or {} + self.profile = VeneerData.ArtifactPower[guid] + self.profile.bagslots = self.profile.bagslots or {} + self.profile.artifacts = self.profile.artifacts or {} + self:GetCurrentArtifact(true) + self.updateSummary = true + + -- Bagnon compatibility + -- todo: ArkInventory, Elv, etc + if IsAddOnLoaded('Bagnon') then + local oToggleAllBags = ToggleAllBags + ToggleAllBags = function() + print('|cFFFF0088ToggleAllBags') + oToggleAllBags() + if BagnonFrameinventory:IsShown() then + self:Show() + else + self.enabled = nil + self:Hide() + end + end + else + hooksecurefunc("OpenBackpack", function() + self:Show() + end) + hooksecurefunc("CloseBackpack", function() + self.enabled = nil + self:Hide() + end) + end + + +end +local UNDERLIGHT_ANGLER_ID = 133755 +function ap:GetCurrentArtifact(newItem) + if not self.profile then + return + end + local artifacts = self.profile.artifacts + local itemID, altItemID, name, texture, currentXP, pointsSpent, _, _, artifactAppearanceID, appearanceModID, itemAppearanceID, altItemAppearanceID, altOnTop = C_ArtifactUI:GetArtifactInfo() + + + if itemID then + + + + + print('updating', itemID, name, currentXP, pointsSpent, pointsAvailable, adjustedXP) + table.wipe(artifacts[itemID]) + artifacts[itemID] = artifacts[itemID] or {} + artifacts[itemID].name = name + artifacts[itemID].texture = texture + artifacts[itemID].currentXP = currentXP + artifacts[itemID].level = pointsSpent + end + + + self:Update() +end +function ap:QueueBag(containerID) + containerID = tonumber(containerID) + if not containerID then + return + end + + if not tContains(BAGS_TO_SCAN, containerID) then + print(' queueing', containerID, type(containerID), #BAGS_TO_SCAN , 'in line') + BAGS_TO_SCAN[#BAGS_TO_SCAN + 1] = containerID + end +end + +function ap:OnShow() + self.enabled = true + self:Update() + Veneer:DynamicReanchor() +end +function ap:OnHide() + Veneer:DynamicReanchor() +end + +function ap:OnEnter() + + GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') + + GameTooltip:AddLine(self.bagAP) + GameTooltip:AddLine(self.bankAP) + +end + +function ap:OnEvent(event, ...) + print(self:GetName()..':OnEvent()', event, ...) + if event == 'BAG_UPDATE' then + local containerID = ... + self:QueueBag(containerID) + elseif event == 'PLAYER_BANKSLOTS_CHANGED' then + self:QueueBag(BANK_CONTAINER) + elseif event == 'BAG_UPDATE_DELAYED' then + self:ScanAllBags() + elseif event == 'BANKFRAME_OPENED' then + self.bankAccess = true + self:QueueBag(BANK_CONTAINER) + for i = 1, GetNumBankSlots() do + self:QueueBag(i+NUM_BAG_SLOTS) + end + self:ScanAllBags() + elseif event == 'BANKFRAME_CLOSED' then + self.bankAccess = false + self:Update() + elseif event == 'ARTIFACT_UPDATE' then + self:GetCurrentArtifact(...) + elseif event == 'ARTIFACT_UPDATE_XP' then + self:GetCurrentArtifact(...) + self:Update() + elseif event == 'MODIFIER_STATE_CHANGED' then + self:Update() + elseif event == 'PLAYER_REGEN_ENABLED' then + if self.enabled then + self:Show() + end + + elseif event == 'PLAYER_REGEN_DISABLED' then + self:Hide() + end +end + +function ap:OnMouseDown() + self.enabled = nil + self:Hide() +end + +function ap:Update() + if not self:IsShown() then + return + end + print('|cFF00FFFFUpdate()|r') + + local bankText, bagText + if not (self.bankAP and self.bagAP) then + bankText = '|cFFFF0000Open bank frame to count all AP|r ' + else + bankText = '|cFFFFFFFFAP:|r' .. tostring(self.bagAP + self.bankAP) .. ' |cFFFFFF00('..tostring(self.bankAP)..' banked)|r' + end + self.SummaryHeader:SetText(bankText) + + -- Artifact icons, in no particular order + local equippedID = C_ArtifactUI.GetEquippedArtifactInfo() + local numButtons = 0 + local lastFrame + for itemID, artifact in pairs(self.profile.artifacts) do + print(artifact.name, artifact.texture, artifact.currentXP) + numButtons = numButtons + 1 + local button = self.Artifact[numButtons] + + button:SetID(itemID) + for k,v in pairs(artifact) do + --print('::',k,v) + button[k] = v + end + + + local pointsAvailable = button.level + local cost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable) + local adjustedXP = button.currentXP + if itemID ~= UNDERLIGHT_ANGLER_ID then + adjustedXP = adjustedXP + (self.bankAP or 0) + (self.bagAP or 0) + print('not UL angler', adjustedXP) + else + print('UL angler', adjustedXP) + end + + while adjustedXP >= cost do + pointsAvailable = pointsAvailable + 1 + adjustedXP = adjustedXP - cost + print(pointsAvailable, '-', cost, '=', adjustedXP) + cost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable) + end + button.adjustedXP = adjustedXP + button.actualLevel = pointsAvailable + + button.isEquipped = (equippedID == itemID) + button.relativeFrame = lastFrame + button:Update() + lastFrame = button + button:Show() + end + for i = numButtons+1, #self.Artifact do + print('hide', i) + self.Artifact[i]:Hide() + end + + + + self:SetWidth(64*3+ 16) + self:SetHeight(8 + self.SummaryHeader:GetHeight() + 64) + self:Reanchor() + +end + +function ap:ScanBag(id) + print('|cFF00FFFFScanBag()|r', id, IsBagOpen(id), GetContainerNumSlots(id)) + local numSlots = GetContainerNumSlots(id) + local requiresUpdate + if numSlots == 0 then + return nil + end + + + self.profile.bagslots[id] = self.profile.bagslots[id] or {} + table.wipe(self.profile.bagslots[id]) + local bagData = self.profile.bagslots[id] + bagData.totalAP = 0 + for slotID = 1, numSlots do + local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(id, slotID) + local itemID = GetContainerItemID(id, slotID) + + if link then + self.tooltip:SetOwner(self, 'ANCHOR_NONE') + self.tooltip:SetHyperlink(link) + self.tooltip:Show() + local numLines = self.tooltip:NumLines() + if numLines >= 3 then + local subText = _G[TOOLTIP_NAME .. 'TextLeft2']:GetText() + if subText and subText:match(ARTIFACT_POWER) then + for i = 3, numLines do + local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText() + if text and text:match(ARTIFACT_POWER) then + text = text:gsub('[,%D]', '') + print(link, '-', tonumber(text)) + local itemAP = tonumber(text) + if itemAP then + bagData.numItems = (bagData.numItems or 0) + 1 + bagData.totalAP = (bagData.totalAP or 0) + itemAP + bagData.items = bagData.items or {} + if not bagData.items[itemID] then + requiresUpdate = true + bagData.numUnique = (bagData.numUnique or 0) + 1 + end + bagData.items[itemID] = (bagData.items[itemAP] or 0) + 1 + end + end + end + end + end + end + + if self.profile.artifacts[itemID] then + print('artfiact weapon', itemID, link, id, slotID) + self.profile.artifacts[itemID].containerID = id + self.profile.artifacts[itemID].slotID = slotID + end + + end + + return requiresUpdate +end + +function ap:ScanAllBags() + print('|cFFFF0088ScanAllBags()|r') + + local bagID = tremove(BAGS_TO_SCAN, 1) + while bagID do + self.updateSummary = self:ScanBag(bagID) or self.updateSummary + bagID = tremove(BAGS_TO_SCAN, 1) + end + + if self.updateSummary then + print('tripped updater') + self.bankAP = 0 + self.bagAP = 0 + for id, bagData in pairs(self.profile.bagslots) do + print(id, GetBagName(id), bagData.totalAP) + id = tonumber(id) + if bagData.totalAP then + if (id == BANK_CONTAINER) or (id >= 5) then + self.bankAP = self.bankAP + bagData.totalAP + else + self.bagAP = self.bagAP + bagData.totalAP + end + end + + end + self.lastUpdate = GetTime() + self:Update() + end + self.updateSummary = nil +end + +VeneerArtifactButtonMixin = {} +function VeneerArtifactButtonMixin:Update() + + if self.actualLevel ~= self.level then + self.Level:SetText(self.actualLevel) + self.Level:SetTextColor(0,1,0) + self.CurrentXP:SetText(self.adjustedXP) + self.CurrentXP:SetTextColor(0,1,0) + else + self.Level:SetText(self.level, 1, 1, 1) + self.Level:SetTextColor(1,1,1) + self.CurrentXP:SetText(self.currentXP) + self.CurrentXP:SetTextColor(1,1,0) + end + + if self.isEquipped then + self:SetNormalTexture([[Interface\Buttons\ButtonHilight-Square]]) + self:GetNormalTexture():SetBlendMode('ADD') + self:GetNormalTexture():SetVertexColor(0,1,0) + else + self:SetNormalTexture(nil, 'ADD') + end + + self:ClearAllPoints() + if self.relativeFrame then + self:SetPoint('BOTTOMLEFT', self.relativeFrame, 'BOTTOMRIGHT', 4, 0) + else + self:SetPoint('BOTTOMLEFT', 4, 4) + end + + + + self.Icon:SetTexture(self.texture) + self.Name:SetText(self.name) + self:SetSize(64,64) +end + +function VeneerArtifactButtonMixin:OnEnter() + GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') + GameTooltip:SetText(self.name) + GameTooltip:AddLine(self.currentXP, 1, 1, 0) + if self.adjustedXP ~= self.currentXP then + GameTooltip:AddLine(self.adjustedXP, 0, 1, 1) + end + + + GameTooltip:Show() +end +function VeneerArtifactButtonMixin:OnLeave() + if GameTooltip:IsOwned(self) then + GameTooltip:Hide() + end +end + +function VeneerArtifactButtonMixin:OnClick(button, down) + if self.isEquipped then + SocketInventoryItem(16) + else + SocketContainerItem(self.containerID, self.slotID) + end +end \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/ArtifactPower.xml Mon Jan 16 20:24:12 2017 -0500 @@ -0,0 +1,73 @@ +<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ +..\FrameXML\UI.xsd"> + <Script file="ArtifactPower.lua" /> + + <Button name="VeneerArtifactButton" parentArray="Artifact" mixin="VeneerArtifactButtonMixin" virtual="true"> + + <Scripts> + <OnEnter method="OnEnter" /> + <OnLeave method="OnLeave" /> + <OnClick method="OnClick" /> + </Scripts> + <Size x="64" y="64" /> + <PushedTexture file="Interface\Buttons\UI-Quickslot-Depress" setAllPoints="true" /> + <HighlightTexture file="Interface\Buttons\ButtonHilight-Square" setAllPoints="true" alphaMode="ADD" /> + <Layers> + <Layer level="BACKGROUND"> + <Texture name="$parentIcon" parentKey="Icon" setAllPoints="true" /> + </Layer> + + <Layer level="OVERLAY"> + + <FontString name="$parentName" parentKey="Name" inherits="VeneerNumberFont" text="NAME" wordwrap="false"> + <Anchors> + <Anchor point="TOPLEFT" x="4" y="-16" /> + <Anchor point="RIGHT" x="-4" /> + </Anchors> + <Color r="0" g="1" b="1" /> + </FontString> + <FontString name="$parentLevel" parentKey="Level" inherits="VeneerHeaderFont"> + <Anchors> + <Anchor point="TOP" x="0" y="-2" /> + </Anchors> + </FontString> + <FontString name="$parentCurrentXP" parentKey="CurrentXP" inherits="VeneerNumberFont" text="Bank:"> + <Anchors> + <Anchor point="BOTTOM" x="0" y="4" /> + </Anchors> + <Color r="1" g="1" b="0" /> + </FontString> + </Layer> + </Layers> + </Button> + <Frame name="VeneerArtifactPower" hidden="true" mixin="VeneerArtifactPowerMixin" parent="UIParent" inherits="VeneerMixinScripts" enableMouse="true"> + <Size x="300" y="36" /> + <Scripts> + <OnEnter method="OnEnter" /> + <OnLeave method="OnLeave" /> + <OnMouseDown method="OnMouseDown" /> + </Scripts> + <Layers> + <Layer level="BACKGROUND"> + + <Texture parentKey="Background"> + <Color a="0.5" r="0" g="0" b="0" /> + </Texture> + </Layer> + <Layer level="OVERLAY"> + <FontString name="$parentSummaryHeader" parentKey="SummaryHeader" inherits="VeneerNumberFont" text=""> + <Anchors> + <Anchor point="TOPLEFT" x="4" y="-4" /> + </Anchors> + <Color r="0" g="1" b="1" /> + </FontString> + </Layer> + </Layers> + <Frames> + <Button inherits="VeneerArtifactButton" /> + <Button inherits="VeneerArtifactButton" /> + <Button inherits="VeneerArtifactButton" /> + <Button inherits="VeneerArtifactButton" /> + </Frames> + </Frame> +</Ui>
--- a/Modules/BuffFrame.lua Tue Jan 03 14:06:41 2017 -0500 +++ b/Modules/BuffFrame.lua Mon Jan 16 20:24:12 2017 -0500 @@ -35,7 +35,7 @@ local COUNT_PARENT local DURATION_ANCHOR = 'BOTTOMLEFT' -local DURATION_INSET = 4 +local DURATION_INSET = 1 local DURATION_PARENT VeneerBuffFrameMixin = { @@ -243,7 +243,6 @@ (ANCHOR_INSET_DELTA[COUNT_ANCHOR][1] * COUNT_INSET), (ANCHOR_INSET_DELTA[COUNT_ANCHOR][2] * COUNT_INSET)) - self.underlay:SetParent(UIParent) self.underlay:SetFrameStrata('BACKGROUND') @@ -290,7 +289,7 @@ hooksecurefunc("BuffFrame_Update", function(...) self:OnBuffFrameUpdate(...) end) - --hooksecurefunc("AuraButton_UpdateDuration", function(...) self:OnUpdateDuration(...) end) + hooksecurefunc("AuraButton_UpdateDuration", function(...) self:OnUpdateDuration(...) end) hooksecurefunc("AuraButton_Update", function(...) self:OnAuraButton_Update(...) end) hooksecurefunc("BuffFrame_UpdateAllBuffAnchors", function(...) self:OnUpdateAllBuffAnchors(...) end) hooksecurefunc("TemporaryEnchantFrame_Update", function(...) self:OnTemporaryEnchantFrameUpdate(...) end) @@ -564,7 +563,7 @@ end end function plugin:OnUpdateDuration (frame, timeLeft) - local veneer = self:Acquire(frame) + local veneer = self:Acquire(frame:GetName()) local hours = floor(timeLeft/3600) local minutes = floor(mod(timeLeft, 3600)/60) local seconds = floor(mod(timeLeft, 60)) @@ -580,13 +579,11 @@ if timeLeft < 10 then if not veneer.duration.getHuge then veneer.duration.getHuge = true - veneer.duration:SetFontObject(VeneerNumberFontLarge) - veneer.duration:SetTextColor(1,1,0,1) + veneer.duration:SetTextColor(1,.5,0,1) end else if veneer.duration.getHuge then veneer.duration.getHuge = nil - veneer.duration:SetFontObject(VeneerNumberFont) veneer.duration:SetTextColor(1,1,1,1) end end
--- a/Modules/BuffFrame.xml Tue Jan 03 14:06:41 2017 -0500 +++ b/Modules/BuffFrame.xml Mon Jan 16 20:24:12 2017 -0500 @@ -51,7 +51,7 @@ </Texture> </Layer> <Layer level="OVERLAY"> - <FontString name="$parentDuration" parentKey="duration" inherits="VeneerNumberFont"> + <FontString name="$parentDuration" parentKey="duration" inherits="VeneerTimeFont"> <Anchors> <Anchor point="BOTTOMLEFT" x="5" y="9" /> </Anchors>
--- a/Modules/WorldState.lua Tue Jan 03 14:06:41 2017 -0500 +++ b/Modules/WorldState.lua Mon Jan 16 20:24:12 2017 -0500 @@ -4,6 +4,7 @@ -- %file-revision% -- +local print = DEVIAN_WORKSPACE and function(...) print('VnWorldState', ...) end or nop local WorldStateBlockMixin = {} VeneerOrderHallMixin = { anchorPoint = 'TOP', @@ -13,8 +14,8 @@ addonTrigger = 'Blizzard_OrderHallUI', addonFrame = 'OrderHallCommandBar', } + VeneerWorldStateHeadsUpMixin = { - } VeneerWorldStateCurrencyMixin = { @@ -27,7 +28,6 @@ detectedFrames = {}, anchorPoint = 'TOP', } -local print = DEVIAN_WORKSPACE and function(...) print('VnWorldState', ...) end or nop function VeneerWorldStateMixin:Reset() for i, frame in ipairs(self.modules) do @@ -86,6 +86,7 @@ function VeneerWorldStateMixin:OnEvent(event, arg) print(event, arg) if event == 'PLAYER_ENTERING_WORLD' then + self:Show() self:Update() elseif event == 'PLAYER_REGEN_ENABLED' then self:SetShown(true)
--- a/Templates.xml Tue Jan 03 14:06:41 2017 -0500 +++ b/Templates.xml Mon Jan 16 20:24:12 2017 -0500 @@ -15,6 +15,8 @@ <Color a="1" r="1" g="0.4" b="0" /> </Font> + <Font name="VeneerTimeFont" font="Fonts\ARIALN.ttf" outline="THICK" height="14" /> + <!-- generic animations --> <Frame name="VeneerAnimations" virtual="true"> <Animations>
--- a/Veneer.lua Tue Jan 03 14:06:41 2017 -0500 +++ b/Veneer.lua Mon Jan 16 20:24:12 2017 -0500 @@ -111,8 +111,8 @@ local select, IsAddOnLoaded, IsLoggedIn = select, IsAddOnLoaded, IsLoggedIn function VeneerCore:OnEvent(event, ...) - print(event, ...) - if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then + print('|cFFFF0088OnEvent()|r',event, ...) + if event == 'PLAYER_LOGIN' then print(IsLoggedIn(), self.initialized) if IsLoggedIn() and not self.intialized then self:Setup() @@ -151,15 +151,19 @@ end local VeneerModule_Setup = function(frame) - if (not frame.addonTrigger) or select(2,IsAddOnLoaded(frame.addonTrigger)) then - if not frame.initialized then + if not frame.initialized then + local doSetup = (not frame.addonTrigger) or select(2, IsAddOnLoaded(frame.addonTrigger)) + print(' '..frame:GetName()..'.doSetup =', doSetup) + if doSetup then frame:Setup() frame.initialized = true end + end end function VeneerCore:Setup () + print('|cFFFF0088Setup()|r') local resetConfig = (not VeneerData) if (not VeneerData) then VeneerData = defaults @@ -228,7 +232,9 @@ end end if not primaryAnchor then - primaryAnchor = 'TOPLEFT' + primaryAnchor = 'CENTER' + clusterTable[primaryAnchor] = clusterTable[primaryAnchor] or {} + clusterTable = clusterTable[primaryAnchor] end if not insertPosition then insertPosition = #clusterTable + 1 @@ -237,7 +243,7 @@ end function VeneerCore:AddHandler(handler, ...) - print('*** Adding handler:', handler.moduleName or handler:GetName()) + print('|cFFFFFF00*** Adding handler:', handler.moduleName or handler:GetName()) local anchorGroup, clusterTable, clusterIndex = self:GetClusterFromArgs(...) @@ -248,7 +254,7 @@ end tinsert(clusterTable, clusterIndex, handler) - print('cluster', anchorGroup, 'table', clusterTable, 'position', clusterIndex) + print(' cluster', anchorGroup, 'table', clusterTable, 'position', clusterIndex) handler.anchorCluster = clusterTable handler.anchorIndex = clusterIndex @@ -314,10 +320,11 @@ if frame:IsVisible() then if frame.anchorFrame then + print(frame.anchorPoint) frame:SetPoint(frame.anchorPoint, frame.anchorFrame, frame.anchorFrom, frame.anchorX, frame.anchorY) print(frame:GetTop(), frame:GetRight()) else - anchorPoint = frame.anchorPoint + anchorPoint = frame.anchorPoint or anchorPoint frame:ClearAllPoints() if lastFrame then frame:SetPoint(anchorPoint, lastFrame, ANCHOR_OFFSET_POINT[anchorPoint], 0, 0) @@ -409,7 +416,7 @@ print('delaying walk for', method) return end - print('|cFF00FF00Veneer:ExecuteOnClusters|r('..tostring(layer)..', '..tostring(method)..')') + print('|cFF00FF00ExecuteOnClusters|r('..tostring(layer)..', '..tostring(method)..')') else print(' Level '..self.parserDepth) end
--- a/Veneer.toc Tue Jan 03 14:06:41 2017 -0500 +++ b/Veneer.toc Mon Jan 16 20:24:12 2017 -0500 @@ -1,6 +1,6 @@ ## Interface: 70100 ## Title: Veneer -## Notes: Buff button management +## Notes: Collection of interface enhancements that make life easier ## Author: Krakyn ## Version: 1.0-@project-revision@ ## SavedVariables: VeneerData @@ -16,4 +16,5 @@ Modules\TalkingHead.xml Modules\BuffFrame.xml Modules\PaperDoll.xml -Modules\GuildInfo.xml \ No newline at end of file +Modules\GuildInfo.xml +Modules\ArtifactPower.xml \ No newline at end of file