Nenue@97: -- Veneer Nenue@97: -- ArtifactPower.lua Nenue@97: -- Created: 1/15/2017 11:44 PM Nenue@97: -- %file-revision% Nenue@97: -- Nenue@97: Nenue@97: local print = DEVIAN_WORKSPACE and function(...) print('VnAP', ...) end or nop Nenue@97: VeneerArtifactPowerMixin = { Nenue@99: numItems = 0, Nenue@99: Tokens = {}, Nenue@101: cache = {}, Nenue@101: fishingCache = {}, Nenue@101: scanQueue = {}, Nenue@99: ItemButtons = {}, Nenue@97: anchorPoint = 'TOP', Nenue@97: anchorFrom = 'TOP', Nenue@97: } Nenue@101: local defaultSettings = { Nenue@101: firstUse = true, Nenue@101: autoHide = true, Nenue@101: } Nenue@97: local ap = VeneerArtifactPowerMixin Nenue@97: local BAGS_TO_SCAN = {BACKPACK_CONTAINER } Nenue@97: local TOOLTIP_NAME = 'VeneerAPScanner' Nenue@98: local POINT_COSTS = { Nenue@98: 100, 300, 325, 350, 375, Nenue@98: 400, 425, 450, 525, 625, Nenue@98: 750, 875, 1000, 6840, 8830, Nenue@98: 11280, 14400, 18620, 24000, 30600, Nenue@98: 39520, 50880, 64800, 82500, 105280, Nenue@98: 138650, 182780, 240870, 325520, 417560, Nenue@98: 546000, 718200, 946660, 1245840, 1635200, Nenue@98: 191500, 2010000, 2110000, 2215000, 2325000, Nenue@98: 2440000, 2560000, 2690000, 2825000, 2965000, Nenue@98: 3115000, 3270000, 3435000, 3605000, 3785000, Nenue@98: 3975000, 4175000, 4385000, 4605000 Nenue@98: } Nenue@97: Nenue@99: local FRAME_LIST = {'ContainerFrame1', 'BankFrame'} Nenue@99: local BAG_FRAMES = {'ContainerFrame1'} Nenue@99: local BANK_FRAMES = {'BankFrame'} Nenue@99: Nenue@97: function ap:OnLoad() Nenue@97: self:RegisterEvent('BAG_UPDATE') -- use to obtain bag IDs to scan Nenue@97: self:RegisterEvent('BAG_UPDATE_DELAYED') -- use to trigger actual scan activity Nenue@97: self:RegisterEvent('BANKFRAME_OPENED') -- determine when bank info is available Nenue@97: self:RegisterEvent('BANKFRAME_CLOSED') -- " " " Nenue@97: self:RegisterEvent('ARTIFACT_UPDATE') -- when artifact data has changed Nenue@98: self:RegisterEvent('ARTIFACT_XP_UPDATE') -- when artifact xp has changed (but not necessarily data) Nenue@97: self:RegisterEvent('PLAYER_REGEN_ENABLED') Nenue@97: self:RegisterEvent('PLAYER_REGEN_DISABLED') Nenue@99: self:RegisterEvent('PLAYER_ENTERING_WORLD') Nick@108: self:RegisterEvent('ITEM_LOCK_CHANGED') -- use to clear bag slot cache data Nick@108: Veneer:AddHandler(self, self.anchorPoint, 2) Nenue@97: SLASH_VENEER_AP1 = "/vap" Nenue@97: SLASH_VENEER_AP2 = "/veneerap" Nenue@98: SlashCmdList.VENEER_AP = function(arg) Nenue@98: if arg == 'fishing' then Nenue@98: if VeneerData.ArtifactPower.EnableFishing then Nenue@98: VeneerData.ArtifactPower.EnableFishing = nil Nenue@98: else Nenue@98: VeneerData.ArtifactPower.EnableFishing = true Nenue@98: end Nenue@98: self:Print('Show Underlight Angler:', (VeneerData.ArtifactPower.EnableFishing and 'ON' or 'OFF')) Nenue@98: self:Update() Nick@108: elseif arg == 'reset' then Nick@108: if self.db then Nick@108: table.wipe(self.db.cache) Nick@108: table.wipe(self.db.fishingCache) Nick@108: end Nick@108: self:Print('Cache data reset.') Nick@108: self:Update() Nenue@98: else Nenue@98: self:Show() Nenue@98: end Nenue@97: end Nenue@97: Nenue@97: self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') Nenue@99: tinsert(UISpecialFrames, self:GetName()) Nenue@99: Nenue@97: Nenue@97: end Nick@108: local ShortNumberString = function (value) Nick@108: if value >= 100000 then Nick@108: return tostring(floor(value/1000)) .. 'k' Nick@108: elseif value >= 1000 then Nick@108: return tostring(floor(value/100)/10) .. 'k' Nick@108: else Nick@108: return value Nick@108: end Nick@108: end Nenue@97: Nenue@102: Nenue@102: local IsBagnonOpen = function() Nenue@102: return ((BagnonFramebank and BagnonFramebank:IsShown()) or (BagnonFrameinventory and BagnonFrameinventory:IsShown())) Nenue@102: end Nenue@99: local addonCompatibility = { Nenue@99: ['Bagnon'] = { Nenue@99: BagFrames = {'BagnonFrameinventory'}, Nenue@99: BankFrames = {'BagnonFramebank'}, Nenue@102: FrameMethods = { Nenue@103: ['Hide'] = IsBagnonOpen, Nenue@103: ['Show'] = IsBagnonOpen Nenue@102: }, Nenue@103: PostHooks = {}, Nenue@99: MethodClass = 'Bagnon', Nenue@102: MethodHooks = {'BANK_OPENED', 'BANKFRAME_CLOSED'}, Nenue@102: Nenue@99: } Nenue@97: } Nenue@97: Nenue@103: Nenue@103: Nenue@103: local queued_hooks = {} Nenue@103: local function CreateHook(...) Nenue@103: if select('#', ...) >= 2 then Nenue@103: tinsert(queued_hooks, {...}) Nenue@103: end Nenue@103: if not InCombatLockdown() then Nenue@103: local info = tremove(queued_hooks) Nenue@103: while info do Nenue@103: print('hooking', unpack(info)) Nenue@103: hooksecurefunc(unpack(info)) Nenue@103: info = tremove(queued_hooks) Nenue@103: end Nenue@103: Nenue@103: end Nenue@103: end Nenue@103: Nenue@102: local function AddFrameHooks(frame, args) Nenue@102: for funcName, func in pairs(args.FrameMethods) do Nenue@102: print('binding', frame:GetName(), funcName, 'to', tostring(func)) Nenue@103: CreateHook(frame, funcName, function() Nenue@103: VeneerArtifactPower:TryToShow() Nenue@103: end) Nenue@102: end Nenue@102: end Nenue@102: local PENDING_HOOKS = {} Nenue@102: Nenue@102: local function RegisterInventoryFrame(name, listType, args) Nenue@102: print('register', name, 'as inventory frame type =', (listType == BAG_FRAMES) and 'bags' or 'bank') Nenue@102: tinsert(FRAME_LIST, name) Nenue@102: tinsert(listType, name) Nenue@102: if _G[name] then Nenue@102: AddFrameHooks(_G[name], args) Nenue@102: else Nenue@102: PENDING_HOOKS[name] = args Nenue@102: end Nenue@102: end Nenue@102: Nenue@97: function ap:Setup() Nenue@97: print(self:GetName()..':Setup()') Nenue@97: local guid = UnitGUID('player') Nenue@97: VeneerData.ArtifactPower = VeneerData.ArtifactPower or defaultSettings Nenue@101: self.db = VeneerData.ArtifactPower Nenue@101: self.db[guid] = self.db[guid] or {} Nenue@101: self.db.cache = self.db.cache or {} Nenue@101: self.db.fishingCache = self.db.fishingCache or {} Nenue@101: Nenue@101: for i, data in pairs(self.cache) do Nenue@101: -- bring in anything found before player data is active Nenue@101: self.db.cache[i] = data Nenue@101: end Nenue@101: for i, data in pairs(self.fishingCache) do Nenue@101: self.db.fishingCache[i] = data Nenue@101: end Nenue@101: Nenue@101: Nenue@101: self.profile = self.db[guid] Nick@108: self.profile.cache = self.profile.cache or {} Nick@108: self.profile.cache.bagItems = self.profile.cache.bagItems or {} Nick@108: self.profile.cache.bags = self.profile.cache.bags or {} Nick@108: self.profile.cache.fishing = self.profile.cache.fishing or {} Nick@108: self.profile.cache.items = self.profile.cache.items or {} Nenue@97: self.profile.bagslots = self.profile.bagslots or {} Nenue@97: self.profile.artifacts = self.profile.artifacts or {} Nenue@97: self.updateSummary = true Nick@108: self.cache = self.profile.cache Nenue@97: Nenue@101: VeneerArtifactPowerTimer:SetScript('OnUpdate', function() Nenue@101: self:OnUpdate() Nenue@101: end) Nenue@101: Nenue@99: local DoTryToShow = function() Nenue@99: self:TryToShow() Nenue@99: end Nenue@103: CreateHook("OpenBackpack", DoTryToShow) Nenue@103: CreateHook("CloseBackpack", DoTryToShow) Nenue@99: Nenue@97: -- Bagnon compatibility Nenue@97: -- todo: ArkInventory, Elv, etc Nenue@99: for addon, args in pairs(addonCompatibility) do Nenue@99: if IsAddOnLoaded(addon) then Nenue@102: Nenue@99: for _, name in ipairs(args.BagFrames) do Nenue@102: RegisterInventoryFrame(name, BAG_FRAMES, args) Nenue@99: end Nenue@99: for _, name in ipairs(args.BankFrames) do Nenue@102: RegisterInventoryFrame(name, BANK_FRAMES, args) Nenue@99: end Nenue@102: Nenue@102: -- should only specify non-secure functions in this table Nenue@99: for _, name in ipairs(args.PostHooks) do Nenue@99: local oFunc = _G[name] Nenue@103: print('hook entry', name, tostring(oFunc)) Nenue@103: CreateHook(name, function(...) Nenue@103: print('|cFFFF0088' .. name .. '|r', ..., 'original', tostring(oFunc)) Nenue@99: oFunc(...) Nenue@99: self:TryToShow() Nenue@103: end) Nenue@99: end Nenue@99: local frame = _G[args.MethodClass] Nenue@99: if frame then Nenue@103: print() Nenue@99: for _, name in ipairs(args.MethodHooks) do Nenue@103: CreateHook(frame, name, DoTryToShow) Nenue@99: end Nenue@97: end Nenue@97: end Nenue@97: end Nenue@101: Nenue@101: if self.db.firstUse then Nenue@101: self.db.firstUse = nil Nenue@101: Nenue@101: end Nenue@99: end Nenue@97: Nenue@97: local UNDERLIGHT_ANGLER_ID = 133755 Nenue@97: Nenue@97: function ap:QueueBag(containerID) Nenue@97: containerID = tonumber(containerID) Nenue@97: if not containerID then Nenue@97: return Nenue@97: end Nenue@97: Nenue@97: if not tContains(BAGS_TO_SCAN, containerID) then Nenue@97: print(' queueing', containerID, type(containerID), #BAGS_TO_SCAN , 'in line') Nenue@97: BAGS_TO_SCAN[#BAGS_TO_SCAN + 1] = containerID Nenue@97: end Nenue@97: end Nenue@97: Nenue@99: function ap:Reanchor() Nenue@99: if Veneer then Nenue@99: Veneer:DynamicReanchor() Nenue@99: end Nenue@99: end Nenue@99: Nenue@97: function ap:OnShow() Nenue@99: print('|cFFFFFF00OnShow()|r') Nenue@102: Nenue@102: for name, args in pairs(PENDING_HOOKS) do Nenue@102: if _G[name] then Nenue@102: AddFrameHooks(_G[name], args) Nenue@102: PENDING_HOOKS[name] = nil Nenue@102: end Nenue@102: end Nenue@102: Nenue@102: Nenue@97: self.enabled = true Nenue@99: self:ScanAllBags() Nenue@99: self:Reanchor() Nenue@97: end Nenue@97: function ap:OnHide() Nenue@99: print('|cFF88FF00OnHide()|r') Nenue@99: self:Reanchor() Nenue@97: end Nenue@97: function ap:OnEnter() Nenue@97: Nenue@97: GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') Nenue@97: Nenue@99: Nenue@97: GameTooltip:AddLine(self.bagAP) Nenue@97: GameTooltip:AddLine(self.bankAP) Nenue@97: Nenue@97: end Nenue@97: Nenue@99: function ap:TryToShow() Nenue@99: Nenue@99: print('|cFFFFFF00TryToShow()') Nenue@99: Nenue@99: if not InCombatLockdown() then Nenue@99: for _, name in ipairs(FRAME_LIST) do Nenue@103: print('test:', name, (_G[name] and _G[name]:IsShown())) Nenue@99: if _G[name] and _G[name]:IsShown() then Nenue@99: if self:IsShown() then Nenue@99: self:Update() Nenue@99: else Nenue@99: self:Show() Nenue@99: end Nenue@99: return Nenue@99: end Nenue@99: end Nenue@99: end Nenue@99: Nenue@99: Nenue@99: self:Hide() Nenue@99: end Nenue@99: Nenue@99: Nenue@97: function ap:OnEvent(event, ...) Nenue@99: print('|cFF00FF88OnEvent()', event, ...) Nenue@99: if event == 'PLAYER_ENTERING_WORLD' then Nenue@99: self:TryToShow() Nenue@99: elseif event == 'BAG_UPDATE' then Nenue@97: local containerID = ... Nick@108: Nick@108: Nenue@97: self:QueueBag(containerID) Nick@108: elseif event == 'ITEM_LOCK_CHANGED' then Nick@108: Nick@108: local containerID, slotID = ... Nick@108: Nick@108: if self.cache.bags[containerID] and self.cache.bags[containerID][slotID] then Nick@108: self.cache.bags[containerID][slotID] = nil Nick@108: self.cache.fishing[containerID][slotID] = nil Nick@108: end Nick@108: Nick@108: Nenue@97: elseif event == 'PLAYER_BANKSLOTS_CHANGED' then Nenue@99: self:ScanAllBags() Nenue@97: elseif event == 'BAG_UPDATE_DELAYED' then Nenue@99: if not self.firstHit then Nenue@99: self.firstHit = true Nenue@99: else Nenue@99: self:ScanAllBags() Nenue@99: end Nenue@97: elseif event == 'BANKFRAME_OPENED' then Nenue@97: self.bankAccess = true Nenue@99: self:ScanAllBags() Nenue@97: elseif event == 'BANKFRAME_CLOSED' then Nenue@99: self.bankAccess = nil Nenue@97: elseif event == 'ARTIFACT_UPDATE' then Nenue@98: local newItem = ... Nenue@98: if newItem then Nenue@98: local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetArtifactInfo() Nenue@98: self:SetArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@98: self:ScanAllBags(self.bankAccess) Nenue@98: end Nenue@98: elseif event == 'ARTIFACT_XP_UPDATE' then Nenue@98: local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetEquippedArtifactInfo() Nenue@98: self:SetArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@98: self:ScanAllBags(self.bankAccess) Nenue@97: elseif event == 'PLAYER_REGEN_ENABLED' then Nenue@103: Nenue@103: if self.queuedScan then Nenue@103: self:ScanAllBags(self.backAccess) Nenue@103: else Nenue@103: self:TryToShow() Nenue@97: end Nenue@97: Nenue@103: if #queued_hooks >= 1 then Nenue@103: CreateHook() Nenue@103: end Nenue@97: elseif event == 'PLAYER_REGEN_DISABLED' then Nenue@97: self:Hide() Nenue@97: end Nenue@97: end Nenue@97: Nenue@101: function ap:OnUpdate() Nenue@101: if #self.scanQueue >= 1 then Nenue@101: local scanInfo = tremove(self.scanQueue, 1) Nenue@101: Nenue@101: end Nenue@101: end Nenue@101: Nenue@97: function ap:OnMouseDown() Nenue@97: self.enabled = nil Nenue@97: self:Hide() Nenue@97: end Nenue@97: Nenue@97: function ap:Update() Nenue@97: if not self:IsShown() then Nenue@99: print('|cFFFF4400Update()|r') Nenue@97: return Nenue@97: end Nenue@97: print('|cFF00FFFFUpdate()|r') Nenue@97: Nenue@97: local bankText, bagText Nenue@101: if not self.profile.knowledgeMultiplier then Nenue@101: bankText = '|cFF00FF00Shift-Right-Click an artifact weapon to start building data.' Nenue@101: elseif not (self.bankAP and self.bagAP) then Nenue@97: bankText = '|cFFFF0000Open bank frame to count all AP|r ' Nenue@97: else Nenue@98: if (self.bagAP + self.bankAP) == 0 then Nenue@99: bankText = '|cFFFF4400No Artifact Power tokens on hand|r' Nenue@98: else Nenue@98: if self.bagAP and (self.bagAP > 0) then Nenue@98: bankText = '|cFFFFFFFF' .. tostring(self.bagAP) .. '|r' Nenue@98: end Nenue@98: if self.bankAP and (self.bankAP > 0) then Nenue@98: bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..tostring(self.bankAP)..'|r' Nenue@98: end Nenue@98: end Nenue@97: end Nick@108: if self.fishingAP and self.fishingAP > 0 then Nenue@99: bankText = (bankText and (bankText .. ' ') or '') .. '|cFF0088FF' .. tostring(self.fishingAP) .. ' fishing AP|r' Nenue@99: end Nenue@99: Nenue@97: self.SummaryHeader:SetText(bankText) Nenue@97: Nenue@101: local numButtons = 0 Nick@108: local contentsHeight = 16 + self.SummaryHeader:GetHeight() + 64 Nick@108: local contentsWidth = 64 Nenue@101: if self.profile.knowledgeMultiplier then Nenue@101: numButtons = self:UpdateArtifactButtons() Nick@108: Nick@108: contentsWidth = 64*numButtons + 4 * (numButtons+1) Nick@108: Nick@108: local itemsWidth, itemsHeight = self:UpdateItemButtons() Nick@108: contentsHeight = contentsHeight + itemsHeight Nick@108: contentsWidth = max(contentsWidth, itemsWidth) Nenue@101: end Nenue@101: Nenue@101: Nenue@101: Nick@108: self:SetWidth(contentsWidth) Nick@108: self:SetHeight(contentsHeight) Nenue@101: self:Reanchor() Nenue@101: end Nenue@101: Nenue@101: function ap:UpdateArtifactButtons() Nenue@101: Nenue@97: -- Artifact icons, in no particular order Nenue@99: self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo() Nenue@97: local numButtons = 0 Nenue@99: local lastFrame = self Nenue@99: local fishingID, fishingData Nenue@98: local index, button Nenue@97: for itemID, artifact in pairs(self.profile.artifacts) do Nenue@99: if (itemID == UNDERLIGHT_ANGLER_ID) then Nenue@98: if VeneerData.ArtifactPower.EnableFishing then Nenue@98: fishingID = itemID Nenue@98: fishingData = artifact Nenue@98: end Nenue@97: Nenue@98: else Nick@108: if artifact.level ~= 54 then Nick@108: numButtons = numButtons + 1 Nick@108: button = self.Artifact[numButtons] Nick@108: button.relativeFrame = lastFrame Nick@108: lastFrame = button:SetButton(itemID, artifact, numButtons, (self.equippedID == itemID)) Nick@108: end Nenue@97: end Nenue@97: Nenue@98: end Nenue@97: Nick@108: if fishingData and (self.fishingAP and self.fishingAP > 0) then Nenue@98: numButtons = numButtons + 1 Nenue@99: local button = self.Artifact[numButtons] Nenue@99: button.relativeFrame = lastFrame Nenue@99: button:SetButton(fishingID, fishingData, numButtons, self.equippedID == fishingID) Nenue@98: end Nenue@97: Nenue@99: for i = numButtons+ 1, #self.Artifact do Nenue@97: print('hide', i) Nenue@97: self.Artifact[i]:Hide() Nenue@97: end Nenue@97: Nenue@101: return numButtons Nenue@97: end Nenue@97: Nenue@99: Nenue@99: function ap:UpdateItemButtons() Nenue@99: print('|cFF00FFFFUpdateItemButtons()|r') Nenue@99: local lastFrame, upFrame Nenue@99: local numButtons = 0 Nenue@101: local buttonsHeight = 0 Nick@108: local buttonsWidth = 0 Nenue@99: for index, button in ipairs(self.Tokens) do Nenue@99: if button.numItems >= 1 then Nenue@99: if button.itemName then Nenue@99: self:SetItemAction(button) Nenue@99: end Nenue@99: Nenue@99: button:ClearAllPoints() Nenue@99: numButtons = numButtons + 1 Nenue@99: print(index, button:GetID(), button.Icon:GetTexture()) Nenue@99: if numButtons == 1 then Nenue@101: button:SetPoint('TOPLEFT', self, 'TOPLEFT', 4, -76) Nenue@99: upFrame = button Nenue@101: buttonsHeight = 52 Nick@108: buttonsWidth = 50 Nenue@99: else Nick@108: local col = mod(numButtons,8) Nick@108: if col == 1 then Nick@108: button:SetPoint('TOPLEFT', upFrame, 'BOTTOMLEFT', 0, -2) Nick@108: upFrame = button Nick@108: buttonsHeight = buttonsHeight + 52 Nick@108: Nick@108: else Nick@108: button:SetPoint('TOPLEFT', lastFrame, 'TOPRIGHT', 2, 0) Nick@108: Nick@108: end Nick@108: buttonsWidth = max(buttonsWidth, col * 50) Nenue@99: end Nenue@99: button.Count:SetText(button.numItems) Nenue@99: lastFrame = button Nenue@99: button:Show() Nenue@99: else Nenue@99: button:Hide() Nenue@99: end Nenue@99: end Nenue@99: Nenue@101: Nenue@101: Nick@108: return buttonsWidth, buttonsHeight Nenue@99: end Nenue@99: Nenue@99: function ap:SetItemAction(button, name) Nenue@99: name = name or self.itemName Nenue@99: if InCombatLockdown() then Nenue@99: self.itemName = name Nenue@99: return Nenue@99: else Nenue@99: button:SetAttribute('*type*','item') Nenue@99: button:SetAttribute('*item*', name) Nenue@99: end Nenue@99: end Nenue@99: Nenue@99: function ap:GetItemButton(itemID, texture, itemAP) Nenue@99: print('|cFF00FFFFGetItemButton()|r', itemID, texture, itemAP) Nenue@99: local button = self.ItemButtons[itemID] Nenue@101: Nenue@99: if not button then Nenue@99: button = CreateFrame('Button', 'VeneerAPToken'..itemID, self, 'VeneerItemButton') Nenue@101: button.baseAP = itemAP Nenue@101: Nenue@99: button:SetPushedTexture([[Interface\Buttons\UI-Quickslot-Depress]]) Nenue@99: button:SetHighlightTexture([[Interface\Buttons\ButtonHilight-Square]],"ADD") Nenue@99: button:SetID(itemID) Nenue@99: button.numItems = 0 Nenue@99: button.Icon:SetTexture(texture) Nenue@99: button:RegisterForClicks("AnyUp") Nenue@99: self:SetItemAction(button, GetItemInfo(itemID)) Nenue@99: Nenue@99: print(' created') Nenue@99: self.ItemButtons[itemID] = button Nenue@99: self.numItems = self.numItems + 1 Nenue@99: end Nenue@99: Nick@108: local itemAPtext = itemAP Nenue@101: if itemAPtext >= 100000 then Nenue@101: itemAPtext = floor(itemAPtext/1000) .. 'k' Nenue@101: elseif itemAPtext >= 1000 then Nenue@101: itemAPtext = (floor(itemAPtext/100)/10 ) .. 'k' Nenue@101: end Nenue@101: button.Label:SetText(itemAPtext) Nenue@101: Nenue@99: button.numItems = button.numItems + 1 Nenue@99: return button Nenue@99: end Nenue@99: Nenue@101: function ap:GetItemAP(itemID, itemLink, bagData) Nick@108: if not self.cache.items[itemID] then Nenue@101: Nenue@101: print('doing tooltip scan') Nenue@101: self.tooltip:SetOwner(self, 'ANCHOR_NONE') Nenue@101: self.tooltip:SetHyperlink(itemLink) Nenue@101: self.tooltip:Show() Nenue@101: local numLines = self.tooltip:NumLines() Nenue@101: if numLines >= 3 then Nenue@101: local subText = _G[TOOLTIP_NAME .. 'TextLeft2']:GetText() Nenue@101: if subText and subText:match(ARTIFACT_POWER) then Nenue@101: for i = 3, numLines do Nenue@101: local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText() Nenue@101: if text and text:match(ARTIFACT_POWER) then Nenue@101: text = text:gsub('[,%D]', '') Nenue@101: print(itemLink, '-', tonumber(text)) Nenue@101: local itemAP = tonumber(text) Nenue@101: if itemAP then Nick@108: itemAP = itemAP Nick@108: self.cache.items[itemID] = itemAP Nenue@101: end Nenue@101: end Nenue@101: end Nenue@101: end Nenue@101: local fishingText = _G[TOOLTIP_NAME .. 'TextLeft3']:GetText() Nenue@101: if fishingText and fishingText:match('fishing artifact') then Nenue@101: local fishingAP = fishingText:match("%d+") Nenue@101: fishingAP = tonumber(fishingAP) Nenue@101: if fishingAP then Nick@108: self.cache.items[itemID] = fishingAP Nick@108: self.cache.fishing[itemID] = true Nenue@101: end Nenue@101: end Nenue@101: else Nenue@101: Nick@108: self.cache.items[itemID] = 0 Nenue@101: end Nenue@101: end Nick@108: return self.cache.items[itemID], self.cache.fishing[itemID] Nenue@101: end Nenue@101: Nenue@103: function ap:SetArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@103: print('|cFF00FF00SetArtifact()|r') Nenue@103: if not self.profile then Nenue@103: return Nenue@103: end Nenue@103: local artifacts = self.profile.artifacts Nenue@103: Nenue@103: local multi = C_ArtifactUI.GetArtifactKnowledgeMultiplier() Nick@108: if multi and (self.profile.knowledgeMultiplier ~= multi) then Nick@108: table.wipe(self.cache.items) Nick@108: table.wipe(self.cache.fishing) Nick@108: end Nick@108: Nenue@103: self.profile.knowledgeMultiplier = multi or self.profile.knowledgeMultiplier Nenue@103: print('multiplier:', multi) Nenue@103: Nenue@103: if itemID then Nenue@103: Nenue@103: self.currentEquipped = itemID Nenue@103: Nenue@103: artifacts[itemID] = artifacts[itemID] or {} Nenue@103: table.wipe(artifacts[itemID]) Nenue@103: local artifact = artifacts[itemID] Nenue@103: Nenue@103: artifact.name = name Nenue@103: artifact.texture = texture Nenue@103: artifact.currentXP = currentXP Nenue@103: artifact.level = pointsSpent Nenue@103: local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent) Nick@108: artifact.currentCost = cost Nenue@103: Nenue@103: local pointsAvailable = pointsSpent Nenue@103: local actualCost = cost Nenue@103: local actualXP = currentXP Nenue@103: while actualXP >= actualCost do Nenue@103: pointsAvailable = pointsAvailable + 1 Nenue@103: actualXP = actualXP - actualCost Nenue@103: print(pointsAvailable, '-', actualCost, '=', actualXP) Nenue@103: actualCost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable) Nenue@103: end Nenue@103: print('updating', itemID, name, currentXP, pointsSpent, pointsAvailable, actualXP) Nenue@103: artifact.actualXP = actualXP Nenue@103: artifact.actualLevel = pointsAvailable Nenue@103: artifact.actualCost = actualCost Nenue@103: Nenue@103: end Nenue@103: end Nenue@103: Nenue@97: function ap:ScanBag(id) Nenue@97: print('|cFF00FFFFScanBag()|r', id, IsBagOpen(id), GetContainerNumSlots(id)) Nenue@97: local numSlots = GetContainerNumSlots(id) Nenue@97: local requiresUpdate Nenue@97: if numSlots == 0 then Nenue@97: return nil Nenue@97: end Nenue@97: Nenue@97: Nenue@97: self.profile.bagslots[id] = self.profile.bagslots[id] or {} Nenue@97: table.wipe(self.profile.bagslots[id]) Nenue@97: local bagData = self.profile.bagslots[id] Nenue@97: bagData.totalAP = 0 Nenue@99: bagData.fishingAP = 0 Nenue@99: bagData.items = bagData.items or {} Nenue@99: table.wipe(bagData.items) Nenue@99: Nick@108: self.cache.bagItems[id] = self.cache.bagItems[id] or {} Nick@108: self.cache.bags[id] = self.cache.bags[id] or {} Nick@108: self.cache.fishing[id] = self.cache.fishing[id] or {} Nick@108: Nenue@97: for slotID = 1, numSlots do Nenue@97: local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(id, slotID) Nenue@101: if link then Nenue@101: local itemID = GetContainerItemID(id, slotID) Nenue@101: local name, _, quality, iLevel, reqLevel, class, subclass = GetItemInfo(link) Nenue@97: Nenue@101: if class == 'Consumable' and subclass == 'Other' then Nenue@102: --print(GetItemInfo(link)) Nick@108: local itemAP, isFishingAP Nick@108: if self.cache.bags[id][slotID] and (self.cache.bagItems[id][slotID] == itemID) then Nick@108: print('slot cache data', id, slotID) Nick@108: itemAP = self.cache.bags[id][slotID] Nick@108: else Nick@108: itemAP, isFishingAP = self:GetItemAP(itemID, link) Nick@108: self.cache.bagItems[id][slotID] = itemID Nick@108: self.cache.bags[id][slotID] = itemAP Nick@108: self.cache.fishing[id][slotID] = isFishingAP Nick@108: end Nick@108: Nick@108: Nenue@102: --print(itemAP, isFishingAP) Nenue@102: if itemAP and (itemAP > 0) then Nenue@102: local itemButton = self:GetItemButton(itemID, texture, itemAP) Nenue@102: Nenue@101: if isFishingAP then Nenue@101: bagData.fishingItems = (bagData.fishingItems or 0) + 1 Nenue@101: bagData.fishingAP = (bagData.fishingAP or 0) + itemAP Nenue@101: else Nick@108: itemAP = itemAP Nenue@101: bagData.numItems = (bagData.numItems or 0) + 1 Nenue@101: bagData.totalAP = (bagData.totalAP or 0) + itemAP Nenue@101: end Nenue@101: bagData.items[itemID] = (bagData.items[itemID] or 0) + 1 Nenue@101: end Nenue@101: elseif self.profile.artifacts[itemID] then Nenue@101: print('artfiact weapon', itemID, link, id, slotID) Nenue@101: self.profile.artifacts[itemID].containerID = id Nenue@101: self.profile.artifacts[itemID].slotID = slotID Nenue@101: end Nenue@99: Nenue@97: end Nenue@97: Nenue@97: end Nenue@97: Nenue@97: end Nenue@97: Nenue@98: local BAG_SLOTS = {0, 1, 2, 3, 4 } Nenue@98: local BANK_SLOTS = {-1, 5, 6,7, 8, 9, 10, 11, 12} Nenue@99: local ItemCounts = {} Nenue@99: function ap:ScanAllBags() Nenue@99: if InCombatLockdown() then Nenue@99: self.queuedScan = true Nenue@99: return Nenue@99: end Nenue@101: if not self.profile.knowledgeMultiplier then Nenue@101: print('need to get knowledge level') Nenue@101: return Nenue@101: end Nenue@101: Nenue@99: self.queuedScan = nil Nenue@98: Nenue@101: print('|cFFFF0088ScanAllBags()|r', self.profile.knowledgeMultiplier) Nenue@97: Nenue@99: for _, button in ipairs(self.Tokens) do Nenue@99: button.numItems = 0 Nenue@99: end Nenue@99: Nenue@99: Nenue@98: for _, bagID in ipairs(BAG_SLOTS) do Nenue@98: self:ScanBag(bagID) Nenue@97: end Nenue@97: Nenue@99: if self.bankAccess then Nenue@98: for _, bagID in ipairs(BANK_SLOTS) do Nenue@98: self:ScanBag(bagID) Nenue@98: end Nenue@98: end Nenue@98: Nenue@98: self.bankAP = 0 Nenue@98: self.bagAP = 0 Nenue@99: self.fishingAP = 0 Nenue@99: Nenue@99: table.wipe(ItemCounts) Nenue@98: for id, bagData in pairs(self.profile.bagslots) do Nenue@98: print(id, GetBagName(id), bagData.totalAP) Nenue@98: id = tonumber(id) Nenue@98: if bagData.totalAP then Nenue@98: if (id == BANK_CONTAINER) or (id >= 5) then Nenue@98: self.bankAP = self.bankAP + bagData.totalAP Nenue@98: else Nenue@98: self.bagAP = self.bagAP + bagData.totalAP Nenue@97: end Nenue@98: end Nenue@99: if bagData.fishingAP then Nenue@99: self.fishingAP = self.fishingAP + bagData.fishingAP Nenue@99: end Nenue@97: Nenue@97: end Nenue@98: self.lastUpdate = GetTime() Nenue@103: self.queuedScan = nil Nenue@99: self:TryToShow() Nenue@97: end Nenue@97: Nenue@97: VeneerArtifactButtonMixin = {} Nenue@98: Nenue@99: function VeneerArtifactButtonMixin:SetButton(itemID, artifact, index, equipped) Nenue@99: print(itemID, index) Nenue@98: print(artifact.name, artifact.texture, artifact.currentXP) Nenue@98: self:SetID(itemID) Nick@108: if not artifact.currentCost then Nick@108: artifact.currentCost = artifact.cost Nick@108: end Nick@108: Nenue@98: for k,v in pairs(artifact) do Nenue@98: --print('::',k,v) Nenue@98: self[k] = v Nenue@98: end Nenue@98: Nenue@98: -- this can change between artifact parses Nenue@98: local potentialPoints = self.actualLevel Nenue@99: local totalAP = (itemID ~= UNDERLIGHT_ANGLER_ID) and ((self:GetParent().bankAP or 0) + (self:GetParent().bagAP or 0)) or (self:GetParent().fishingAP or 0) Nenue@99: print(totalAP) Nenue@98: local potentialXP = self.actualXP + totalAP Nenue@99: Nenue@98: self.potentialXP = potentialXP Nenue@98: local potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints) Nenue@98: while potentialXP >= potentialCost do Nenue@98: potentialXP = potentialXP - potentialCost Nenue@98: potentialPoints = potentialPoints + 1 Nenue@98: print('inc estimate', potentialXP, potentialPoints) Nenue@98: potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints) Nenue@98: end Nenue@98: self.potentialCost = potentialCost Nenue@98: self.potentialLevel = potentialPoints Nenue@98: self.potentialAdjustedXP = potentialXP Nenue@98: Nick@108: self.maxCost = self.currentCost Nick@108: for i = self.level + 1, #POINT_COSTS do Nick@108: self.maxCost = self.maxCost + POINT_COSTS[i] Nick@108: end Nenue@98: Nenue@99: if index ~= 1 then Nenue@99: self:ClearAllPoints() Nenue@99: self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPRIGHT', 4, 0) Nenue@99: else Nenue@99: self:ClearAllPoints() Nenue@99: self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', 4, -4) Nenue@99: end Nenue@98: Nenue@99: self.isEquipped = equipped Nenue@98: self:Update() Nenue@98: self:Show() Nenue@98: return self Nenue@98: end Nenue@98: Nenue@97: function VeneerArtifactButtonMixin:Update() Nenue@99: local r, g, b = 1, 1, 1 Nenue@99: local lR, lG, lB = 1, 1, 0 Nenue@99: local levelText = self.level Nenue@99: local xpValue = self.currentXP Nick@108: local costValue = self.currentCost Nenue@97: if self.actualLevel ~= self.level then Nenue@99: levelText, r,g,b = self.actualLevel, 0,1,0 Nenue@99: xpValue, costValue, lR, lG, lB = self.actualXP, self.actualCost, 0, 1, 0 Nenue@99: elseif self.potentialLevel ~= self.level then Nenue@99: levelText, r, g, b = self.potentialLevel, 0,1,1 Nenue@99: xpValue, costValue, lR, lG, lB = self.potentialAdjustedXP, self.potentialCost, 0,1,0 Nenue@99: Nenue@97: end Nenue@97: Nenue@99: self.Level:SetText(levelText) Nenue@99: self.Level:SetTextColor(r, g, b) Nick@108: self.CurrentXP:SetText(ShortNumberString( xpValue)) Nenue@99: self.CurrentXP:SetTextColor(lR, lG, lB) Nenue@99: Nenue@97: if self.isEquipped then Nenue@97: self:SetNormalTexture([[Interface\Buttons\ButtonHilight-Square]]) Nenue@97: self:GetNormalTexture():SetBlendMode('ADD') Nenue@97: self:GetNormalTexture():SetVertexColor(0,1,0) Nenue@97: else Nenue@97: self:SetNormalTexture(nil, 'ADD') Nenue@97: end Nenue@97: Nick@108: local currentProgress = (self.currentXP < self.currentCost) and (self.currentXP / self.currentCost) or 1 Nenue@98: if self.level <= 53 then Nenue@98: self.CurrentProgress.animateFrom = self.CurrentProgress:GetHeight() or 1 Nenue@98: self.CurrentProgress.animateTo = currentProgress * self:GetHeight() Nenue@98: self.CurrentProgress:Show() Nenue@101: self.ProgressLine:Show() Nenue@98: else Nenue@98: self.CurrentProgress:Hide() Nenue@101: self.ProgressLine:Hide() Nenue@98: end Nenue@99: Nenue@98: if self.potentialXP > self.currentXP then Nenue@99: local projectedProgress = (self.potentialAdjustedXP < self.potentialCost) and (self.potentialXP / self.potentialCost) or 1 Nenue@98: if (projectedProgress > currentProgress) then Nenue@98: self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP') Nenue@98: projectedProgress = projectedProgress - currentProgress Nenue@98: else Nenue@98: self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM') Nenue@98: end Nenue@99: print('show potential', currentProgress, projectedProgress) Nenue@98: self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1 Nenue@98: self.AdjustedProgress.animateTo = projectedProgress * self:GetHeight() Nenue@101: self.AdjustedLine:Show() Nenue@98: self.AdjustedProgress:Show() Nenue@98: else Nenue@98: self.AdjustedProgress:Hide() Nenue@101: self.AdjustedLine:Hide() Nenue@98: end Nenue@97: self.Icon:SetTexture(self.texture) Nenue@97: self:SetSize(64,64) Nenue@97: end Nenue@97: Nenue@98: Nenue@98: function VeneerArtifactButtonMixin:AnimateProgress(region) Nenue@98: local cTime = GetTime() Nenue@98: if not region.animateStart then Nenue@98: region.animateStart = cTime Nenue@98: end Nenue@98: local progressTo, progressFrom = region.animateTo, region.animateFrom Nenue@98: local elapsed = cTime - region.animateStart Nenue@98: if elapsed >= .5 then Nenue@98: region:SetHeight(progressTo) Nenue@98: region.animateTo = nil Nenue@98: region.animateStart = nil Nenue@98: region.animateFrom = nil Nenue@98: else Nenue@98: local progress = elapsed / .5 Nenue@98: local height = (progressFrom + (progressTo - progressFrom) * progress) Nenue@98: --print(self:GetName(), progressTo, progressFrom, (progressTo - progressFrom), ceil(progress*10)/10, ceil(height)) Nenue@98: region:SetHeight(height) Nenue@98: end Nenue@98: end Nenue@98: Nenue@98: function VeneerArtifactButtonMixin:OnUpdate(sinceLast) Nenue@98: if self.CurrentProgress.animateTo then Nenue@98: self:AnimateProgress(self.CurrentProgress) Nenue@98: end Nenue@98: Nenue@98: if self.AdjustedProgress.animateTo then Nenue@98: self:AnimateProgress(self.AdjustedProgress) Nenue@98: end Nenue@98: end Nenue@98: Nenue@97: function VeneerArtifactButtonMixin:OnEnter() Nenue@97: GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') Nenue@97: GameTooltip:SetText(self.name) Nick@108: GameTooltip:AddLine(ShortNumberString(self.currentXP) .. ' / '..ShortNumberString(self.currentCost), 1, 1, 0) Nenue@98: if self.potentialXP > self.currentXP then Nick@108: GameTooltip:AddLine(ShortNumberString(self.potentialXP) .. ' potential XP', 0, 1, 1) Nenue@99: if self.potentialAdjustedXP ~= self.potentialXP then Nick@108: GameTooltip:AddLine(ShortNumberString(self.potentialAdjustedXP) .. ' / ' .. ShortNumberString(self.potentialCost).. ' after', 0, 1, 0) Nenue@98: end Nenue@97: end Nenue@99: if self.actualLevel ~= self.level then Nick@108: GameTooltip:AddLine(ShortNumberString(self.actualLevel - self.level) .. ' points unlocked', 0, 1, 1) Nick@108: end Nick@108: if self.currentXP < self.currentCost then Nick@108: GameTooltip:AddLine(ShortNumberString(self.currentCost - self.currentXP) .. ' needed') Nenue@99: end Nenue@99: Nenue@97: GameTooltip:Show() Nenue@97: end Nenue@97: function VeneerArtifactButtonMixin:OnLeave() Nenue@97: if GameTooltip:IsOwned(self) then Nenue@97: GameTooltip:Hide() Nenue@97: end Nenue@97: end Nick@108: function VeneerArtifactButtonMixin:OnHide() Nick@108: Nick@108: if GameTooltip:IsOwned(self) then Nick@108: GameTooltip:Hide() Nick@108: end Nick@108: end Nenue@97: Nenue@97: function VeneerArtifactButtonMixin:OnClick(button, down) Nenue@97: if self.isEquipped then Nenue@97: SocketInventoryItem(16) Nenue@97: else Nick@108: if IsShiftKeyDown() then Nenue@97: SocketContainerItem(self.containerID, self.slotID) Nick@108: else Nick@108: Nick@108: end Nenue@97: end Nenue@97: end