annotate Modules/ArtifactPower.lua @ 103:8df154a2bfd6 v7.1.5-r104

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