Mercurial > wow > buffalo2
view Modules/ArtifactPower.lua @ 111:1196c2bad31c
- obtain World Quest AP via WorldPlan
- artifact button text adjustments
- removed from UISpecialFrames to fix hiding on map open
author | Nick@Zahhak |
---|---|
date | Tue, 21 Mar 2017 16:33:51 -0400 |
parents | a41f6b74709a |
children | 7c77fde36287 |
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 FISHING_MAX_TRAITS = 24 local WEAPON_MAX_TRAITS = 54 local BUTTON_SIZE = 48 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') self:RegisterEvent('ITEM_LOCK_CHANGED') -- use to clear bag slot cache data Veneer:AddHandler(self, self.anchorPoint, 2) 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() elseif arg == 'reset' then if self.db then table.wipe(self.db.cache) table.wipe(self.db.fishingCache) end self:Print('Cache data reset.') self:Update() else self:Show() end end self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') end local ShortNumberString = function (value) if value >= 100000 then return tostring(floor(value/1000)) .. 'k' elseif value >= 1000 then return tostring(floor(value/100)/10) .. 'k' else return value end end local IsBagnonOpen = function() return ((BagnonFramebank and BagnonFramebank:IsShown()) or (BagnonFrameinventory and BagnonFrameinventory:IsShown())) end local addonCompatibility = { ['Bagnon'] = { BagFrames = {'BagnonFrameinventory'}, BankFrames = {'BagnonFramebank'}, FrameMethods = { ['Hide'] = IsBagnonOpen, ['Show'] = IsBagnonOpen }, PostHooks = {}, MethodClass = 'Bagnon', MethodHooks = {'BANK_OPENED', 'BANKFRAME_CLOSED'}, } } local queued_hooks = {} local function CreateHook(...) if select('#', ...) >= 2 then tinsert(queued_hooks, {...}) end if not InCombatLockdown() then local info = tremove(queued_hooks) while info do --[[local oFunc = tremove(info, #info) local args = info local func = function(...) print('|cFFFF0088Callback:|r', unpack(args)) oFunc(...) end print('hooking', unpack(info), oFunc, func) hooksecurefunc(unpack(info), func) --]] hooksecurefunc(unpack(info)) info = tremove(queued_hooks) end end end local function AddFrameHooks(frame, args) for funcName, func in pairs(args.FrameMethods) do print('binding', frame:GetName(), funcName, 'to', tostring(func)) CreateHook(frame, funcName, function() print(frame:GetName(), funcName, 'hook') VeneerArtifactPower:TryToShow() end) 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.profile = self.db[guid] self.profile.cache = self.profile.cache or {} self.profile.cache.bagItems = self.profile.cache.bagItems or {} self.profile.cache.bags = self.profile.cache.bags or {} self.profile.cache.fishing = self.profile.cache.fishing or {} self.profile.cache.items = self.profile.cache.items or {} self.profile.bagslots = self.profile.bagslots or {} self.profile.artifacts = self.profile.artifacts or {} self.updateSummary = true self.cache = self.profile.cache VeneerArtifactPowerTimer:SetScript('OnUpdate', function() self:OnUpdate() end) local DoTryToShow = function() self:TryToShow() end CreateHook("OpenBackpack", DoTryToShow) CreateHook("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] print('hook entry', name, tostring(oFunc)) CreateHook(name, function(...) print('|cFFFF0088' .. name .. '|r', ..., 'original', tostring(oFunc)) oFunc(...) self:TryToShow() end) end local frame = _G[args.MethodClass] if frame then print() for _, name in ipairs(args.MethodHooks) do CreateHook(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:ResetCache() table.wipe(self.cache.items) table.wipe(self.cache.fishing) table.wipe(self.cache.bags) table.wipe(self.cache.bagItems) self:ScanAllBags() 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', debugstack()) 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('test:', name, (_G[name] and _G[name]:IsShown())) if _G[name] and _G[name]:IsVisible() then if self:IsShown() then self:Update() else self:Show() end return end end end print('failed tests') 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 == 'ITEM_LOCK_CHANGED' then local containerID, slotID = ... if self.cache.bags[containerID] and self.cache.bags[containerID][slotID] then self.cache.bags[containerID][slotID] = nil self.cache.fishing[containerID][slotID] = nil end 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.queuedScan then self:ScanAllBags(self.backAccess) else self:TryToShow() end if #queued_hooks >= 1 then CreateHook() 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 if IsShiftKeyDown() then self.Refresh:Show() else self.Refresh:Hide() 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 and (self.bagAP > 0) then bankText = 'Inventory: |cFFFFFFFF' .. ShortNumberString(self.bagAP) .. '|r' end if self.bankAP and (self.bankAP > 0) then bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..ShortNumberString(self.bankAP)..' banked|r' end if self.fishingAP and self.fishingAP > 0 then bankText = (bankText and (bankText .. ' | ') or '') .. '|cFF0088FF' .. ShortNumberString(self.fishingAP) .. ' fishing|r' end end self.worldQuestAP = 0 if WorldPlan then if not self.worldPlanHooked then WorldPlan:RegisterDataCallback(function() self:Update() end) end local showWQ print('world plan is loaded') local worldQuests = WorldPlan:GetQuestPins() for index, pin in ipairs(worldQuests) do if pin.dataLoaded and (pin.rewardType == WORLD_QUEST_REWARD_TYPE_FLAG_ARTIFACT_POWER) then showWQ = true print(pin.itemNumber) self.worldQuestAP = self.worldQuestAP + pin.itemNumber end end if showWQ then bankText = (bankText and (bankText .. '\n') or '') .. '|cFFFFBB00World Quests:|r |cFFFFFFFF' .. ShortNumberString(self.worldQuestAP) .. '' end end self.SummaryHeader:SetText(bankText) local numButtons = 0 local contentsHeight = 16 + self.SummaryHeader:GetHeight() local contentsWidth = self.SummaryHeader:GetWidth() + 16 if self.profile.knowledgeMultiplier then numButtons = self:UpdateArtifactButtons() if numButtons ~= 0 then contentsHeight = contentsHeight + 64 end contentsWidth = max(contentsWidth, 64*numButtons + 4 * (numButtons+1)) local itemsWidth, itemsHeight = self:UpdateItemButtons() contentsHeight = contentsHeight + itemsHeight contentsWidth = max(contentsWidth, itemsWidth) end if not self.hasArtifacts then self:SetShown(false) end self:SetWidth(contentsWidth) self:SetHeight(contentsHeight) self:Reanchor() end function ap:UpdateArtifactButtons() -- Artifact icons, in no particular order self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo() self.canAddAP = nil self.canAddFishingAP = nil local hasArtifacts 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 if artifact.level < FISHING_MAX_TRAITS then if itemID == self.equippedID then self.canAddFishingAP = true end end else if artifact.level < WEAPON_MAX_TRAITS then if itemID == self.equippedID then self.canAddAP = true end hasArtifacts = true numButtons = numButtons + 1 button = self.Artifact[numButtons] button.relativeFrame = lastFrame lastFrame = button:SetButton(itemID, artifact, numButtons, (self.equippedID == itemID), nil) end end end if fishingData and (self.fishingAP and self.fishingAP > 0) then numButtons = numButtons + 1 hasArtifacts = true local button = self.Artifact[numButtons] button.relativeFrame = lastFrame button.isFishing = true button:SetButton(fishingID, fishingData, numButtons, self.equippedID == fishingID) end self.hasArtifacts = hasArtifacts 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 apType if self.canAddFishingAP then apType = true elseif not self.canAddAP then for index, button in ipairs(self.Tokens) do button:Hide() end return 0, 0 end local lastFrame, upFrame local numButtons = 0 local buttonsHeight = 0 local buttonsWidth = 0 for index, button in ipairs(self.Tokens) do if (button.numItems >= 1) and (button.isFishingAP == apType) then if button.itemName then self:SetItemAction(button) end button:ClearAllPoints() numButtons = numButtons + 1 local col = mod(numButtons,8) print(index, button:GetID(), button.Icon:GetTexture()) if numButtons == 1 then button:SetPoint('TOPLEFT', self, 'TOPLEFT', 4, -76) upFrame = button buttonsHeight = 52 else if col == 1 then button:SetPoint('TOPLEFT', upFrame, 'BOTTOMLEFT', 0, -2) upFrame = button buttonsHeight = buttonsHeight + 52 else button:SetPoint('TOPLEFT', lastFrame, 'TOPRIGHT', 2, 0) end end button.Count:SetText(button.numItems) lastFrame = button button:Show() else button:Hide() end buttonsWidth = min(numButtons, 8) * (BUTTON_SIZE) end if buttonsWidth ~= 0 then buttonsWidth = buttonsWidth + 8+ ((min(numButtons, 8)-1)*2) end return buttonsWidth, 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, fishing) 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") button.isFishingAP = fishing self:SetItemAction(button, GetItemInfo(itemID)) print(' created') self.ItemButtons[itemID] = button self.numItems = self.numItems + 1 end local itemAPtext = itemAP 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.items[itemID] then print('doing tooltip scan', itemLink, itemID) self.tooltip:SetOwner(self, 'ANCHOR_NONE') self.tooltip:SetHyperlink(itemLink) self.tooltip:Show() local numLines = self.tooltip:NumLines() if numLines >= 3 then for i = 3, numLines do local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText() if text then text = text:lower():gsub(',', '') if text:match('equipped artifact') then print(itemLink, '-', tonumber(text)) local itemAP = text:match('%d+') if itemAP then itemAP = itemAP self.cache.items[itemID] = tonumber(itemAP) end end if text:match('fishing artifact') then local fishingAP = text:match("%d+") fishingAP = fishingAP print(itemLink, 'fishing', tonumber(text)) if fishingAP then self.cache.items[itemID] = tonumber(fishingAP) self.cache.fishing[itemID] = true end end end end else self.cache.items[itemID] = 0 end end return self.cache.items[itemID], self.cache.fishing[itemID] end 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() if multi and (self.profile.knowledgeMultiplier ~= multi) then table.wipe(self.cache.items) table.wipe(self.cache.fishing) end 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.currentCost = 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: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) local c = self.cache c.bagItems[id] = c.bagItems[id] or {} c.bags[id] = c.bags[id] or {} c.fishing[id] = c.fishing[id] or {} 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' or subclass == 'Cooking' then --print(GetItemInfo(link)) local itemAP, isFishingAP if c.bags[id][slotID] and (c.bagItems[id][slotID] == itemID) then --print('cached slot', id, slotID, name) itemAP = c.bags[id][slotID] isFishingAP = c.fishing[id] and c.fishing[id][slotID] else itemAP, isFishingAP = self:GetItemAP(itemID, link) c.bagItems[id][slotID] = itemID c.bags[id][slotID] = itemAP c.fishing[id][slotID] = isFishingAP end --print(itemAP, isFishingAP) if itemAP and (itemAP > 0) then local itemButton = self:GetItemButton(itemID, texture, itemAP, isFishingAP) if isFishingAP then bagData.fishingItems = (bagData.fishingItems or 0) + 1 bagData.fishingAP = (bagData.fishingAP or 0) + itemAP else itemAP = itemAP 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('artifact weapon', itemID, link, id, slotID) self.profile.artifacts[itemID].containerID = id self.profile.artifacts[itemID].slotID = slotID else --print('skipping', class, subclass, link) 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, bagData.fishingAP) 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.queuedScan = nil self:TryToShow() end VeneerArtifactButtonMixin = {} function VeneerArtifactButtonMixin:SetButton(itemID, artifact, index, equipped, fishing) print(itemID, index) print(artifact.name, artifact.texture, artifact.currentXP) self:SetID(itemID) if not artifact.currentCost then artifact.currentCost = artifact.cost end for k,v in pairs(artifact) do --print('::',k,v) self[k] = v end self.isFishing = fishing -- 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 self.maxCost = self.currentCost for i = self.level + 1, #POINT_COSTS do self.maxCost = self.maxCost + POINT_COSTS[i] end 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 = ShortNumberString(self.currentXP) local costValue = self.currentCost if self.actualLevel ~= self.level then levelText, r,g,b = self.actualLevel, 0,1,0 xpValue, costValue, lR, lG, lB = ShortNumberString(self.potentialXP) .. '\n' .. ShortNumberString(self.potentialCost-self.potentialXP), 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 = ShortNumberString(self.potentialXP) .. '\n' .. ShortNumberString(self.potentialCost-self.potentialXP), self.potentialCost, 0,1,1 else xpValue, lR, lG, lB = ShortNumberString(self.actualXP) .. '\n|cFFFFFF00' .. ShortNumberString(self.actualCost-self.actualXP)..'|r', 1, 1, 1 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.currentCost) and (self.currentXP / self.currentCost) 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(ShortNumberString(self.currentXP) .. ' / '..ShortNumberString(self.currentCost), 1, 1, 0) if self.potentialXP > self.currentXP then GameTooltip:AddLine(ShortNumberString(self.potentialXP) .. ' potential XP', 0, 1, 1) if self.potentialAdjustedXP ~= self.potentialXP then GameTooltip:AddLine(ShortNumberString(self.potentialAdjustedXP) .. ' / ' .. ShortNumberString(self.potentialCost).. ' after', 0, 1, 0) end end if self.actualLevel ~= self.level then GameTooltip:AddLine(ShortNumberString(self.actualLevel - self.level) .. ' points unlocked', 0, 1, 1) end if self.currentXP < self.currentCost then GameTooltip:AddLine(ShortNumberString(self.currentCost - self.currentXP) .. ' needed') end GameTooltip:Show() end function VeneerArtifactButtonMixin:OnLeave() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function VeneerArtifactButtonMixin:OnHide() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function VeneerArtifactButtonMixin:OnClick(button, down) if self.isEquipped then SocketInventoryItem(16) else if IsShiftKeyDown() then SocketContainerItem(self.containerID, self.slotID) else end end end