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@119: worldQuestAP = 0, Nenue@119: worldQuestItems = {}, Nenue@99: ItemButtons = {}, Nenue@121: anchorGroup = 'TOP', Nenue@122: anchorPoint = 'TOPLEFT', Nenue@116: anchorPriority = 3, Nenue@121: anchorFrom = 'BOTTOMLEFT', Nenue@115: moduleName = 'Artifactor', Nenue@115: HideCombat = true Nenue@97: } Nenue@122: Nenue@122: VeneerArtifactButtonMixin = {} Nenue@122: local Artifact = VeneerArtifactButtonMixin Nenue@122: Nenue@101: local defaultSettings = { Nenue@101: firstUse = true, Nenue@101: autoHide = true, Nenue@101: } Nenue@116: local Module = VeneerArtifactPowerMixin Nenue@122: local BAGS_TO_SCAN = {BACKPACK_CONTAINER} Nenue@97: local TOOLTIP_NAME = 'VeneerAPScanner' Nick@111: local FISHING_MAX_TRAITS = 24 Nenue@116: local WEAPON_MAX_TRAITS = 92 Nenue@116: local FRAME_PADDING = 4 Nenue@116: local EQUIPPED_SIZE = 64 Nick@111: local BUTTON_SIZE = 48 Nenue@99: local FRAME_LIST = {'ContainerFrame1', 'BankFrame'} Nenue@99: local BAG_FRAMES = {'ContainerFrame1'} Nenue@99: local BANK_FRAMES = {'BankFrame'} Nenue@99: Nenue@116: function Module: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@122: self:RegisterEvent('BANKFRAME_OPENED') -- bank info available Nenue@122: self:RegisterEvent('BANKFRAME_CLOSED') -- Nenue@122: self:RegisterEvent('ARTIFACT_UPDATE') -- visible data change Nenue@122: self:RegisterEvent('ARTIFACT_XP_UPDATE') -- xp for equipped artifact Nenue@122: self:RegisterEvent('PLAYER_REGEN_ENABLED') -- combat Nenue@122: self:RegisterEvent('PLAYER_REGEN_DISABLED') -- Nenue@122: self:RegisterEvent('PLAYER_ENTERING_WORLD') -- zone/instance transfer Nick@108: self:RegisterEvent('ITEM_LOCK_CHANGED') -- use to clear bag slot cache data Nenue@115: Veneer:AddHandler(self) 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@122: elseif arg:match('item') then Nenue@122: print('name', arg:match("^item (%S.+)")) Nenue@122: print('num', arg:match("Hitem:(%d+)")) Nenue@122: local linkOrID = arg:match("item:(%d+)") or arg:match("^item (%S+)") Nenue@122: if linkOrID then Nenue@122: local name, etc = GetItemInfo(linkOrID) Nenue@122: end Nenue@122: Nenue@98: else Nenue@122: Nenue@98: self:Show() Nenue@98: end Nenue@97: end Nenue@97: Nenue@97: self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') Nenue@99: Nenue@97: Nenue@97: end Nick@108: local ShortNumberString = function (value) Nenue@122: if value >= 1000000000 then Nenue@122: Nenue@122: return tostring(floor(value/10000000)/100) .. 'B' Nenue@122: elseif value >= 1000000 then Nenue@116: return tostring(floor(value/100000)/10) .. 'M' Nenue@116: elseif 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 Nick@111: --[[local oFunc = tremove(info, #info) Nick@111: local args = info Nick@111: Nick@111: local func = function(...) Nick@111: print('|cFFFF0088Callback:|r', unpack(args)) Nick@111: Nick@111: oFunc(...) Nick@111: end Nick@111: print('hooking', unpack(info), oFunc, func) Nick@111: hooksecurefunc(unpack(info), func) Nick@111: --]] 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() Nick@111: print(frame:GetName(), funcName, 'hook') Nenue@103: VeneerArtifactPower:TryToShow() Nenue@103: end) Nenue@102: end Nenue@102: end Nenue@102: local PENDING_HOOKS = {} Nenue@119: local guid = UnitGUID('player') 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@116: function Module:Setup() Nenue@97: print(self:GetName()..':Setup()') Nenue@119: 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: 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() Nick@111: 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@116: function Module:ResetCache() Nick@111: table.wipe(self.cache.items) Nick@111: table.wipe(self.cache.fishing) Nick@111: table.wipe(self.cache.bags) Nick@111: table.wipe(self.cache.bagItems) Nick@111: self:ScanAllBags() Nick@111: end Nick@111: Nenue@116: function Module: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@116: function Module:Reanchor() Nenue@99: if Veneer then Nenue@99: Veneer:DynamicReanchor() Nenue@99: end Nenue@99: end Nenue@99: Nenue@116: function Module: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@119: self:UpdateWorldQuestsAP() Nenue@119: self:RegisterEvent('QUEST_LOG_UPDATE') Nenue@119: self.enabled = true Nenue@102: Nenue@99: self:ScanAllBags() Nenue@99: self:Reanchor() Nenue@97: end Nenue@116: function Module:OnHide() Nick@111: print('|cFF88FF00OnHide()|r', debugstack()) Nenue@119: self:UnregisterEvent('QUEST_LOG_UPDATE') Nenue@99: self:Reanchor() Nenue@97: end Nenue@116: function Module: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@116: function Module: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())) Nick@111: if _G[name] and _G[name]:IsVisible() 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: Nick@111: print('failed tests') Nenue@99: self:Hide() Nenue@99: end Nenue@99: Nenue@99: Nenue@116: function Module: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@122: -- prevent double call from login 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@122: self:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@122: --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@122: self:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@122: --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@119: elseif event == 'QUEST_LOG_UPDATE' then Nenue@119: self:UpdateWorldQuestsAP() Nenue@97: elseif event == 'PLAYER_REGEN_DISABLED' then Nenue@97: self:Hide() Nenue@97: end Nenue@97: end Nenue@97: Nenue@116: function Module:OnUpdate() Nenue@101: if #self.scanQueue >= 1 then Nenue@101: local scanInfo = tremove(self.scanQueue, 1) Nick@111: end Nick@111: if IsShiftKeyDown() then Nick@111: self.Refresh:Show() Nick@111: else Nick@111: self.Refresh:Hide() Nick@111: end Nenue@101: Nenue@101: end Nenue@101: Nenue@119: function Module:OnMouseDown(button) Nenue@97: self.enabled = nil Nenue@119: if button == 'RightButton' then Nenue@119: self:Hide() Nenue@119: end Nenue@119: Nenue@97: end Nenue@97: Nenue@116: function Module:Update() Nenue@97: if not self:IsShown() then Nenue@99: print('|cFFFF4400Update()|r') Nenue@97: return Nenue@97: end Nenue@122: print('|cFFFFFF00pdate()|r') Nenue@122: Nenue@122: local numButtons = 0 Nenue@122: local contentsHeight = 16 Nenue@122: local contentsWidth = 400 Nenue@122: if self.profile.knowledgeMultiplier then Nenue@122: local artifactsWidth = self:UpdateArtifactButtons() Nenue@122: Nenue@122: if artifactsWidth ~= 0 then Nenue@122: contentsHeight = contentsHeight + 64 Nenue@122: end Nenue@122: Nenue@122: contentsWidth = max(contentsWidth, min(artifactsWidth, 400)) Nenue@122: Nenue@122: local itemsWidth, itemsHeight = self:UpdateItemButtons() Nenue@122: contentsHeight = contentsHeight + itemsHeight Nenue@122: contentsWidth = max(contentsWidth, itemsWidth) Nenue@122: end Nenue@122: Nenue@122: 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 Nick@111: Nick@111: if self.bagAP and (self.bagAP > 0) then Nick@111: bankText = 'Inventory: |cFFFFFFFF' .. ShortNumberString(self.bagAP) .. '|r' Nick@111: end Nick@111: if self.bankAP and (self.bankAP > 0) then Nick@111: bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..ShortNumberString(self.bankAP)..' banked|r' Nick@111: end Nick@111: if self.fishingAP and self.fishingAP > 0 then Nick@111: bankText = (bankText and (bankText .. ' | ') or '') .. '|cFF0088FF' .. ShortNumberString(self.fishingAP) .. ' fishing|r' Nick@111: end Nick@111: end Nick@111: Nenue@119: if self.worldQuestAP then Nenue@119: bankText = (bankText and (bankText .. '\n') or '') .. '|cFFFFBB00World Quests:|r |cFFFFFFFF' .. ShortNumberString(self.worldQuestAP) .. '' Nenue@119: end Nick@111: Nenue@99: Nenue@97: self.SummaryHeader:SetText(bankText) Nenue@122: if not self.lastButton then Nenue@122: contentsHeight = contentsHeight + self.SummaryHeader:GetHeight() Nenue@101: end Nenue@101: Nenue@101: Nick@111: if not self.hasArtifacts then Nick@111: self:SetShown(false) Nick@111: end Nick@111: Nenue@101: Nick@108: self:SetWidth(contentsWidth) Nick@108: self:SetHeight(contentsHeight) Nenue@101: self:Reanchor() Nenue@101: end Nenue@101: Nenue@119: local BROKEN_ISLE_ID = 1007 Nenue@119: Nenue@119: function Module:UpdateWorldQuestsAP() Nenue@119: self.waitingForQuestRewardData = false Nenue@119: self.worldQuestAP = 0 Nenue@119: wipe(self.worldQuestItems) Nenue@119: Nenue@119: for zoneIndex = 1, C_MapCanvas.GetNumZones(BROKEN_ISLE_ID) do Nenue@119: local zoneMapID, zoneName, zoneDepth, left, right, top, bottom = C_MapCanvas.GetZoneInfo(BROKEN_ISLE_ID, zoneIndex); Nenue@119: --print(zoneMapID, zoneName) Nenue@119: if zoneDepth <= 1 then -- Exclude subzones Nenue@119: local taskInfo = C_TaskQuest.GetQuestsForPlayerByMapID(zoneMapID, BROKEN_ISLE_ID); Nenue@119: Nenue@119: if taskInfo then Nenue@119: for i, info in ipairs(taskInfo) do Nenue@119: local questID = info.questId Nenue@119: Nenue@119: local questTitle, factionID, capped = C_TaskQuest.GetQuestInfoByQuestID(questID) Nenue@119: --print(questTitle, HaveQuestRewardData(questID)) Nenue@119: if HaveQuestRewardData(questID) then Nenue@119: Nenue@119: Nenue@119: local numQuestRewards = GetNumQuestLogRewards(questID); Nenue@119: Nenue@119: if numQuestRewards > 0 then Nenue@119: for i = 1, numQuestRewards do Nenue@119: local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID) Nenue@119: if IsArtifactPowerItem(itemID) then Nenue@119: local _, link = GetItemInfo(itemID) Nenue@119: if link then Nenue@119: local ap = self:GetItemAP(itemID, link) Nenue@119: --print('ap =', ap) Nenue@119: if ap then Nenue@119: self.worldQuestAP = self.worldQuestAP + ap Nenue@119: Nenue@119: end Nenue@119: Nenue@119: self.worldQuestItems[itemID] = (self.worldQuestItems[itemID] or 0) + 1 Nenue@119: end Nenue@119: Nenue@119: --print(self.worldQuestAP) Nenue@119: end Nenue@119: Nenue@119: end Nenue@119: Nenue@119: end Nenue@119: Nenue@119: Nenue@119: else Nenue@119: C_TaskQuest.RequestPreloadRewardData(questID); Nenue@119: self.waitingForQuestRewardData = true Nenue@119: end Nenue@119: end Nenue@119: end Nenue@119: end Nenue@119: end Nenue@119: end Nenue@119: Nenue@116: function Module:UpdateArtifactButtons() Nenue@101: Nenue@97: -- Artifact icons, in no particular order Nenue@99: self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo() Nenue@122: self.lastButton = nil Nick@111: self.canAddAP = nil Nick@111: self.canAddFishingAP = nil Nick@111: local hasArtifacts Nenue@97: local numButtons = 0 Nenue@99: local lastFrame = self Nenue@99: local fishingID, fishingData Nenue@98: local index, button Nenue@116: local equipped =self.profile.artifacts[self.equippedID] Nenue@116: local buttonsWidth = 0 Nenue@116: if equipped then Nenue@116: numButtons = numButtons + 1 Nenue@116: button = self.Artifact[numButtons] Nenue@116: button.relativeFrame = self Nenue@122: if self.equippedID ~= button.itemID then Nenue@122: button:SetItem(self.equippedID, equipped, numButtons, true, nil) Nenue@122: hasArtifacts = true Nenue@122: end Nenue@122: lastFrame = button Nenue@116: buttonsWidth = EQUIPPED_SIZE + (FRAME_PADDING * 2) Nenue@116: end Nenue@97: for itemID, artifact in pairs(self.profile.artifacts) do Nenue@116: if (itemID == UNDERLIGHT_ANGLER_ID) then Nenue@116: -- only add if we have fishing AP items and it's not being shown in the equipped slot Nenue@116: if VeneerData.ArtifactPower.EnableFishing and (itemID ~= self.equippedID) then Nenue@98: fishingID = itemID Nenue@98: fishingData = artifact Nenue@98: end Nenue@97: Nick@111: if artifact.level < FISHING_MAX_TRAITS then Nick@111: if itemID == self.equippedID then Nick@111: self.canAddFishingAP = true Nick@111: end Nick@111: end Nenue@98: else Nick@111: if artifact.level < WEAPON_MAX_TRAITS then Nick@111: if itemID == self.equippedID then Nick@111: self.canAddAP = true Nenue@116: else Nenue@116: Nenue@116: hasArtifacts = true Nenue@116: numButtons = numButtons + 1 Nenue@116: button = self.Artifact[numButtons] Nenue@116: button.relativeFrame = lastFrame Nenue@122: if button.itemID ~= itemID then Nenue@122: button:SetItem(itemID, artifact, numButtons, (self.equippedID == itemID), nil) Nenue@122: end Nenue@122: lastFrame = button Nenue@116: buttonsWidth = buttonsWidth + lastFrame:GetWidth() + FRAME_PADDING Nick@111: end Nick@108: end Nenue@97: end Nick@111: end Nenue@97: Nenue@122: self.lastButton = lastFrame Nenue@122: Nenue@97: Nick@108: if fishingData and (self.fishingAP and self.fishingAP > 0) then Nenue@98: numButtons = numButtons + 1 Nick@111: hasArtifacts = true Nenue@99: local button = self.Artifact[numButtons] Nenue@99: button.relativeFrame = lastFrame Nick@111: button.isFishing = true Nenue@122: button:SetItem(fishingID, fishingData, numButtons, self.equippedID == fishingID) Nenue@122: self.lastButton = button Nenue@98: end Nenue@97: Nick@111: self.hasArtifacts = hasArtifacts 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@122: self.SummaryHeader:ClearAllPoints() Nenue@122: if self.lastButton then Nenue@122: self.SummaryHeader:SetPoint('TOPLEFT', self.lastButton, 'TOPRIGHT', 4, -2) Nenue@122: else Nenue@122: self.SummaryHeader:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', 4, 4) Nenue@122: end Nenue@122: Nenue@122: Nick@111: Nenue@116: return buttonsWidth Nenue@97: end Nenue@97: Nenue@99: Nenue@116: function Module:UpdateItemButtons() Nenue@99: print('|cFF00FFFFUpdateItemButtons()|r') Nick@111: Nick@111: local apType Nick@111: if self.canAddFishingAP then Nick@111: apType = true Nick@111: elseif not self.canAddAP then Nick@111: for index, button in ipairs(self.Tokens) do Nick@111: button:Hide() Nick@111: end Nick@111: return 0, 0 Nick@111: end Nick@111: Nick@111: Nenue@99: local lastFrame, upFrame Nenue@99: local numButtons = 0 Nenue@101: local buttonsHeight = 0 Nick@108: local buttonsWidth = 0 Nick@111: Nenue@99: for index, button in ipairs(self.Tokens) do Nick@111: if (button.numItems >= 1) and (button.isFishingAP == apType) 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 Nick@111: local col = mod(numButtons,8) 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 Nenue@99: else 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 Nenue@99: end Nick@111: 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 Nick@111: buttonsWidth = min(numButtons, 8) * (BUTTON_SIZE) Nick@111: end Nick@111: Nick@111: Nick@111: Nick@111: if buttonsWidth ~= 0 then Nick@111: buttonsWidth = buttonsWidth + 8+ ((min(numButtons, 8)-1)*2) Nenue@99: end Nenue@99: Nenue@101: Nenue@101: Nick@108: return buttonsWidth, buttonsHeight Nenue@99: end Nenue@99: Nenue@116: function Module: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@116: function Module:GetItemButton(itemID, texture, itemAP, fishing) 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") Nick@111: button.isFishingAP = fishing 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: Nenue@116: button.Label:SetText(ShortNumberString(itemAP)) Nenue@101: Nenue@99: button.numItems = button.numItems + 1 Nenue@99: return button Nenue@99: end Nenue@99: Nenue@116: function Module:GetItemAP(itemID, itemLink, bagData) Nick@108: if not self.cache.items[itemID] then Nenue@101: Nick@111: print('doing tooltip scan', itemLink, itemID) 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: for i = 3, numLines do Nenue@101: local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText() Nick@111: if text then Nick@111: Nick@111: text = text:lower():gsub(',', '') Nenue@116: Nick@111: if text:match('equipped artifact') then Nick@111: print(itemLink, '-', tonumber(text)) Nenue@116: Nenue@116: local itemAP = text:match('[%d%.]+') Nick@111: if itemAP then Nenue@116: -- tokens > 1M are described as '%f million' Nenue@116: if text:match("million") then Nenue@116: itemAP = tonumber(itemAP) * 1000000 Nenue@116: end Nenue@116: Nick@111: itemAP = itemAP Nick@111: self.cache.items[itemID] = tonumber(itemAP) Nick@111: end Nick@111: end Nick@111: if text:match('fishing artifact') then Nick@111: local fishingAP = text:match("%d+") Nick@111: fishingAP = fishingAP Nick@111: print(itemLink, 'fishing', tonumber(text)) Nick@111: if fishingAP then Nick@111: self.cache.items[itemID] = tonumber(fishingAP) Nick@111: self.cache.fishing[itemID] = true Nick@111: end Nenue@101: end 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@122: function Module:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) Nenue@122: print('|cFF00FF00UpdateArtifact()|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: if itemID then 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@116: artifact.tier = C_ArtifactUI.GetArtifactTier() or ((pointsSpent >= 36) and 2 or 1) Nenue@122: artifact.itemID = itemID Nenue@116: Nenue@116: print('tier', artifact.tier) Nenue@116: local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent, artifact.tier) Nick@108: artifact.currentCost = cost Nenue@103: Nenue@122: for index, frame in pairs(self.Artifact) do Nenue@122: if frame.itemID == itemID then Nenue@122: frame:SetItem(itemID, artifact, index, (itemID == self.equippedID), (itemID == UNDERLIGHT_ANGLER_ID)) Nenue@122: end Nenue@122: end Nenue@103: Nenue@103: end Nenue@103: end Nenue@103: Nenue@116: function Module: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) Nick@111: local c = self.cache Nenue@99: Nick@111: c.bagItems[id] = c.bagItems[id] or {} Nick@111: c.bags[id] = c.bags[id] or {} Nick@111: c.fishing[id] = c.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: Nick@111: if class == 'Consumable' or subclass == 'Cooking' then Nenue@102: --print(GetItemInfo(link)) Nick@108: local itemAP, isFishingAP Nick@111: if c.bags[id][slotID] and (c.bagItems[id][slotID] == itemID) then Nick@111: --print('cached slot', id, slotID, name) Nick@111: itemAP = c.bags[id][slotID] Nick@111: isFishingAP = c.fishing[id] and c.fishing[id][slotID] Nick@108: else Nick@108: itemAP, isFishingAP = self:GetItemAP(itemID, link) Nick@111: c.bagItems[id][slotID] = itemID Nick@111: c.bags[id][slotID] = itemAP Nick@111: c.fishing[id][slotID] = isFishingAP Nick@108: end Nick@108: Nick@108: Nenue@102: --print(itemAP, isFishingAP) Nenue@102: if itemAP and (itemAP > 0) then Nick@111: local itemButton = self:GetItemButton(itemID, texture, itemAP, isFishingAP) 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 Nick@111: --print('artifact weapon', itemID, link, id, slotID) Nenue@101: self.profile.artifacts[itemID].containerID = id Nenue@101: self.profile.artifacts[itemID].slotID = slotID Nick@111: else Nick@111: --print('skipping', class, subclass, link) 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@116: function Module: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 Nick@111: print(id, GetBagName(id), bagData.totalAP, bagData.fishingAP) 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@98: Nenue@122: function Artifact:SetItem(itemID, artifact, index, equipped, fishing) Nenue@122: print('|cFF00FFFFSetItem()|r', itemID, index) Nenue@98: print(artifact.name, artifact.texture, artifact.currentXP) Nenue@122: 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: Nick@111: self.isFishing = fishing Nenue@98: -- this can change between artifact parses Nenue@117: local unusedXP = (itemID ~= UNDERLIGHT_ANGLER_ID) and ((self:GetParent().bankAP or 0) + (self:GetParent().bagAP or 0)) or (self:GetParent().fishingAP or 0) Nenue@117: print('unspent:', unusedXP) Nenue@99: Nenue@117: -- current standing artifact XP (what appears in the artifact ui) Nenue@117: -- actual artifact XP after any unlocked points are spent Nenue@117: -- total total of invested and inventory XP Nenue@117: -- totalCost total of costs between current and actual level Nenue@117: local actualXP = artifact.currentXP Nenue@116: local actualLevel = artifact.level Nenue@116: local actualCost = C_ArtifactUI.GetCostForPointAtRank(actualLevel, artifact.tier) Nenue@119: local totalXP = actualXP Nenue@117: local totalCost = actualCost Nenue@117: local totalLevel = actualLevel Nenue@116: Nenue@117: print('tier:', artifact.tier) Nenue@117: print('current:', self.level, self.currentXP, '/', self.currentCost) Nenue@116: while actualXP >= actualCost do Nenue@116: actualXP = actualXP - actualCost Nenue@116: actualLevel = actualLevel + 1 Nenue@116: actualCost = C_ArtifactUI.GetCostForPointAtRank(actualLevel, artifact.tier) Nenue@117: Nenue@117: print('* ', actualLevel, actualXP, actualCost, totalCost) Nenue@98: end Nenue@117: print('actual:', actualLevel, actualXP, '/', actualCost) Nenue@117: Nenue@117: Nenue@120: local remaining = totalXP + unusedXP Nenue@120: local nextCost = artifact.currentCost Nenue@120: if remaining > nextCost then Nenue@117: totalCost = nextCost Nenue@120: while remaining >= nextCost do Nenue@117: totalLevel = totalLevel + 1 Nenue@119: remaining = remaining - nextCost Nenue@117: nextCost = C_ArtifactUI.GetCostForPointAtRank(totalLevel, artifact.tier) Nenue@119: print('|cFFFFFF00+ ', totalLevel, remaining, '/', totalCost) Nenue@117: end Nenue@119: totalXP = remaining Nenue@119: totalCost = nextCost Nenue@117: end Nenue@117: print('total:', totalLevel, totalXP, '/', totalCost) Nenue@117: Nenue@117: self.currentLevel = self.level Nenue@117: Nenue@117: Nenue@116: self.actualCost = actualCost Nenue@116: self.actualLevel = actualLevel Nenue@116: self.actualXP = actualXP Nenue@117: Nenue@117: self.totalXP = totalXP Nenue@117: self.totalCost = totalCost Nenue@117: self.totalLevel = totalLevel Nenue@117: Nenue@98: 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@122: self.itemID = itemID Nenue@99: self.isEquipped = equipped Nenue@98: self:Update() Nenue@98: self:Show() Nenue@122: Nenue@98: return self Nenue@98: end Nenue@98: Nenue@122: function Artifact:UpdateXPBar() Nenue@122: local r3, g3, b3 = 1, .5, 0 -- main xp bar Nenue@122: -- current: amount shown in blizz ui Nenue@122: -- actual: amount contributing the next level, will be same until current point cap is reached Nenue@122: -- potential: total of ap on hand Nenue@122: print(self.currentXP, self.actualXP, self.potentialXP) Nenue@122: Nenue@122: local maxHeight = self:GetHeight() - 8 Nenue@122: local currentHeight = self.CurrentProgress:GetHeight() or 1 Nenue@122: local offHeight = self.AdjustedProgress:GetHeight() or 1 Nenue@122: Nenue@122: Nenue@122: local currentProgress = (self.currentXP < self.currentCost) and (self.currentXP / self.currentCost) or 1 Nenue@122: local projectedProgress = (self.totalXP < self.totalCost) and (self.totalXP / self.totalCost) or 1 Nenue@122: if self.actualLevel ~= self.level then Nenue@122: r3, g3, b3 = 0, 1, 1 Nenue@122: end Nenue@122: Nenue@122: print('|cFFFF4400', currentProgress) Nenue@122: if self.level <= WEAPON_MAX_TRAITS then Nenue@122: self.CurrentProgress.animateFrom = currentHeight or 1 Nenue@122: self.CurrentProgress.animateTo = currentProgress * maxHeight Nenue@122: self.CurrentProgress:Show() Nenue@122: self.ProgressLine:Show() Nenue@122: else Nenue@122: self.CurrentProgress:Hide() Nenue@122: self.ProgressLine:Hide() Nenue@122: end Nenue@122: Nenue@122: if self.totalXP ~= self.currentXP then Nenue@122: print('|cFF00FFFF', projectedProgress) Nenue@122: if (projectedProgress > currentProgress) then Nenue@122: self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP') Nenue@122: projectedProgress = projectedProgress - currentProgress Nenue@122: print('show projected above', currentProgress, projectedProgress) Nenue@122: else Nenue@122: self.CurrentProgress:Hide() Nenue@122: self.ProgressLine:Hide() Nenue@122: self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM', 0 , 4) Nenue@122: print('show projected at bottom', currentProgress, projectedProgress) Nenue@122: end Nenue@122: Nenue@122: self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1 Nenue@122: self.AdjustedProgress.animateTo = projectedProgress * self:GetHeight() Nenue@122: self.AdjustedLine:Show() Nenue@122: self.AdjustedProgress:Show() Nenue@122: else Nenue@122: self.CurrentProgress:SetPoint('BOTTOM', self, 'BOTTOM', 0, 4) Nenue@122: self.AdjustedProgress:Hide() Nenue@122: self.AdjustedLine:Hide() Nenue@122: end Nenue@122: --print(self.CurrentProgress:GetPoint(3)) Nenue@122: --print(self.CurrentProgress:GetSize()) Nenue@122: Nenue@122: self.CurrentProgress:SetColorTexture(r3,g3,b3,1) Nenue@122: Nenue@122: end Nenue@122: Nenue@122: function Artifact:OnLoad() Nenue@122: print('|cFFFF4400OnLoad()|r', self:GetName(), self:GetID()) Nenue@122: self:RegisterEvent('ARTIFACT_UPDATE') Nenue@122: self:RegisterEvent('PLAYER_LOGIN') Nenue@122: end Nenue@122: Nenue@122: function Artifact:OnEvent(event) Nenue@122: local itemID, _, _, nextCost = C_ArtifactUI.GetEquippedArtifactInfo() Nenue@122: print(self:GetID(), '|cFFFF4400OnEvent()|r', event, itemID, '=', self.itemID, (itemID == self.itemID)) Nenue@122: if itemID == self.itemID then Nenue@122: self:Update() Nenue@122: end Nenue@122: end Nenue@122: Nenue@116: function Artifact:Update() Nenue@122: if not self.itemID then Nenue@122: return Nenue@122: end Nenue@122: Nenue@122: print(self:GetName(), '|ff00FFFFUpdate()|r') Nenue@122: local r1, g1, b1 = 1, 1, 1 -- top text Nenue@122: local r2, g2, b2 = 1, 1, 0 -- bottom text Nenue@99: local levelText = self.level Nenue@116: local xpText = ShortNumberString(self.currentXP) Nenue@116: local costText = ShortNumberString(self.currentCost) Nenue@116: local remainingText = ShortNumberString(self.currentCost - self.currentXP) Nenue@122: Nenue@122: local maxHeight = self:GetHeight() - 4 Nenue@122: local currentHeight = self.CurrentProgress:GetHeight() or 1 Nenue@122: local offHeight = self.AdjustedProgress:GetHeight() or 1 Nenue@122: Nenue@97: if self.actualLevel ~= self.level then Nenue@116: levelText = self.actualLevel Nenue@116: r1, g1, b1 = 0, 1, 0 Nenue@116: xpText = ShortNumberString(self.actualXP) Nenue@116: costText = ShortNumberString(self.actualCost) Nenue@116: remainingText = ShortNumberString(self.actualCost-self.actualXP) Nenue@116: --[[elseif self.potentialLevel ~= self.level then Nenue@116: r1, g1, b1 = 0, 1, 1 Nenue@116: r2, g2, b2 = 0, 1, 1 Nenue@116: costText = ShortNumberString(self.potentialCost) Nenue@116: remainingText = ShortNumberString(self.potentialCost-self.potentialXP) Nenue@116: --]] Nenue@97: end Nenue@97: Nenue@99: self.Level:SetText(levelText) Nenue@116: self.CurrentXP:SetText( xpText ) Nenue@116: self.RemainingCost:SetText(remainingText) Nenue@116: self.Level:SetTextColor(r1, g1, b1) Nenue@116: self.CurrentXP:SetTextColor(r1, g1, b1) Nenue@99: Nenue@97: if self.isEquipped then Nenue@116: self:SetSize(64,64) 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@116: self:SetSize(48,48) Nenue@97: self:SetNormalTexture(nil, 'ADD') Nenue@97: end Nenue@97: Nenue@122: self:UpdateXPBar() Nenue@116: Nenue@117: if self.actualLevel ~= self.currentLevel then Nenue@117: self:SetNormalTexture([[Interface\Buttons\UI-Quickslot-Depress]], 'ADD') Nenue@117: self:GetNormalTexture():SetBlendMode('BLEND') Nenue@117: self:GetNormalTexture():SetVertexColor(1,1,1) Nenue@117: else Nenue@117: self:SetNormalTexture(nil, 'ADD') Nenue@117: end Nenue@97: self.Icon:SetTexture(self.texture) Nenue@97: end Nenue@97: Nenue@119: local XP_SCALING_DURATION = .5 Nenue@116: function Artifact: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@119: if elapsed >= XP_SCALING_DURATION 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@119: local progress = elapsed / XP_SCALING_DURATION 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@116: function Artifact: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@116: function Artifact:OnEnter() Nenue@97: GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') Nenue@97: GameTooltip:SetText(self.name) Nenue@119: GameTooltip:AddLine(ShortNumberString(self.currentXP) .. ' / '..ShortNumberString(self.currentCost), 1, 1, 1) Nenue@99: if self.actualLevel ~= self.level then Nenue@119: GameTooltip:AddLine(ShortNumberString(self.actualLevel - self.level) .. ' points unlocked', 1, 1, 0) Nick@108: end Nick@108: if self.currentXP < self.currentCost then Nenue@117: GameTooltip:AddLine(ShortNumberString(self.currentCost - self.currentXP) .. ' for level ' .. (self.currentLevel+1), 1, 1, 0) Nenue@117: else Nenue@117: GameTooltip:AddLine(ShortNumberString(self.actualCost - self.actualXP) .. ' for level ' .. (self.actualLevel+1), 0, 1, 0) Nenue@117: end Nenue@117: if self.totalLevel ~= self.actualLevel then Nenue@117: GameTooltip:AddLine('Level ' .. self.totalLevel .. ' with unspent tokens', 0, 1, 1) Nenue@99: end Nenue@99: Nenue@97: GameTooltip:Show() Nenue@97: end Nenue@116: function Artifact:OnLeave() Nenue@97: if GameTooltip:IsOwned(self) then Nenue@97: GameTooltip:Hide() Nenue@97: end Nenue@97: end Nenue@116: function Artifact:OnHide() Nick@108: Nick@108: if GameTooltip:IsOwned(self) then Nick@108: GameTooltip:Hide() Nick@108: end Nick@108: end Nenue@97: Nenue@116: function Artifact:OnClick(button, down) Nenue@97: if self.isEquipped then Nenue@97: SocketInventoryItem(16) Nenue@97: else Nick@108: if IsShiftKeyDown() then Nenue@119: SocketContainerItem(self.containerID, self.slotID) Nick@108: else Nick@108: Nick@108: end Nenue@97: end Nenue@122: end