annotate Modules/ArtifactPower.lua @ 102:1e511e9aaca5

- clean up handler loading inconsistencies; exclude free frames from anchor cluster iterations, and remove extraneous PLAYER_LOGIN handling - added a Setup method to the handler template that creates and reconciles a SavedVariables table for that module
author Nenue
date Wed, 25 Jan 2017 23:11:27 -0500
parents f32b63c93275
children 8df154a2bfd6
rev   line source
Nenue@97 1 -- Veneer
Nenue@97 2 -- ArtifactPower.lua
Nenue@97 3 -- Created: 1/15/2017 11:44 PM
Nenue@97 4 -- %file-revision%
Nenue@97 5 --
Nenue@97 6
Nenue@97 7 local print = DEVIAN_WORKSPACE and function(...) print('VnAP', ...) end or nop
Nenue@97 8 VeneerArtifactPowerMixin = {
Nenue@99 9 numItems = 0,
Nenue@99 10 Tokens = {},
Nenue@101 11 cache = {},
Nenue@101 12 fishingCache = {},
Nenue@101 13 scanQueue = {},
Nenue@99 14 ItemButtons = {},
Nenue@97 15 anchorPoint = 'TOP',
Nenue@97 16 anchorFrom = 'TOP',
Nenue@97 17 }
Nenue@101 18 local defaultSettings = {
Nenue@101 19 firstUse = true,
Nenue@101 20 autoHide = true,
Nenue@101 21 }
Nenue@97 22 local ap = VeneerArtifactPowerMixin
Nenue@97 23 local BAGS_TO_SCAN = {BACKPACK_CONTAINER }
Nenue@97 24 local TOOLTIP_NAME = 'VeneerAPScanner'
Nenue@98 25 local POINT_COSTS = {
Nenue@98 26 100, 300, 325, 350, 375,
Nenue@98 27 400, 425, 450, 525, 625,
Nenue@98 28 750, 875, 1000, 6840, 8830,
Nenue@98 29 11280, 14400, 18620, 24000, 30600,
Nenue@98 30 39520, 50880, 64800, 82500, 105280,
Nenue@98 31 138650, 182780, 240870, 325520, 417560,
Nenue@98 32 546000, 718200, 946660, 1245840, 1635200,
Nenue@98 33 191500, 2010000, 2110000, 2215000, 2325000,
Nenue@98 34 2440000, 2560000, 2690000, 2825000, 2965000,
Nenue@98 35 3115000, 3270000, 3435000, 3605000, 3785000,
Nenue@98 36 3975000, 4175000, 4385000, 4605000
Nenue@98 37 }
Nenue@97 38
Nenue@99 39 local FRAME_LIST = {'ContainerFrame1', 'BankFrame'}
Nenue@99 40 local BAG_FRAMES = {'ContainerFrame1'}
Nenue@99 41 local BANK_FRAMES = {'BankFrame'}
Nenue@99 42
Nenue@97 43 function ap:OnLoad()
Nenue@97 44 self:RegisterEvent('BAG_UPDATE') -- use to obtain bag IDs to scan
Nenue@97 45 self:RegisterEvent('BAG_UPDATE_DELAYED') -- use to trigger actual scan activity
Nenue@97 46 self:RegisterEvent('BANKFRAME_OPENED') -- determine when bank info is available
Nenue@97 47 self:RegisterEvent('BANKFRAME_CLOSED') -- " " "
Nenue@97 48 self:RegisterEvent('ARTIFACT_UPDATE') -- when artifact data has changed
Nenue@98 49 self:RegisterEvent('ARTIFACT_XP_UPDATE') -- when artifact xp has changed (but not necessarily data)
Nenue@97 50 self:RegisterEvent('PLAYER_REGEN_ENABLED')
Nenue@97 51 self:RegisterEvent('PLAYER_REGEN_DISABLED')
Nenue@99 52 self:RegisterEvent('PLAYER_ENTERING_WORLD')
Nenue@97 53 Veneer:AddHandler(self, self.anchorPoint, true)
Nenue@97 54 SLASH_VENEER_AP1 = "/vap"
Nenue@97 55 SLASH_VENEER_AP2 = "/veneerap"
Nenue@98 56 SlashCmdList.VENEER_AP = function(arg)
Nenue@98 57 if arg == 'fishing' then
Nenue@98 58 if VeneerData.ArtifactPower.EnableFishing then
Nenue@98 59 VeneerData.ArtifactPower.EnableFishing = nil
Nenue@98 60 else
Nenue@98 61 VeneerData.ArtifactPower.EnableFishing = true
Nenue@98 62 end
Nenue@98 63 self:Print('Show Underlight Angler:', (VeneerData.ArtifactPower.EnableFishing and 'ON' or 'OFF'))
Nenue@98 64 self:Update()
Nenue@98 65
Nenue@98 66 else
Nenue@98 67 self:Show()
Nenue@98 68 end
Nenue@97 69 end
Nenue@97 70
Nenue@97 71 self.tooltip = CreateFrame('GameTooltip', TOOLTIP_NAME, self, 'GameTooltipTemplate')
Nenue@99 72 tinsert(UISpecialFrames, self:GetName())
Nenue@99 73
Nenue@97 74
Nenue@97 75 end
Nenue@97 76
Nenue@102 77
Nenue@102 78 local IsBagnonOpen = function()
Nenue@102 79 return ((BagnonFramebank and BagnonFramebank:IsShown()) or (BagnonFrameinventory and BagnonFrameinventory:IsShown()))
Nenue@102 80 end
Nenue@99 81 local addonCompatibility = {
Nenue@99 82 ['Bagnon'] = {
Nenue@99 83 BagFrames = {'BagnonFrameinventory'},
Nenue@99 84 BankFrames = {'BagnonFramebank'},
Nenue@102 85 FrameMethods = {
Nenue@102 86 ['HideFrame'] = IsBagnonOpen,
Nenue@102 87 ['ShowFrame'] = IsBagnonOpen
Nenue@102 88 },
Nenue@99 89 PostHooks = {'ToggleAllBags', 'ToggleBackpack' },
Nenue@99 90 MethodClass = 'Bagnon',
Nenue@102 91 MethodHooks = {'BANK_OPENED', 'BANKFRAME_CLOSED'},
Nenue@102 92
Nenue@99 93 }
Nenue@97 94 }
Nenue@97 95
Nenue@102 96 local function AddFrameHooks(frame, args)
Nenue@102 97 for funcName, func in pairs(args.FrameMethods) do
Nenue@102 98 print('binding', frame:GetName(), funcName, 'to', tostring(func))
Nenue@102 99 hooksecurefunc(frame, funcName, func)
Nenue@102 100 end
Nenue@102 101 end
Nenue@102 102 local PENDING_HOOKS = {}
Nenue@102 103
Nenue@102 104 local function RegisterInventoryFrame(name, listType, args)
Nenue@102 105 print('register', name, 'as inventory frame type =', (listType == BAG_FRAMES) and 'bags' or 'bank')
Nenue@102 106 tinsert(FRAME_LIST, name)
Nenue@102 107 tinsert(listType, name)
Nenue@102 108 if _G[name] then
Nenue@102 109 AddFrameHooks(_G[name], args)
Nenue@102 110 else
Nenue@102 111 PENDING_HOOKS[name] = args
Nenue@102 112 end
Nenue@102 113 end
Nenue@102 114
Nenue@99 115
Nenue@97 116 function ap:Setup()
Nenue@97 117 print(self:GetName()..':Setup()')
Nenue@97 118 local guid = UnitGUID('player')
Nenue@97 119 VeneerData.ArtifactPower = VeneerData.ArtifactPower or defaultSettings
Nenue@101 120 self.db = VeneerData.ArtifactPower
Nenue@101 121 self.db[guid] = self.db[guid] or {}
Nenue@101 122 self.db.cache = self.db.cache or {}
Nenue@101 123 self.db.fishingCache = self.db.fishingCache or {}
Nenue@101 124
Nenue@101 125 for i, data in pairs(self.cache) do
Nenue@101 126 -- bring in anything found before player data is active
Nenue@101 127 self.db.cache[i] = data
Nenue@101 128 end
Nenue@101 129 for i, data in pairs(self.fishingCache) do
Nenue@101 130 self.db.fishingCache[i] = data
Nenue@101 131 end
Nenue@101 132
Nenue@101 133
Nenue@101 134 self.cache = self.db.cache
Nenue@101 135 self.profile = self.db[guid]
Nenue@97 136 self.profile.bagslots = self.profile.bagslots or {}
Nenue@97 137 self.profile.artifacts = self.profile.artifacts or {}
Nenue@97 138 self.updateSummary = true
Nenue@97 139
Nenue@101 140 VeneerArtifactPowerTimer:SetScript('OnUpdate', function()
Nenue@101 141 self:OnUpdate()
Nenue@101 142 end)
Nenue@101 143
Nenue@99 144 local DoTryToShow = function()
Nenue@99 145 self:TryToShow()
Nenue@99 146 end
Nenue@99 147 hooksecurefunc("OpenBackpack", DoTryToShow)
Nenue@99 148 hooksecurefunc("CloseBackpack", DoTryToShow)
Nenue@99 149
Nenue@97 150 -- Bagnon compatibility
Nenue@97 151 -- todo: ArkInventory, Elv, etc
Nenue@99 152 for addon, args in pairs(addonCompatibility) do
Nenue@99 153 if IsAddOnLoaded(addon) then
Nenue@102 154
Nenue@99 155 for _, name in ipairs(args.BagFrames) do
Nenue@102 156 RegisterInventoryFrame(name, BAG_FRAMES, args)
Nenue@99 157 end
Nenue@99 158 for _, name in ipairs(args.BankFrames) do
Nenue@102 159 RegisterInventoryFrame(name, BANK_FRAMES, args)
Nenue@99 160 end
Nenue@102 161
Nenue@102 162 -- should only specify non-secure functions in this table
Nenue@99 163 for _, name in ipairs(args.PostHooks) do
Nenue@99 164 local oFunc = _G[name]
Nenue@99 165 _G[name] = function(...)
Nenue@99 166 print('|cFFFF0088' .. name .. '|r', ...)
Nenue@99 167 oFunc(...)
Nenue@99 168 self:TryToShow()
Nenue@99 169 end
Nenue@99 170 end
Nenue@99 171 local frame = _G[args.MethodClass]
Nenue@99 172 if frame then
Nenue@99 173 for _, name in ipairs(args.MethodHooks) do
Nenue@99 174 hooksecurefunc(frame, name, DoTryToShow)
Nenue@99 175 end
Nenue@97 176 end
Nenue@97 177 end
Nenue@97 178 end
Nenue@101 179
Nenue@101 180 if self.db.firstUse then
Nenue@101 181 self.db.firstUse = nil
Nenue@101 182
Nenue@101 183 end
Nenue@99 184 end
Nenue@97 185
Nenue@97 186 local UNDERLIGHT_ANGLER_ID = 133755
Nenue@98 187 function ap:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
Nenue@98 188 print('|cFF00FF00SetArtifact()|r')
Nenue@97 189 if not self.profile then
Nenue@97 190 return
Nenue@97 191 end
Nenue@97 192 local artifacts = self.profile.artifacts
Nenue@97 193
Nenue@101 194 local multi = C_ArtifactUI.GetArtifactKnowledgeMultiplier()
Nenue@101 195 self.profile.knowledgeMultiplier = multi or self.profile.knowledgeMultiplier
Nenue@101 196 print('multiplier:', multi)
Nenue@97 197
Nenue@97 198 if itemID then
Nenue@99 199
Nenue@99 200 self.currentEquipped = itemID
Nenue@99 201
Nenue@98 202 artifacts[itemID] = artifacts[itemID] or {}
Nenue@98 203 table.wipe(artifacts[itemID])
Nenue@98 204 local artifact = artifacts[itemID]
Nenue@97 205
Nenue@98 206 artifact.name = name
Nenue@98 207 artifact.texture = texture
Nenue@98 208 artifact.currentXP = currentXP
Nenue@98 209 artifact.level = pointsSpent
Nenue@98 210 local cost = C_ArtifactUI.GetCostForPointAtRank(pointsSpent)
Nenue@98 211 artifact.cost = cost
Nenue@97 212
Nenue@98 213 local pointsAvailable = pointsSpent
Nenue@98 214 local actualCost = cost
Nenue@98 215 local actualXP = currentXP
Nenue@98 216 while actualXP >= actualCost do
Nenue@98 217 pointsAvailable = pointsAvailable + 1
Nenue@98 218 actualXP = actualXP - actualCost
Nenue@98 219 print(pointsAvailable, '-', actualCost, '=', actualXP)
Nenue@98 220 actualCost = C_ArtifactUI.GetCostForPointAtRank(pointsAvailable)
Nenue@98 221 end
Nenue@98 222 print('updating', itemID, name, currentXP, pointsSpent, pointsAvailable, actualXP)
Nenue@98 223 artifact.actualXP = actualXP
Nenue@98 224 artifact.actualLevel = pointsAvailable
Nenue@98 225 artifact.actualCost = actualCost
Nenue@97 226
Nenue@97 227 end
Nenue@97 228 end
Nenue@97 229 function ap:QueueBag(containerID)
Nenue@97 230 containerID = tonumber(containerID)
Nenue@97 231 if not containerID then
Nenue@97 232 return
Nenue@97 233 end
Nenue@97 234
Nenue@97 235 if not tContains(BAGS_TO_SCAN, containerID) then
Nenue@97 236 print(' queueing', containerID, type(containerID), #BAGS_TO_SCAN , 'in line')
Nenue@97 237 BAGS_TO_SCAN[#BAGS_TO_SCAN + 1] = containerID
Nenue@97 238 end
Nenue@97 239 end
Nenue@97 240
Nenue@99 241 function ap:Reanchor()
Nenue@99 242 if Veneer then
Nenue@99 243 Veneer:DynamicReanchor()
Nenue@99 244 end
Nenue@99 245 end
Nenue@99 246
Nenue@97 247 function ap:OnShow()
Nenue@99 248 print('|cFFFFFF00OnShow()|r')
Nenue@102 249
Nenue@102 250 for name, args in pairs(PENDING_HOOKS) do
Nenue@102 251 if _G[name] then
Nenue@102 252 AddFrameHooks(_G[name], args)
Nenue@102 253 PENDING_HOOKS[name] = nil
Nenue@102 254 end
Nenue@102 255 end
Nenue@102 256
Nenue@102 257
Nenue@97 258 self.enabled = true
Nenue@99 259 self:ScanAllBags()
Nenue@99 260 self:Reanchor()
Nenue@97 261 end
Nenue@97 262 function ap:OnHide()
Nenue@99 263 print('|cFF88FF00OnHide()|r')
Nenue@99 264 self:Reanchor()
Nenue@97 265 end
Nenue@97 266 function ap:OnEnter()
Nenue@97 267
Nenue@97 268 GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
Nenue@97 269
Nenue@99 270
Nenue@97 271 GameTooltip:AddLine(self.bagAP)
Nenue@97 272 GameTooltip:AddLine(self.bankAP)
Nenue@97 273
Nenue@97 274 end
Nenue@97 275
Nenue@99 276 function ap:TryToShow()
Nenue@99 277
Nenue@99 278 print('|cFFFFFF00TryToShow()')
Nenue@99 279
Nenue@99 280 if not InCombatLockdown() then
Nenue@99 281 for _, name in ipairs(FRAME_LIST) do
Nenue@99 282 --print(name, (_G[name] and _G[name]:IsShown()))
Nenue@99 283 if _G[name] and _G[name]:IsShown() then
Nenue@99 284 if self:IsShown() then
Nenue@99 285 self:Update()
Nenue@99 286 else
Nenue@99 287 self:Show()
Nenue@99 288 end
Nenue@99 289 return
Nenue@99 290 end
Nenue@99 291 end
Nenue@99 292 end
Nenue@99 293
Nenue@99 294
Nenue@99 295 self:Hide()
Nenue@99 296 end
Nenue@99 297
Nenue@99 298
Nenue@97 299 function ap:OnEvent(event, ...)
Nenue@99 300 print('|cFF00FF88OnEvent()', event, ...)
Nenue@99 301 if event == 'PLAYER_ENTERING_WORLD' then
Nenue@99 302 self:TryToShow()
Nenue@99 303 elseif event == 'BAG_UPDATE' then
Nenue@97 304 local containerID = ...
Nenue@97 305 self:QueueBag(containerID)
Nenue@97 306 elseif event == 'PLAYER_BANKSLOTS_CHANGED' then
Nenue@99 307 self:ScanAllBags()
Nenue@97 308 elseif event == 'BAG_UPDATE_DELAYED' then
Nenue@99 309 if not self.firstHit then
Nenue@99 310 self.firstHit = true
Nenue@99 311 else
Nenue@99 312 self:ScanAllBags()
Nenue@99 313 end
Nenue@97 314 elseif event == 'BANKFRAME_OPENED' then
Nenue@97 315 self.bankAccess = true
Nenue@99 316 self:ScanAllBags()
Nenue@97 317 elseif event == 'BANKFRAME_CLOSED' then
Nenue@99 318 self.bankAccess = nil
Nenue@97 319 elseif event == 'ARTIFACT_UPDATE' then
Nenue@98 320 local newItem = ...
Nenue@98 321 if newItem then
Nenue@98 322 local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetArtifactInfo()
Nenue@98 323 self:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
Nenue@98 324 self:ScanAllBags(self.bankAccess)
Nenue@98 325 end
Nenue@98 326 elseif event == 'ARTIFACT_XP_UPDATE' then
Nenue@98 327 local itemID, _, name, texture, currentXP, pointsSpent = C_ArtifactUI:GetEquippedArtifactInfo()
Nenue@98 328 self:SetArtifact(itemID, name, texture, currentXP, pointsSpent)
Nenue@98 329 self:ScanAllBags(self.bankAccess)
Nenue@97 330 elseif event == 'PLAYER_REGEN_ENABLED' then
Nenue@97 331 if self.enabled then
Nenue@99 332 if self.queuedScan then
Nenue@99 333 self:ScanAllBags(self.backAccess)
Nenue@99 334 else
Nenue@99 335 self:TryToShow()
Nenue@99 336 end
Nenue@97 337 end
Nenue@97 338
Nenue@97 339 elseif event == 'PLAYER_REGEN_DISABLED' then
Nenue@97 340 self:Hide()
Nenue@97 341 end
Nenue@97 342 end
Nenue@97 343
Nenue@101 344 function ap:OnUpdate()
Nenue@101 345 if #self.scanQueue >= 1 then
Nenue@101 346 local scanInfo = tremove(self.scanQueue, 1)
Nenue@101 347
Nenue@101 348 end
Nenue@101 349 end
Nenue@101 350
Nenue@97 351 function ap:OnMouseDown()
Nenue@97 352 self.enabled = nil
Nenue@97 353 self:Hide()
Nenue@97 354 end
Nenue@97 355
Nenue@97 356 function ap:Update()
Nenue@97 357 if not self:IsShown() then
Nenue@99 358 print('|cFFFF4400Update()|r')
Nenue@97 359 return
Nenue@97 360 end
Nenue@97 361 print('|cFF00FFFFUpdate()|r')
Nenue@97 362
Nenue@97 363 local bankText, bagText
Nenue@101 364 if not self.profile.knowledgeMultiplier then
Nenue@101 365 bankText = '|cFF00FF00Shift-Right-Click an artifact weapon to start building data.'
Nenue@101 366 elseif not (self.bankAP and self.bagAP) then
Nenue@97 367 bankText = '|cFFFF0000Open bank frame to count all AP|r '
Nenue@97 368 else
Nenue@98 369 if (self.bagAP + self.bankAP) == 0 then
Nenue@99 370 bankText = '|cFFFF4400No Artifact Power tokens on hand|r'
Nenue@98 371 else
Nenue@98 372 if self.bagAP and (self.bagAP > 0) then
Nenue@98 373 bankText = '|cFFFFFFFF' .. tostring(self.bagAP) .. '|r'
Nenue@98 374 end
Nenue@98 375 if self.bankAP and (self.bankAP > 0) then
Nenue@98 376 bankText = (bankText and (bankText .. ' | ') or '') .. '|cFFFFFF00'..tostring(self.bankAP)..'|r'
Nenue@98 377 end
Nenue@98 378 end
Nenue@97 379 end
Nenue@99 380 if self.fishingAP and self.fishingAP >= 1 then
Nenue@99 381 bankText = (bankText and (bankText .. ' ') or '') .. '|cFF0088FF' .. tostring(self.fishingAP) .. ' fishing AP|r'
Nenue@99 382 end
Nenue@99 383
Nenue@97 384 self.SummaryHeader:SetText(bankText)
Nenue@97 385
Nenue@101 386 local numButtons = 0
Nenue@101 387 local contentsHeight = 64
Nenue@101 388 if self.profile.knowledgeMultiplier then
Nenue@101 389 numButtons = self:UpdateArtifactButtons()
Nenue@101 390 contentsHeight = contentsHeight + self:UpdateItemButtons()
Nenue@101 391 end
Nenue@101 392
Nenue@101 393
Nenue@101 394
Nenue@101 395 self:SetWidth(64*numButtons + 4 * (numButtons+1))
Nenue@101 396 self:SetHeight(16 + self.SummaryHeader:GetHeight() + contentsHeight)
Nenue@101 397 self:Reanchor()
Nenue@101 398 end
Nenue@101 399
Nenue@101 400 function ap:UpdateArtifactButtons()
Nenue@101 401
Nenue@97 402 -- Artifact icons, in no particular order
Nenue@99 403 self.equippedID = C_ArtifactUI.GetEquippedArtifactInfo()
Nenue@97 404 local numButtons = 0
Nenue@99 405 local lastFrame = self
Nenue@99 406 local fishingID, fishingData
Nenue@98 407 local index, button
Nenue@97 408 for itemID, artifact in pairs(self.profile.artifacts) do
Nenue@99 409 if (itemID == UNDERLIGHT_ANGLER_ID) then
Nenue@98 410 if VeneerData.ArtifactPower.EnableFishing then
Nenue@98 411 fishingID = itemID
Nenue@98 412 fishingData = artifact
Nenue@98 413 end
Nenue@97 414
Nenue@98 415 else
Nenue@98 416 numButtons = numButtons + 1
Nenue@98 417 button = self.Artifact[numButtons]
Nenue@99 418 button.relativeFrame = lastFrame
Nenue@99 419 lastFrame = button:SetButton(itemID, artifact, numButtons, (self.equippedID == itemID))
Nenue@97 420 end
Nenue@97 421
Nenue@98 422 end
Nenue@97 423
Nenue@98 424 if fishingData then
Nenue@98 425 numButtons = numButtons + 1
Nenue@99 426 local button = self.Artifact[numButtons]
Nenue@99 427 button.relativeFrame = lastFrame
Nenue@99 428 button:SetButton(fishingID, fishingData, numButtons, self.equippedID == fishingID)
Nenue@98 429 end
Nenue@97 430
Nenue@99 431 for i = numButtons+ 1, #self.Artifact do
Nenue@97 432 print('hide', i)
Nenue@97 433 self.Artifact[i]:Hide()
Nenue@97 434 end
Nenue@97 435
Nenue@101 436 return numButtons
Nenue@97 437 end
Nenue@97 438
Nenue@99 439
Nenue@99 440 function ap:UpdateItemButtons()
Nenue@99 441 print('|cFF00FFFFUpdateItemButtons()|r')
Nenue@99 442 local lastFrame, upFrame
Nenue@99 443 local numButtons = 0
Nenue@101 444 local buttonsHeight = 0
Nenue@101 445 local buttonWidth = 0
Nenue@99 446 for index, button in ipairs(self.Tokens) do
Nenue@99 447 if button.numItems >= 1 then
Nenue@99 448 if button.itemName then
Nenue@99 449 self:SetItemAction(button)
Nenue@99 450 end
Nenue@99 451
Nenue@99 452 button:ClearAllPoints()
Nenue@99 453 numButtons = numButtons + 1
Nenue@99 454 print(index, button:GetID(), button.Icon:GetTexture())
Nenue@99 455 if numButtons == 1 then
Nenue@101 456 button:SetPoint('TOPLEFT', self, 'TOPLEFT', 4, -76)
Nenue@99 457 upFrame = button
Nenue@101 458 buttonsHeight = 52
Nenue@99 459 elseif mod(numButtons,8) == 1 then
Nenue@99 460 button:SetPoint('TOPLEFT', upFrame, 'BOTTOMLEFT', 0, -2)
Nenue@99 461 upFrame = button
Nenue@101 462 buttonsHeight = buttonsHeight + 52
Nenue@99 463 else
Nenue@99 464 button:SetPoint('TOPLEFT', lastFrame, 'TOPRIGHT', 2, 0)
Nenue@99 465 end
Nenue@99 466 button.Count:SetText(button.numItems)
Nenue@99 467 lastFrame = button
Nenue@99 468 button:Show()
Nenue@99 469 else
Nenue@99 470 button:Hide()
Nenue@99 471 end
Nenue@99 472 end
Nenue@99 473
Nenue@101 474
Nenue@101 475
Nenue@101 476 return buttonsHeight
Nenue@99 477 end
Nenue@99 478
Nenue@99 479 function ap:SetItemAction(button, name)
Nenue@99 480 name = name or self.itemName
Nenue@99 481 if InCombatLockdown() then
Nenue@99 482 self.itemName = name
Nenue@99 483 return
Nenue@99 484 else
Nenue@99 485 button:SetAttribute('*type*','item')
Nenue@99 486 button:SetAttribute('*item*', name)
Nenue@99 487 end
Nenue@99 488 end
Nenue@99 489
Nenue@99 490 function ap:GetItemButton(itemID, texture, itemAP)
Nenue@99 491 print('|cFF00FFFFGetItemButton()|r', itemID, texture, itemAP)
Nenue@99 492 local button = self.ItemButtons[itemID]
Nenue@101 493
Nenue@99 494 if not button then
Nenue@99 495 button = CreateFrame('Button', 'VeneerAPToken'..itemID, self, 'VeneerItemButton')
Nenue@101 496 button.baseAP = itemAP
Nenue@101 497
Nenue@99 498 button:SetPushedTexture([[Interface\Buttons\UI-Quickslot-Depress]])
Nenue@99 499 button:SetHighlightTexture([[Interface\Buttons\ButtonHilight-Square]],"ADD")
Nenue@99 500 button:SetID(itemID)
Nenue@99 501 button.numItems = 0
Nenue@99 502 button.Icon:SetTexture(texture)
Nenue@99 503 button:RegisterForClicks("AnyUp")
Nenue@99 504 self:SetItemAction(button, GetItemInfo(itemID))
Nenue@99 505
Nenue@99 506 print(' created')
Nenue@99 507 self.ItemButtons[itemID] = button
Nenue@99 508 self.numItems = self.numItems + 1
Nenue@99 509 end
Nenue@99 510
Nenue@101 511 local itemAPtext = itemAP * self.profile.knowledgeMultiplier
Nenue@101 512 if itemAPtext >= 100000 then
Nenue@101 513 itemAPtext = floor(itemAPtext/1000) .. 'k'
Nenue@101 514 elseif itemAPtext >= 1000 then
Nenue@101 515 itemAPtext = (floor(itemAPtext/100)/10 ) .. 'k'
Nenue@101 516 end
Nenue@101 517 button.Label:SetText(itemAPtext)
Nenue@101 518
Nenue@99 519 button.numItems = button.numItems + 1
Nenue@99 520 return button
Nenue@99 521 end
Nenue@99 522
Nenue@101 523 function ap:GetItemAP(itemID, itemLink, bagData)
Nenue@101 524 if not self.cache[itemID] then
Nenue@101 525
Nenue@101 526 print('doing tooltip scan')
Nenue@101 527 self.tooltip:SetOwner(self, 'ANCHOR_NONE')
Nenue@101 528 self.tooltip:SetHyperlink(itemLink)
Nenue@101 529 self.tooltip:Show()
Nenue@101 530 local numLines = self.tooltip:NumLines()
Nenue@101 531 if numLines >= 3 then
Nenue@101 532 local subText = _G[TOOLTIP_NAME .. 'TextLeft2']:GetText()
Nenue@101 533 if subText and subText:match(ARTIFACT_POWER) then
Nenue@101 534 for i = 3, numLines do
Nenue@101 535 local text = _G[TOOLTIP_NAME .. 'TextLeft'.. i]:GetText()
Nenue@101 536 if text and text:match(ARTIFACT_POWER) then
Nenue@101 537 text = text:gsub('[,%D]', '')
Nenue@101 538 print(itemLink, '-', tonumber(text))
Nenue@101 539 local itemAP = tonumber(text)
Nenue@101 540 if itemAP then
Nenue@101 541 itemAP = itemAP / self.profile.knowledgeMultiplier
Nenue@101 542 self.cache[itemID] = itemAP
Nenue@101 543 end
Nenue@101 544 end
Nenue@101 545 end
Nenue@101 546 end
Nenue@101 547 local fishingText = _G[TOOLTIP_NAME .. 'TextLeft3']:GetText()
Nenue@101 548 if fishingText and fishingText:match('fishing artifact') then
Nenue@101 549 local fishingAP = fishingText:match("%d+")
Nenue@101 550 fishingAP = tonumber(fishingAP)
Nenue@101 551 if fishingAP then
Nenue@101 552 self.cache[itemID] = fishingAP
Nenue@101 553 self.fishingCache[itemID] = true
Nenue@101 554 end
Nenue@101 555 end
Nenue@101 556 else
Nenue@101 557
Nenue@101 558 self.cache[itemID] = 0
Nenue@101 559 end
Nenue@101 560 end
Nenue@101 561 return self.cache[itemID], self.fishingCache[itemID]
Nenue@101 562 end
Nenue@101 563
Nenue@97 564 function ap:ScanBag(id)
Nenue@97 565 print('|cFF00FFFFScanBag()|r', id, IsBagOpen(id), GetContainerNumSlots(id))
Nenue@97 566 local numSlots = GetContainerNumSlots(id)
Nenue@97 567 local requiresUpdate
Nenue@97 568 if numSlots == 0 then
Nenue@97 569 return nil
Nenue@97 570 end
Nenue@97 571
Nenue@97 572
Nenue@97 573 self.profile.bagslots[id] = self.profile.bagslots[id] or {}
Nenue@97 574 table.wipe(self.profile.bagslots[id])
Nenue@97 575 local bagData = self.profile.bagslots[id]
Nenue@97 576 bagData.totalAP = 0
Nenue@99 577 bagData.fishingAP = 0
Nenue@99 578 bagData.items = bagData.items or {}
Nenue@99 579 table.wipe(bagData.items)
Nenue@99 580
Nenue@97 581 for slotID = 1, numSlots do
Nenue@97 582 local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(id, slotID)
Nenue@101 583 if link then
Nenue@101 584 local itemID = GetContainerItemID(id, slotID)
Nenue@101 585 local name, _, quality, iLevel, reqLevel, class, subclass = GetItemInfo(link)
Nenue@97 586
Nenue@101 587 if class == 'Consumable' and subclass == 'Other' then
Nenue@102 588 --print(GetItemInfo(link))
Nenue@101 589 local itemAP, isFishingAP = self:GetItemAP(itemID, link)
Nenue@102 590 --print(itemAP, isFishingAP)
Nenue@102 591 if itemAP and (itemAP > 0) then
Nenue@102 592 local itemButton = self:GetItemButton(itemID, texture, itemAP)
Nenue@102 593
Nenue@101 594 if isFishingAP then
Nenue@101 595 bagData.fishingItems = (bagData.fishingItems or 0) + 1
Nenue@101 596 bagData.fishingAP = (bagData.fishingAP or 0) + itemAP
Nenue@101 597 else
Nenue@102 598 itemAP = itemAP * self.profile.knowledgeMultiplier
Nenue@101 599 bagData.numItems = (bagData.numItems or 0) + 1
Nenue@101 600 bagData.totalAP = (bagData.totalAP or 0) + itemAP
Nenue@101 601 end
Nenue@101 602 bagData.items[itemID] = (bagData.items[itemID] or 0) + 1
Nenue@101 603 end
Nenue@101 604 elseif self.profile.artifacts[itemID] then
Nenue@101 605 print('artfiact weapon', itemID, link, id, slotID)
Nenue@101 606 self.profile.artifacts[itemID].containerID = id
Nenue@101 607 self.profile.artifacts[itemID].slotID = slotID
Nenue@101 608 end
Nenue@99 609
Nenue@97 610 end
Nenue@97 611
Nenue@97 612 end
Nenue@97 613
Nenue@97 614 end
Nenue@97 615
Nenue@98 616 local BAG_SLOTS = {0, 1, 2, 3, 4 }
Nenue@98 617 local BANK_SLOTS = {-1, 5, 6,7, 8, 9, 10, 11, 12}
Nenue@99 618 local ItemCounts = {}
Nenue@99 619 function ap:ScanAllBags()
Nenue@99 620 if InCombatLockdown() then
Nenue@99 621 self.queuedScan = true
Nenue@99 622 return
Nenue@99 623 end
Nenue@101 624 if not self.profile.knowledgeMultiplier then
Nenue@101 625 print('need to get knowledge level')
Nenue@101 626 return
Nenue@101 627 end
Nenue@101 628
Nenue@99 629 self.queuedScan = nil
Nenue@98 630
Nenue@101 631 print('|cFFFF0088ScanAllBags()|r', self.profile.knowledgeMultiplier)
Nenue@97 632
Nenue@99 633 for _, button in ipairs(self.Tokens) do
Nenue@99 634 button.numItems = 0
Nenue@99 635 end
Nenue@99 636
Nenue@99 637
Nenue@98 638 for _, bagID in ipairs(BAG_SLOTS) do
Nenue@98 639 self:ScanBag(bagID)
Nenue@97 640 end
Nenue@97 641
Nenue@99 642 if self.bankAccess then
Nenue@98 643 for _, bagID in ipairs(BANK_SLOTS) do
Nenue@98 644 self:ScanBag(bagID)
Nenue@98 645 end
Nenue@98 646 end
Nenue@98 647
Nenue@98 648 self.bankAP = 0
Nenue@98 649 self.bagAP = 0
Nenue@99 650 self.fishingAP = 0
Nenue@99 651
Nenue@99 652 table.wipe(ItemCounts)
Nenue@98 653 for id, bagData in pairs(self.profile.bagslots) do
Nenue@98 654 print(id, GetBagName(id), bagData.totalAP)
Nenue@98 655 id = tonumber(id)
Nenue@98 656 if bagData.totalAP then
Nenue@98 657 if (id == BANK_CONTAINER) or (id >= 5) then
Nenue@98 658 self.bankAP = self.bankAP + bagData.totalAP
Nenue@98 659 else
Nenue@98 660 self.bagAP = self.bagAP + bagData.totalAP
Nenue@97 661 end
Nenue@98 662 end
Nenue@99 663 if bagData.fishingAP then
Nenue@99 664 self.fishingAP = self.fishingAP + bagData.fishingAP
Nenue@99 665 end
Nenue@97 666
Nenue@97 667 end
Nenue@98 668 self.lastUpdate = GetTime()
Nenue@99 669 self:TryToShow()
Nenue@97 670 end
Nenue@97 671
Nenue@97 672 VeneerArtifactButtonMixin = {}
Nenue@98 673
Nenue@99 674 function VeneerArtifactButtonMixin:SetButton(itemID, artifact, index, equipped)
Nenue@99 675 print(itemID, index)
Nenue@98 676 print(artifact.name, artifact.texture, artifact.currentXP)
Nenue@98 677 self:SetID(itemID)
Nenue@98 678 for k,v in pairs(artifact) do
Nenue@98 679 --print('::',k,v)
Nenue@98 680 self[k] = v
Nenue@98 681 end
Nenue@98 682
Nenue@98 683 -- this can change between artifact parses
Nenue@98 684 local potentialPoints = self.actualLevel
Nenue@99 685 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 686 print(totalAP)
Nenue@98 687 local potentialXP = self.actualXP + totalAP
Nenue@99 688
Nenue@98 689 self.potentialXP = potentialXP
Nenue@98 690 local potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints)
Nenue@98 691 while potentialXP >= potentialCost do
Nenue@98 692 potentialXP = potentialXP - potentialCost
Nenue@98 693 potentialPoints = potentialPoints + 1
Nenue@98 694 print('inc estimate', potentialXP, potentialPoints)
Nenue@98 695 potentialCost = C_ArtifactUI.GetCostForPointAtRank(potentialPoints)
Nenue@98 696 end
Nenue@98 697 self.potentialCost = potentialCost
Nenue@98 698 self.potentialLevel = potentialPoints
Nenue@98 699 self.potentialAdjustedXP = potentialXP
Nenue@98 700
Nenue@102 701
Nenue@98 702
Nenue@99 703 if index ~= 1 then
Nenue@99 704 self:ClearAllPoints()
Nenue@99 705 self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPRIGHT', 4, 0)
Nenue@99 706 else
Nenue@99 707 self:ClearAllPoints()
Nenue@99 708 self:SetPoint('TOPLEFT', self.relativeFrame, 'TOPLEFT', 4, -4)
Nenue@99 709 end
Nenue@98 710
Nenue@99 711 self.isEquipped = equipped
Nenue@98 712 self:Update()
Nenue@98 713 self:Show()
Nenue@98 714 return self
Nenue@98 715 end
Nenue@98 716
Nenue@97 717 function VeneerArtifactButtonMixin:Update()
Nenue@97 718
Nenue@99 719 local r, g, b = 1, 1, 1
Nenue@99 720 local lR, lG, lB = 1, 1, 0
Nenue@99 721 local levelText = self.level
Nenue@99 722 local xpValue = self.currentXP
Nenue@99 723 local costValue = self.cost
Nenue@97 724 if self.actualLevel ~= self.level then
Nenue@99 725 levelText, r,g,b = self.actualLevel, 0,1,0
Nenue@99 726 xpValue, costValue, lR, lG, lB = self.actualXP, self.actualCost, 0, 1, 0
Nenue@99 727 elseif self.potentialLevel ~= self.level then
Nenue@99 728 levelText, r, g, b = self.potentialLevel, 0,1,1
Nenue@99 729 xpValue, costValue, lR, lG, lB = self.potentialAdjustedXP, self.potentialCost, 0,1,0
Nenue@99 730
Nenue@97 731 end
Nenue@97 732
Nenue@99 733 if xpValue >= 100000 then
Nenue@99 734 xpValue = tostring(floor(xpValue/1000))..'k'
Nenue@99 735 elseif xpValue > 1000 then
Nenue@99 736 xpValue = tostring(floor(xpValue/100)/10)..'k'
Nenue@99 737 end
Nenue@99 738 if costValue >= 100000 then
Nenue@99 739 costValue = tostring(floor(costValue/1000))..'k'
Nenue@99 740 elseif costValue >= 1000 then
Nenue@99 741 costValue = tostring(floor(costValue/100)/10)..'k'
Nenue@99 742 end
Nenue@99 743
Nenue@99 744
Nenue@99 745 self.Level:SetText(levelText)
Nenue@99 746 self.Level:SetTextColor(r, g, b)
Nenue@99 747 self.CurrentXP:SetText(xpValue)
Nenue@99 748 self.CurrentXP:SetTextColor(lR, lG, lB)
Nenue@99 749
Nenue@97 750 if self.isEquipped then
Nenue@97 751 self:SetNormalTexture([[Interface\Buttons\ButtonHilight-Square]])
Nenue@97 752 self:GetNormalTexture():SetBlendMode('ADD')
Nenue@97 753 self:GetNormalTexture():SetVertexColor(0,1,0)
Nenue@97 754 else
Nenue@97 755 self:SetNormalTexture(nil, 'ADD')
Nenue@97 756 end
Nenue@97 757
Nenue@98 758 local currentProgress = (self.currentXP < self.cost) and (self.currentXP / self.cost) or 1
Nenue@98 759 if self.level <= 53 then
Nenue@99 760
Nenue@98 761 self.CurrentProgress.animateFrom = self.CurrentProgress:GetHeight() or 1
Nenue@98 762 self.CurrentProgress.animateTo = currentProgress * self:GetHeight()
Nenue@98 763 self.CurrentProgress:Show()
Nenue@101 764 self.ProgressLine:Show()
Nenue@98 765 else
Nenue@98 766 self.CurrentProgress:Hide()
Nenue@101 767 self.ProgressLine:Hide()
Nenue@98 768 end
Nenue@99 769
Nenue@98 770 if self.potentialXP > self.currentXP then
Nenue@99 771 local projectedProgress = (self.potentialAdjustedXP < self.potentialCost) and (self.potentialXP / self.potentialCost) or 1
Nenue@99 772
Nenue@98 773 if (projectedProgress > currentProgress) then
Nenue@98 774 self.AdjustedProgress:SetPoint('BOTTOM', self.CurrentProgress, 'TOP')
Nenue@98 775 projectedProgress = projectedProgress - currentProgress
Nenue@99 776
Nenue@98 777 else
Nenue@98 778 self.AdjustedProgress:SetPoint('BOTTOM', self, 'BOTTOM')
Nenue@98 779 end
Nenue@99 780 print('show potential', currentProgress, projectedProgress)
Nenue@98 781 self.AdjustedProgress.animateFrom = self.AdjustedProgress:GetHeight() or 1
Nenue@98 782 self.AdjustedProgress.animateTo = projectedProgress * self:GetHeight()
Nenue@97 783
Nenue@101 784 self.AdjustedLine:Show()
Nenue@98 785 self.AdjustedProgress:Show()
Nenue@98 786 else
Nenue@98 787 self.AdjustedProgress:Hide()
Nenue@101 788 self.AdjustedLine:Hide()
Nenue@98 789 end
Nenue@97 790
Nenue@99 791
Nenue@97 792 self.Icon:SetTexture(self.texture)
Nenue@97 793 self:SetSize(64,64)
Nenue@97 794 end
Nenue@97 795
Nenue@98 796
Nenue@98 797 function VeneerArtifactButtonMixin:AnimateProgress(region)
Nenue@98 798 local cTime = GetTime()
Nenue@98 799 if not region.animateStart then
Nenue@98 800 region.animateStart = cTime
Nenue@98 801 end
Nenue@98 802 local progressTo, progressFrom = region.animateTo, region.animateFrom
Nenue@98 803 local elapsed = cTime - region.animateStart
Nenue@98 804 if elapsed >= .5 then
Nenue@98 805 region:SetHeight(progressTo)
Nenue@98 806 region.animateTo = nil
Nenue@98 807 region.animateStart = nil
Nenue@98 808 region.animateFrom = nil
Nenue@98 809 else
Nenue@98 810 local progress = elapsed / .5
Nenue@98 811 local height = (progressFrom + (progressTo - progressFrom) * progress)
Nenue@98 812 --print(self:GetName(), progressTo, progressFrom, (progressTo - progressFrom), ceil(progress*10)/10, ceil(height))
Nenue@98 813 region:SetHeight(height)
Nenue@98 814 end
Nenue@98 815 end
Nenue@98 816
Nenue@98 817 function VeneerArtifactButtonMixin:OnUpdate(sinceLast)
Nenue@98 818 if self.CurrentProgress.animateTo then
Nenue@98 819 self:AnimateProgress(self.CurrentProgress)
Nenue@98 820 end
Nenue@98 821
Nenue@98 822 if self.AdjustedProgress.animateTo then
Nenue@98 823 self:AnimateProgress(self.AdjustedProgress)
Nenue@98 824 end
Nenue@98 825
Nenue@98 826 end
Nenue@98 827
Nenue@97 828 function VeneerArtifactButtonMixin:OnEnter()
Nenue@97 829 GameTooltip:SetOwner(self, 'ANCHOR_CURSOR')
Nenue@97 830 GameTooltip:SetText(self.name)
Nenue@98 831 GameTooltip:AddLine(tostring(self.currentXP) .. ' / '..tostring(self.cost), 1, 1, 0)
Nenue@98 832 if self.potentialXP > self.currentXP then
Nenue@98 833 GameTooltip:AddLine(tostring(self.potentialXP) .. ' potential XP', 0, 1, 1)
Nenue@99 834 if self.potentialAdjustedXP ~= self.potentialXP then
Nenue@99 835 GameTooltip:AddLine(tostring(self.potentialAdjustedXP) .. ' / ' .. tostring(self.potentialCost).. ' after', 0, 1, 0)
Nenue@98 836 end
Nenue@97 837 end
Nenue@99 838 if self.actualLevel ~= self.level then
Nenue@99 839 GameTooltip:AddLine(tostring(self.actualLevel - self.level) .. ' points unlocked', 0, 1, 1)
Nenue@99 840 end
Nenue@99 841
Nenue@97 842 GameTooltip:Show()
Nenue@97 843 end
Nenue@97 844 function VeneerArtifactButtonMixin:OnLeave()
Nenue@97 845 if GameTooltip:IsOwned(self) then
Nenue@97 846 GameTooltip:Hide()
Nenue@97 847 end
Nenue@97 848 end
Nenue@97 849
Nenue@97 850 function VeneerArtifactButtonMixin:OnClick(button, down)
Nenue@97 851 if self.isEquipped then
Nenue@97 852 SocketInventoryItem(16)
Nenue@97 853 else
Nenue@97 854 SocketContainerItem(self.containerID, self.slotID)
Nenue@97 855 end
Nenue@97 856 end