Mercurial > wow > buffalo2
view Modules/ArtifactPower.lua @ 125:3f4794dca91b
template load order and Script handlers linkage
author | Nenue |
---|---|
date | Sun, 15 Oct 2017 16:47:22 -0400 |
parents | b3c0258b419d |
children | 9f2cf5609420 |
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 = {}, worldQuestAP = 0, worldQuestItems = {}, ItemButtons = {}, anchorGroup = 'TOP', anchorPoint = 'TOPLEFT', anchorPriority = 3, anchorFrom = 'BOTTOMLEFT', moduleName = 'Artifactor', HideCombat = true } VeneerArtifactButtonMixin = {} local Artifact = VeneerArtifactButtonMixin local defaultSettings = { firstUse = true, autoHide = true, } local Module = VeneerArtifactPowerMixin local BAGS_TO_SCAN = {BACKPACK_CONTAINER} local TOOLTIP_NAME = 'VeneerAPScanner' local XP_INSET = 1 local XP_WIDTH = 4 local FISHING_MAX_TRAITS = 24 local WEAPON_MAX_TRAITS = 92 local FRAME_PADDING = 4 local EQUIPPED_SIZE = 64 local BUTTON_SIZE = 48 local FRAME_LIST = {'ContainerFrame1', 'BankFrame'} local BAG_FRAMES = {'ContainerFrame1'} local BANK_FRAMES = {'BankFrame'} function Module: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') -- bank info available self:RegisterEvent('BANKFRAME_CLOSED') -- self:RegisterEvent('ARTIFACT_UPDATE') -- visible data change self:RegisterEvent('ARTIFACT_XP_UPDATE') -- xp for equipped artifact self:RegisterEvent('PLAYER_REGEN_ENABLED') -- combat self:RegisterEvent('PLAYER_REGEN_DISABLED') -- self:RegisterEvent('PLAYER_ENTERING_WORLD') -- zone/instance transfer self:RegisterEvent('ITEM_LOCK_CHANGED') -- use to clear bag slot cache data Veneer:AddHandler(self) 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() elseif arg:match('item') then print('name', arg:match("^item (%S.+)")) print('num', arg:match("Hitem:(%d+)")) local linkOrID = arg:match("item:(%d+)") or arg:match("^item (%S+)") if linkOrID then local name, etc = GetItemInfo(linkOrID) end else self:Show() end end self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate') end local ShortNumberString = function (value) if value >= 1000000000 then return tostring(floor(value/10000000)/100) .. 'B' elseif value >= 1000000 then return tostring(floor(value/100000)/10) .. 'M' elseif 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 guid = UnitGUID('player') 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 Module:Setup() print(self:GetName()..':Setup()') 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 Module: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 Module: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 Module:Reanchor() if Veneer then Veneer:DynamicReanchor() end end function Module: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:UpdateWorldQuestsAP() self:RegisterEvent('QUEST_LOG_UPDATE') self.enabled = true self:ScanAllBags() self:Reanchor() end function Module:OnHide() print('|cFF88FF00OnHide()|r', debugstack()) self:UnregisterEvent('QUEST_LOG_UPDATE') self:Reanchor() end function Module:OnEnter() GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') GameTooltip:AddLine(self.bagAP) GameTooltip:AddLine(self.bankAP) end function Module: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 Module: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 -- prevent double call from login 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:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) --self:ScanAllBags(self.bankAccess) end self:UpdateArtifactButtons() elseif event == 'ARTIFACT_XP_UPDATE' then local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetEquippedArtifactInfo() self:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) --self:ScanAllBags(self.bankAccess) self:UpdateArtifactButtons() 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 == 'QUEST_LOG_UPDATE' then self:UpdateWorldQuestsAP() elseif event == 'PLAYER_REGEN_DISABLED' then self:Hide() end end function Module: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 Module:OnMouseDown(button) self.enabled = nil if button == 'RightButton' then self:Hide() end end function Module:Update() if not self:IsShown() then print('|cFFFF4400Update()|r') return end print('|cFFFFFF00pdate()|r') local numButtons = 0 local contentsHeight = 16 local contentsWidth = 400 if self.profile.knowledgeMultiplier then local artifactsWidth = self:UpdateArtifactButtons() if artifactsWidth ~= 0 then contentsHeight = contentsHeight + 64 end contentsWidth = max(contentsWidth, min(artifactsWidth, 400)) local itemsWidth, itemsHeight = self:UpdateItemButtons() contentsHeight = contentsHeight + itemsHeight contentsWidth = max(contentsWidth, itemsWidth) end 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 if self.worldQuestAP then bankText = (bankText and (bankText .. '\n') or '') .. '|cFFFFBB00World Quests:|r |cFFFFFFFF' .. ShortNumberString(self.worldQuestAP) .. '' end self.SummaryHeader:SetText(bankText) if not self.lastButton then contentsHeight = contentsHeight + self.SummaryHeader:GetHeight() end if not self.hasArtifacts then self:SetShown(false) end self:SetWidth(contentsWidth) self:SetHeight(contentsHeight) self:Reanchor() end local BROKEN_ISLE_ID = 1007 function Module:UpdateWorldQuestsAP() self.waitingForQuestRewardData = false self.worldQuestAP = 0 wipe(self.worldQuestItems) for zoneIndex = 1, C_MapCanvas.GetNumZones(BROKEN_ISLE_ID) do local zoneMapID, zoneName, zoneDepth, left, right, top, bottom = C_MapCanvas.GetZoneInfo(BROKEN_ISLE_ID, zoneIndex); --print(zoneMapID, zoneName) if zoneDepth <= 1 then -- Exclude subzones local taskInfo = C_TaskQuest.GetQuestsForPlayerByMapID(zoneMapID, BROKEN_ISLE_ID); if taskInfo then for i, info in ipairs(taskInfo) do local questID = info.questId local questTitle, factionID, capped = C_TaskQuest.GetQuestInfoByQuestID(questID) --print(questTitle, HaveQuestRewardData(questID)) if HaveQuestRewardData(questID) then local numQuestRewards = GetNumQuestLogRewards(questID); if numQuestRewards > 0 then for i = 1, numQuestRewards do local name, texture, numItems, quality, isUsable, itemID = GetQuestLogRewardInfo(i, questID) if IsArtifactPowerItem(itemID) then local _, link = GetItemInfo(itemID) if link then local ap = self:GetItemAP(itemID, link) --print('ap =', ap) if ap then self.worldQuestAP = self.worldQuestAP + ap end self.worldQuestItems[itemID] = (self.worldQuestItems[itemID] or 0) + 1 end --print(self.worldQuestAP) end end end else C_TaskQuest.RequestPreloadRewardData(questID); self.waitingForQuestRewardData = true end end end end end end function Module:UpdateArtifactButtons() -- Artifact icons, in no particular order self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo() self.lastButton = nil self.canAddAP = nil self.canAddFishingAP = nil local hasArtifacts local numButtons = 0 local lastFrame = self local fishingID, fishingData local index, button local equipped =self.profile.artifacts[self.equippedID] local buttonsWidth = 0 if equipped then numButtons = numButtons + 1 button = self.Artifact[numButtons] button.relativeFrame = self button:SetItem(self.equippedID, equipped, numButtons, true, nil) if self.equippedID ~= button.itemID then hasArtifacts = true end lastFrame = button buttonsWidth = EQUIPPED_SIZE + (FRAME_PADDING * 2) end for itemID, artifact in pairs(self.profile.artifacts) do if (itemID == UNDERLIGHT_ANGLER_ID) then -- only add if we have fishing AP items and it's not being shown in the equipped slot if VeneerData.ArtifactPower.EnableFishing and (itemID ~= self.equippedID) 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 else hasArtifacts = true numButtons = numButtons + 1 button = self.Artifact[numButtons] button.relativeFrame = lastFrame button:SetItem(itemID, artifact, numButtons, (self.equippedID == itemID), nil) lastFrame = button buttonsWidth = buttonsWidth + lastFrame:GetWidth() + FRAME_PADDING end end end end self.lastButton = lastFrame 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:SetItem(fishingID, fishingData, numButtons, self.equippedID == fishingID) self.lastButton = button end self.hasArtifacts = hasArtifacts for i = numButtons+ 1, #self.Artifact do print('hide', i) self.Artifact[i]:Hide() end self.SummaryHeader:ClearAllPoints() if self.lastButton then self.SummaryHeader:SetPoint('TOPLEFT', self.lastButton, 'TOPRIGHT', 4, -2) else self.SummaryHeader:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', 4, 4) end return buttonsWidth end function Module: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 Module: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 Module: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 button.Label:SetText(ShortNumberString(itemAP)) button.numItems = button.numItems + 1 return button end function Module: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 -- tokens > 1M are described as '%f million' if text:match("million") then itemAP = tonumber(itemAP) * 1000000 end 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 Module:UpdateArtifact(itemID, name, texture, currentXP, pointsSpent) print('|cFF00FF00UpdateArtifact()|r') if not self.profile then return end local artifacts = self.profile.artifacts if itemID then 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 artifact.tier = C_ArtifactUI.GetArtifactTier() or ((pointsSpent >= 36) and 2 or 1) artifact.itemID = itemID print('tier', artifact.tier) local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent, artifact.tier) artifact.currentCost = cost end local equippedID = C_ArtifactUI:GetEquippedArtifactInfo() self.currentEquipped = equippedID end function Module: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 Module: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 function Artifact:SetItem(itemID, artifact, index, equipped, fishing) print('|cFF00FFFFSetItem()|r', itemID, index) print(artifact.name, artifact.texture, artifact.currentXP) 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 unusedXP = (itemID ~= UNDERLIGHT_ANGLER_ID) and ((self:GetParent().bankAP or 0) + (self:GetParent().bagAP or 0)) or (self:GetParent().fishingAP or 0) print('unspent:', unusedXP) -- current standing artifact XP (what appears in the artifact ui) -- actual artifact XP after any unlocked points are spent -- total total of invested and inventory XP -- totalCost total of costs between current and actual level local actualXP = artifact.currentXP local actualLevel = artifact.level local actualCost = C_ArtifactUI.GetCostForPointAtRank(actualLevel, artifact.tier) print('tier:', artifact.tier) print('current:', self.level, self.currentXP, '/', self.currentCost) while actualXP >= actualCost do actualXP = actualXP - actualCost actualLevel = actualLevel + 1 actualCost = C_ArtifactUI.GetCostForPointAtRank(actualLevel, artifact.tier) print('* ', actualLevel, actualXP, actualCost, totalCost) end print('actual:', actualLevel, actualXP, '/', actualCost) local totalXP = actualXP + unusedXP local totalCost = actualCost local totalLevel = actualLevel local remaining = totalXP local nextCost = artifact.currentCost print(totalXP, totalCost) if remaining > nextCost then while remaining >= nextCost do totalLevel = totalLevel + 1 remaining = remaining - nextCost nextCost = C_ArtifactUI.GetCostForPointAtRank(totalLevel, artifact.tier) print('|cFFFFFF00+ ', totalLevel, remaining, '/', totalCost) end totalXP = remaining totalCost = nextCost end print('total:', totalLevel, totalXP, '/', totalCost) self.currentLevel = self.level self.actualCost = actualCost self.actualLevel = actualLevel self.actualXP = actualXP self.totalXP = totalXP self.totalCost = totalCost self.totalLevel = totalLevel 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.itemID = itemID self.isEquipped = equipped self:Update() self:SetShown(true) return self end function Artifact:UpdateXPBar() local r3, g3, b3 = 1, .5, 0 -- main xp bar -- current: amount shown in blizz ui -- actual: amount contributing the next level, will be same until current point cap is reached -- potential: total of ap on hand print(self.currentXP, self.actualXP, self.potentialXP) local maxHeight = self:GetHeight() - (XP_INSET*2) local currentHeight = self.CurrentProgress:GetHeight() or 1 local offHeight = self.AdjustedProgress:GetHeight() or 1 self.CurrentProgress:SetPoint('BOTTOM', self, 'BOTTOM', 0, XP_INSET) local currentProgress = (self.currentXP < self.currentCost) and (self.currentXP / self.currentCost) or 1 local projectedProgress = (self.totalXP < self.totalCost) and (self.totalXP / self.totalCost) or 1 if self.actualLevel ~= self.level then r3, g3, b3 = 0, 1, 1 end print('|cFFFF4400', currentProgress, projectedProgress, self.currentLevel, self.totalLevel) if self.level <= WEAPON_MAX_TRAITS then self.CurrentProgress.animateFrom = currentHeight or 1 self.CurrentProgress.animateTo = currentProgress * maxHeight self.CurrentProgress:Show() else self.CurrentProgress:Hide() end local nextLevel = (self.totalLevel ~= self.currentLevel) if self.totalXP ~= self.currentXP or nextLevel then print('project', 'xp test=', (self.totalXP ~= self.currentXP), 'lvl test=', (self.totalLevel ~= self.currentLevel)) local projectedPos = projectedProgress if projectedProgress > currentProgress and (not nextLevel) then projectedPos = (projectedProgress - currentProgress) self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP', 0, 0) print(' set above', projectedPos, self.CurrentProgress:GetPoint(3)) else self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM', 0 , XP_INSET) print(' set under', projectedPos) end self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1 self.AdjustedProgress.animateTo = projectedPos * maxHeight self.AdjustedProgress:Show() else print('nothing to project') self.AdjustedProgress:Hide() end --print(self.CurrentProgress:GetPoint(3)) --print(self.CurrentProgress:GetSize()) self.XPBackground:SetPoint('BOTTOMLEFT', self, 'BOTTOMLEFT', XP_INSET, XP_INSET) self.XPBackground:SetPoint('TOPRIGHT', self, 'TOPLEFT', XP_INSET + XP_WIDTH, -XP_INSET) self.CurrentProgress:SetColorTexture(r3,g3,b3,1) end function Artifact:OnLoad() print('|cFFFF4400OnLoad()|r', self:GetName(), self:GetID()) end function Artifact:Update() if not self.itemID then return end print(self:GetName(), '|cff00FFFFUpdate()|r') local r1, g1, b1 = 1, 1, 1 -- top text local r2, g2, b2 = 1, 1, 0 -- bottom text local levelText = self.level local xpText = ShortNumberString(self.currentXP) local costText = ShortNumberString(self.currentCost) local remainingText = ShortNumberString(self.currentCost - self.currentXP) local maxHeight = self:GetHeight() - 4 local currentHeight = self.CurrentProgress:GetHeight() or 1 local offHeight = self.AdjustedProgress:GetHeight() or 1 if self.actualLevel ~= self.level then levelText = self.actualLevel r1, g1, b1 = 0, 1, 0 xpText = ShortNumberString(self.actualXP) costText = ShortNumberString(self.actualCost) remainingText = ShortNumberString(self.actualCost-self.actualXP) --[[elseif self.potentialLevel ~= self.level then r1, g1, b1 = 0, 1, 1 r2, g2, b2 = 0, 1, 1 costText = ShortNumberString(self.potentialCost) remainingText = ShortNumberString(self.potentialCost-self.potentialXP) --]] end self.Level:SetText(levelText) self.CurrentXP:SetText( xpText ) self.RemainingCost:SetText(remainingText) self.Level:SetTextColor(r1, g1, b1) self.CurrentXP:SetTextColor(r1, g1, b1) if self.isEquipped then self:SetSize(64,64) self:SetNormalTexture([[Interface\Buttons\ButtonHilight-Square]]) self:GetNormalTexture():SetBlendMode('ADD') self:GetNormalTexture():SetVertexColor(0,1,0) else self:SetSize(48,48) self:SetNormalTexture(nil, 'ADD') end self:UpdateXPBar() if self.actualLevel ~= self.currentLevel then self:SetNormalTexture([[Interface\Buttons\UI-Quickslot-Depress]], 'ADD') self:GetNormalTexture():SetBlendMode('BLEND') self:GetNormalTexture():SetVertexColor(1,1,1) else self:SetNormalTexture(nil, 'ADD') end self.Icon:SetTexture(self.texture) end local XP_SCALING_DURATION = .5 function Artifact: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 >= XP_SCALING_DURATION then region:SetHeight(progressTo) region.animateTo = nil region.animateStart = nil region.animateFrom = nil else local progress = elapsed / XP_SCALING_DURATION 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 Artifact:OnUpdate(sinceLast) if self.CurrentProgress.animateTo then self:AnimateProgress(self.CurrentProgress) end if self.AdjustedProgress.animateTo then self:AnimateProgress(self.AdjustedProgress) end end function Artifact:OnEnter() GameTooltip:SetOwner(self, 'ANCHOR_CURSOR') GameTooltip:SetText(self.name) GameTooltip:AddLine(ShortNumberString(self.currentXP) .. ' / '..ShortNumberString(self.currentCost), 1, 1, 1) if self.actualLevel ~= self.level then GameTooltip:AddLine(ShortNumberString(self.actualLevel - self.level) .. ' points unlocked', 1, 1, 0) end if self.currentXP < self.currentCost then GameTooltip:AddLine(ShortNumberString(self.currentCost - self.currentXP) .. ' for level ' .. (self.currentLevel+1), 1, 1, 0) else GameTooltip:AddLine(ShortNumberString(self.actualCost - self.actualXP) .. ' for level ' .. (self.actualLevel+1), 0, 1, 0) end if self.totalLevel ~= self.actualLevel then GameTooltip:AddLine('Level ' .. self.totalLevel .. ' with unspent tokens', 0, 1, 1) end GameTooltip:Show() end function Artifact:OnLeave() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function Artifact:OnHide() if GameTooltip:IsOwned(self) then GameTooltip:Hide() end end function Artifact:OnClick(button, down) if self.isEquipped then SocketInventoryItem(16) else if IsShiftKeyDown() then SocketContainerItem(self.containerID, self.slotID) else end end end