Mercurial > wow > buffalo2
view Modules/ArtifactPower.lua @ 102:1e511e9aaca5
- clean up handler loading inconsistencies; exclude free frames from anchor cluster iterations, and remove extraneous PLAYER_LOGIN handling
- added a Setup method to the handler template that creates and reconciles a SavedVariables table for that module
author | Nenue |
---|---|
date | Wed, 25 Jan 2017 23:11:27 -0500 |
parents | f32b63c93275 |
children | 8df154a2bfd6 |
line wrap: on
line source
-- Veneer -- ArtifactPower.lua -- Created: 1/15/2017 11:44 PM -- %file-revision% -- local print = DEVIAN_WORKSPACE and function(...) print('VnAP', ...) end or nop VeneerArtifactPowerMixin = { numItems = 0, Tokens = {}, cache = {}, fishingCache = {}, scanQueue = {}, ItemButtons = {}, anchorPoint = 'TOP', anchorFrom = 'TOP', } local defaultSettings = { firstUse = true, autoHide = true, } local ap = VeneerArtifactPowerMixin local BAGS_TO_SCAN = {BACKPACK_CONTAINER } local TOOLTIP_NAME = 'VeneerAPScanner' local POINT_COSTS = { 100, 300, 325, 350, 375, 400, 425, 450, 525, 625, 750, 875, 1000, 6840, 8830, 11280, 14400, 18620, 24000, 30600, 39520, 50880, 64800, 82500, 105280, 138650, 182780, 240870, 325520, 417560, 546000, 718200, 946660, 1245840, 1635200, 191500, 2010000, 2110000, 2215000, 2325000, 2440000, 2560000, 2690000, 2825000, 2965000, 3115000, 3270000, 3435000, 3605000, 3785000, 3975000, 4175000, 4385000, 4605000 } local FRAME_LIST = {'ContainerFrame1', 'BankFrame'} local BAG_FRAMES = {'ContainerFrame1'} local BANK_FRAMES = {'BankFrame'} 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_XP_UPDATE') -- when artifact xp has changed (but not necessarily data) self:RegisterEvent('PLAYER_REGEN_ENABLED') self:RegisterEvent('PLAYER_REGEN_DISABLED') self:RegisterEvent('PLAYER_ENTERING_WORLD') Veneer:AddHandler(self, self.anchorPoint, true) SLASH_VENEER_AP1 = "/vap" SLASH_VENEER_AP2 = "/veneerap" SlashCmdList.VENEER_AP = function(arg) if arg == 'fishing' then if VeneerData.ArtifactPower.EnableFishing then VeneerData.ArtifactPower.EnableFishing = nil else VeneerData.ArtifactPower.EnableFishing = true end self:Print('Show Underlight Angler:', (VeneerData.ArtifactPower.EnableFishing and 'ON' or 'OFF')) self:Update() else self:Show() end end self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') tinsert(UISpecialFrames, self:GetName()) end local IsBagnonOpen = function() return ((BagnonFramebank and BagnonFramebank:IsShown()) or (BagnonFrameinventory and BagnonFrameinventory:IsShown())) end local addonCompatibility = { ['Bagnon'] = { BagFrames = {'BagnonFrameinventory'}, BankFrames = {'BagnonFramebank'}, FrameMethods = { ['HideFrame'] = IsBagnonOpen, ['ShowFrame'] = IsBagnonOpen }, PostHooks = {'ToggleAllBags', 'ToggleBackpack' }, MethodClass = 'Bagnon', MethodHooks = {'BANK_OPENED', 'BANKFRAME_CLOSED'}, } } local function AddFrameHooks(frame, args) for funcName, func in pairs(args.FrameMethods) do print('binding', frame:GetName(), funcName, 'to', tostring(func)) hooksecurefunc(frame, funcName, func) end end local PENDING_HOOKS = {} local function RegisterInventoryFrame(name, listType, args) print('register', name, 'as inventory frame type =', (listType == BAG_FRAMES) and 'bags' or 'bank') tinsert(FRAME_LIST, name) tinsert(listType, name) if _G[name] then AddFrameHooks(_G[name], args) else PENDING_HOOKS[name] = args end end function ap:Setup() print(self:GetName()..':Setup()') local guid = UnitGUID('player') VeneerData.ArtifactPower = VeneerData.ArtifactPower or defaultSettings self.db = VeneerData.ArtifactPower self.db[guid] = self.db[guid] or {} self.db.cache = self.db.cache or {} self.db.fishingCache = self.db.fishingCache or {} for i, data in pairs(self.cache) do -- bring in anything found before player data is active self.db.cache[i] = data end for i, data in pairs(self.fishingCache) do self.db.fishingCache[i] = data end self.cache = self.db.cache self.profile = self.db[guid] self.profile.bagslots = self.profile.bagslots or {} self.profile.artifacts = self.profile.artifacts or {} self.updateSummary = true VeneerArtifactPowerTimer:SetScript('OnUpdate', function() self:OnUpdate() end) local DoTryToShow = function() self:TryToShow() end hooksecurefunc("OpenBackpack", DoTryToShow) hooksecurefunc("CloseBackpack", DoTryToShow) -- Bagnon compatibility -- todo: ArkInventory, Elv, etc for addon, args in pairs(addonCompatibility) do if IsAddOnLoaded(addon) then for _, name in ipairs(args.BagFrames) do RegisterInventoryFrame(name, BAG_FRAMES, args) end for _, name in ipairs(args.BankFrames) do RegisterInventoryFrame(name, BANK_FRAMES, args) end -- should only specify non-secure functions in this table for _, name in ipairs(args.PostHooks) do local oFunc = _G[name] _G[name] = function(...) print('|cFFFF0088' .. name .. '|r', ...) oFunc(...) self:TryToShow() end end local frame = _G[args.MethodClass] if frame then for _, name in ipairs(args.MethodHooks) do hooksecurefunc(frame, name, DoTryToShow) end end end end if self.db.firstUse then self.db.firstUse = nil end end local UNDERLIGHT_ANGLER_ID = 133755 function ap:SetArtifact(itemID, name, texture, currentXP, pointsSpent) print('|cFF00FF00SetArtifact()|r') if not self.profile then return end local artifacts = self.profile.artifacts local multi = C_ArtifactUI.GetArtifactKnowledgeMultiplier() self.profile.knowledgeMultiplier = multi or self.profile.knowledgeMultiplier print('multiplier:', multi) if itemID then self.currentEquipped = itemID artifacts[itemID] = artifacts[itemID] or {} table.wipe(artifacts[itemID]) local artifact = artifacts[itemID] artifact.name = name artifact.texture = texture artifact.currentXP = currentXP artifact.level = pointsSpent local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent) artifact.cost = cost local pointsAvailable = pointsSpent local actualCost = cost local actualXP = currentXP while actualXP >= actualCost do pointsAvailable = pointsAvailable + 1 actualXP = actualXP - actualCost print(pointsAvailable, '-', actualCost, '=', actualXP) actualCost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable) end print('updating', itemID, name, currentXP, pointsSpent, pointsAvailable, actualXP) artifact.actualXP = actualXP artifact.actualLevel = pointsAvailable artifact.actualCost = actualCost end 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:Reanchor() if Veneer then Veneer:DynamicReanchor() end end function ap:OnShow() print('|cFFFFFF00OnShow()|r') for name, args in pairs(PENDING_HOOKS) do if _G[name] then AddFrameHooks(_G[name], args) PENDING_HOOKS[name] = nil end end self.enabled = true self:ScanAllBags() self:Reanchor() end function ap:OnHide() print('|cFF88FF00OnHide()|r') self:Reanchor() end function ap:OnEnter() GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') GameTooltip:AddLine(self.bagAP) GameTooltip:AddLine(self.bankAP) end function ap:TryToShow() print('|cFFFFFF00TryToShow()') if not InCombatLockdown() then for _, name in ipairs(FRAME_LIST) do --print(name, (_G[name] and _G[name]:IsShown())) if _G[name] and _G[name]:IsShown() then if self:IsShown() then self:Update() else self:Show() end return end end end self:Hide() end function ap:OnEvent(event, ...) print('|cFF00FF88OnEvent()', event, ...) if event == 'PLAYER_ENTERING_WORLD' then self:TryToShow() elseif event == 'BAG_UPDATE' then local containerID = ... self:QueueBag(containerID) elseif event == 'PLAYER_BANKSLOTS_CHANGED' then self:ScanAllBags() elseif event == 'BAG_UPDATE_DELAYED' then if not self.firstHit then self.firstHit = true else self:ScanAllBags() end elseif event == 'BANKFRAME_OPENED' then self.bankAccess = true self:ScanAllBags() elseif event == 'BANKFRAME_CLOSED' then self.bankAccess = nil elseif event == 'ARTIFACT_UPDATE' then local newItem = ... if newItem then local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetArtifactInfo() self:SetArtifact(itemID, name, texture, currentXP, pointsSpent) self:ScanAllBags(self.bankAccess) end elseif event == 'ARTIFACT_XP_UPDATE' then local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetEquippedArtifactInfo() self:SetArtifact(itemID, name, texture, currentXP, pointsSpent) self:ScanAllBags(self.bankAccess) elseif event == 'PLAYER_REGEN_ENABLED' then if self.enabled then if self.queuedScan then self:ScanAllBags(self.backAccess) else self:TryToShow() end end elseif event == 'PLAYER_REGEN_DISABLED' then self:Hide() end end function ap:OnUpdate() if #self.scanQueue >= 1 then local scanInfo = tremove(self.scanQueue, 1) end end function ap:OnMouseDown() self.enabled = nil self:Hide() end function ap:Update() if not self:IsShown() then print('|cFFFF4400Update()|r') return end print('|cFF00FFFFUpdate()|r') local bankText, bagText if not self.profile.knowledgeMultiplier then bankText = '|cFF00FF00Shift-Right-Click an artifact weapon to start building data.' elseif not (self.bankAP and self.bagAP) then bankText = '|cFFFF0000Open bank frame to count all AP|r ' else if (self.bagAP + self.bankAP) == 0 then bankText = '|cFFFF4400No Artifact Power tokens on hand|r' else if self.bagAP and (self.bagAP > 0) then bankText = '|cFFFFFFFF' .. tostring(self.bagAP) .. '|r' end if self.bankAP and (self.bankAP > 0) then bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..tostring(self.bankAP)..'|r' end end end if self.fishingAP and self.fishingAP >= 1 then bankText = (bankText and (bankText .. ' ') or '') .. '|cFF0088FF' .. tostring(self.fishingAP) .. ' fishing AP|r' end self.SummaryHeader:SetText(bankText) local numButtons = 0 local contentsHeight = 64 if self.profile.knowledgeMultiplier then numButtons = self:UpdateArtifactButtons() contentsHeight = contentsHeight + self:UpdateItemButtons() end self:SetWidth(64*numButtons + 4 * (numButtons+1)) self:SetHeight(16 + self.SummaryHeader:GetHeight() + contentsHeight) self:Reanchor() end function ap:UpdateArtifactButtons() -- Artifact icons, in no particular order self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo() local numButtons = 0 local lastFrame = self local fishingID, fishingData local index, button for itemID, artifact in pairs(self.profile.artifacts) do if (itemID == UNDERLIGHT_ANGLER_ID) then if VeneerData.ArtifactPower.EnableFishing then fishingID = itemID fishingData = artifact end else numButtons = numButtons + 1 button = self.Artifact[numButtons] button.relativeFrame = lastFrame lastFrame = button:SetButton(itemID, artifact, numButtons, (self.equippedID == itemID)) end end if fishingData then numButtons = numButtons + 1 local button = self.Artifact[numButtons] button.relativeFrame = lastFrame button:SetButton(fishingID, fishingData, numButtons, self.equippedID == fishingID) end for i = numButtons+ 1, #self.Artifact do print('hide', i) self.Artifact[i]:Hide() end return numButtons end function ap:UpdateItemButtons() print('|cFF00FFFFUpdateItemButtons()|r') local lastFrame, upFrame local numButtons = 0 local buttonsHeight = 0 local buttonWidth = 0 for index, button in ipairs(self.Tokens) do if button.numItems >= 1 then if button.itemName then self:SetItemAction(button) end button:ClearAllPoints() numButtons = numButtons + 1 print(index, button:GetID(), button.Icon:GetTexture()) if numButtons == 1 then button:SetPoint('TOPLEFT', self, 'TOPLEFT', 4, -76) upFrame = button buttonsHeight = 52 elseif mod(numButtons,8) == 1 then button:SetPoint('TOPLEFT', upFrame, 'BOTTOMLEFT', 0, -2) upFrame = button buttonsHeight = buttonsHeight + 52 else button:SetPoint('TOPLEFT', lastFrame, 'TOPRIGHT', 2, 0) end button.Count:SetText(button.numItems) lastFrame = button button:Show() else button:Hide() end end return buttonsHeight end function ap:SetItemAction(button, name) name = name or self.itemName if InCombatLockdown() then self.itemName = name return else button:SetAttribute('*type*','item') button:SetAttribute('*item*', name) end end function ap:GetItemButton(itemID, texture, itemAP) print('|cFF00FFFFGetItemButton()|r', itemID, texture, itemAP) local button = self.ItemButtons[itemID] if not button then button = CreateFrame('Button', 'VeneerAPToken'..itemID, self, 'VeneerItemButton') button.baseAP = itemAP button:SetPushedTexture([[Interface\Buttons\UI-Quickslot-Depress]]) button:SetHighlightTexture([[Interface\Buttons\ButtonHilight-Square]],"ADD") button:SetID(itemID) button.numItems = 0 button.Icon:SetTexture(texture) button:RegisterForClicks("AnyUp") self:SetItemAction(button, GetItemInfo(itemID)) print(' created') self.ItemButtons[itemID] = button self.numItems = self.numItems + 1 end local itemAPtext = itemAP * self.profile.knowledgeMultiplier if itemAPtext >= 100000 then itemAPtext = floor(itemAPtext/1000) .. 'k' elseif itemAPtext >= 1000 then itemAPtext = (floor(itemAPtext/100)/10 ) .. 'k' end button.Label:SetText(itemAPtext) button.numItems = button.numItems + 1 return button end function ap:GetItemAP(itemID, itemLink, bagData) if not self.cache[itemID] then print('doing tooltip scan') self.tooltip:SetOwner(self, 'ANCHOR_NONE') self.tooltip:SetHyperlink(itemLink) 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(itemLink, '-', tonumber(text)) local itemAP = tonumber(text) if itemAP then itemAP = itemAP / self.profile.knowledgeMultiplier self.cache[itemID] = itemAP end end end end local fishingText = _G[TOOLTIP_NAME .. 'TextLeft3']:GetText() if fishingText and fishingText:match('fishing artifact') then local fishingAP = fishingText:match("%d+") fishingAP = tonumber(fishingAP) if fishingAP then self.cache[itemID] = fishingAP self.fishingCache[itemID] = true end end else self.cache[itemID] = 0 end end return self.cache[itemID], self.fishingCache[itemID] 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 bagData.fishingAP = 0 bagData.items = bagData.items or {} table.wipe(bagData.items) for slotID = 1, numSlots do local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(id, slotID) if link then local itemID = GetContainerItemID(id, slotID) local name, _, quality, iLevel, reqLevel, class, subclass = GetItemInfo(link) if class == 'Consumable' and subclass == 'Other' then --print(GetItemInfo(link)) local itemAP, isFishingAP = self:GetItemAP(itemID, link) --print(itemAP, isFishingAP) if itemAP and (itemAP > 0) then local itemButton = self:GetItemButton(itemID, texture, itemAP) if isFishingAP then bagData.fishingItems = (bagData.fishingItems or 0) + 1 bagData.fishingAP = (bagData.fishingAP or 0) + itemAP else itemAP = itemAP * self.profile.knowledgeMultiplier bagData.numItems = (bagData.numItems or 0) + 1 bagData.totalAP = (bagData.totalAP or 0) + itemAP end bagData.items[itemID] = (bagData.items[itemID] or 0) + 1 end elseif 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 end end local BAG_SLOTS = {0, 1, 2, 3, 4 } local BANK_SLOTS = {-1, 5, 6,7, 8, 9, 10, 11, 12} local ItemCounts = {} function ap:ScanAllBags() if InCombatLockdown() then self.queuedScan = true return end if not self.profile.knowledgeMultiplier then print('need to get knowledge level') return end self.queuedScan = nil print('|cFFFF0088ScanAllBags()|r', self.profile.knowledgeMultiplier) for _, button in ipairs(self.Tokens) do button.numItems = 0 end for _, bagID in ipairs(BAG_SLOTS) do self:ScanBag(bagID) end if self.bankAccess then for _, bagID in ipairs(BANK_SLOTS) do self:ScanBag(bagID) end end self.bankAP = 0 self.bagAP = 0 self.fishingAP = 0 table.wipe(ItemCounts) 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 if bagData.fishingAP then self.fishingAP = self.fishingAP + bagData.fishingAP end end self.lastUpdate = GetTime() self:TryToShow() end VeneerArtifactButtonMixin = {} function VeneerArtifactButtonMixin:SetButton(itemID, artifact, index, equipped) print(itemID, index) print(artifact.name, artifact.texture, artifact.currentXP) self:SetID(itemID) for k,v in pairs(artifact) do --print('::',k,v) self[k] = v end -- this can change between artifact parses local potentialPoints = self.actualLevel local totalAP = (itemID ~= UNDERLIGHT_ANGLER_ID) and ((self:GetParent().bankAP or 0) + (self:GetParent().bagAP or 0)) or (self:GetParent().fishingAP or 0) print(totalAP) local potentialXP = self.actualXP + totalAP self.potentialXP = potentialXP local potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints) while potentialXP >= potentialCost do potentialXP = potentialXP - potentialCost potentialPoints = potentialPoints + 1 print('inc estimate', potentialXP, potentialPoints) potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints) end self.potentialCost = potentialCost self.potentialLevel = potentialPoints self.potentialAdjustedXP = potentialXP if index ~= 1 then self:ClearAllPoints() self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPRIGHT', 4, 0) else self:ClearAllPoints() self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', 4, -4) end self.isEquipped = equipped self:Update() self:Show() return self end function VeneerArtifactButtonMixin:Update() local r, g, b = 1, 1, 1 local lR, lG, lB = 1, 1, 0 local levelText = self.level local xpValue = self.currentXP local costValue = self.cost if self.actualLevel ~= self.level then levelText, r,g,b = self.actualLevel, 0,1,0 xpValue, costValue, lR, lG, lB = self.actualXP, self.actualCost, 0, 1, 0 elseif self.potentialLevel ~= self.level then levelText, r, g, b = self.potentialLevel, 0,1,1 xpValue, costValue, lR, lG, lB = self.potentialAdjustedXP, self.potentialCost, 0,1,0 end if xpValue >= 100000 then xpValue = tostring(floor(xpValue/1000))..'k' elseif xpValue > 1000 then xpValue = tostring(floor(xpValue/100)/10)..'k' end if costValue >= 100000 then costValue = tostring(floor(costValue/1000))..'k' elseif costValue >= 1000 then costValue = tostring(floor(costValue/100)/10)..'k' end self.Level:SetText(levelText) self.Level:SetTextColor(r, g, b) self.CurrentXP:SetText(xpValue) self.CurrentXP:SetTextColor(lR, lG, lB) 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 local currentProgress = (self.currentXP < self.cost) and (self.currentXP / self.cost) or 1 if self.level <= 53 then self.CurrentProgress.animateFrom = self.CurrentProgress:GetHeight() or 1 self.CurrentProgress.animateTo = currentProgress * self:GetHeight() self.CurrentProgress:Show() self.ProgressLine:Show() else self.CurrentProgress:Hide() self.ProgressLine:Hide() end if self.potentialXP > self.currentXP then local projectedProgress = (self.potentialAdjustedXP < self.potentialCost) and (self.potentialXP / self.potentialCost) or 1 if (projectedProgress > currentProgress) then self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP') projectedProgress = projectedProgress - currentProgress else self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM') end print('show potential', currentProgress, projectedProgress) self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1 self.AdjustedProgress.animateTo = projectedProgress * self:GetHeight() self.AdjustedLine:Show() self.AdjustedProgress:Show() else self.AdjustedProgress:Hide() self.AdjustedLine:Hide() end self.Icon:SetTexture(self.texture) self:SetSize(64,64) end function VeneerArtifactButtonMixin:AnimateProgress(region) local cTime = GetTime() if not region.animateStart then region.animateStart = cTime end local progressTo, progressFrom = region.animateTo, region.animateFrom local elapsed = cTime - region.animateStart if elapsed >= .5 then region:SetHeight(progressTo) region.animateTo = nil region.animateStart = nil region.animateFrom = nil else local progress = elapsed / .5 local height = (progressFrom + (progressTo - progressFrom) * progress) --print(self:GetName(), progressTo, progressFrom, (progressTo - progressFrom), ceil(progress*10)/10, ceil(height)) region:SetHeight(height) end end function VeneerArtifactButtonMixin:OnUpdate(sinceLast) if self.CurrentProgress.animateTo then self:AnimateProgress(self.CurrentProgress) end if self.AdjustedProgress.animateTo then self:AnimateProgress(self.AdjustedProgress) end end function VeneerArtifactButtonMixin:OnEnter() GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') GameTooltip:SetText(self.name) GameTooltip:AddLine(tostring(self.currentXP) .. ' / '..tostring(self.cost), 1, 1, 0) if self.potentialXP > self.currentXP then GameTooltip:AddLine(tostring(self.potentialXP) .. ' potential XP', 0, 1, 1) if self.potentialAdjustedXP ~= self.potentialXP then GameTooltip:AddLine(tostring(self.potentialAdjustedXP) .. ' / ' .. tostring(self.potentialCost).. ' after', 0, 1, 0) end end if self.actualLevel ~= self.level then GameTooltip:AddLine(tostring(self.actualLevel - self.level) .. ' points unlocked', 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