comparison Shopping.lua @ 89:6bbe64d587b4 v42

Improved artifact/relic reading, gear display. Now creates equipment manager sets when you use button or command to equip a set.
author yellowfive
date Sun, 18 Sep 2016 21:24:08 -0700
parents 0515882856f1
children f1da233629be
comparison
equal deleted inserted replaced
88:b3ff336fad77 89:6bbe64d587b4
17 local _chk1 17 local _chk1
18 local _chk2 18 local _chk2
19 local _chk3 19 local _chk3
20 local _chk4 20 local _chk4
21 local _isAhOpen = false 21 local _isAhOpen = false
22
23 local function incrementTableItem(tbl, key, inc)
24 tbl[key] = tbl[key] and tbl[key] + inc or inc
25 end
22 26
23 local function onShopFrameClose(widget) 27 local function onShopFrameClose(widget)
24 AceGUI:Release(widget) 28 AceGUI:Release(widget)
25 _frameShop = nil 29 _frameShop = nil
26 _cboPlayers = nil 30 _cboPlayers = nil
177 panel:SetWidth(w) 181 panel:SetWidth(w)
178 panel:SetHeight(30) 182 panel:SetHeight(30)
179 scroll:AddChild(panel) 183 scroll:AddChild(panel)
180 184
181 lbl = AceGUI:Create("AmrUiLabel") 185 lbl = AceGUI:Create("AmrUiLabel")
182 lbl:SetWidth(35) 186 lbl:SetWidth(40)
183 lbl:SetWordWrap(false) 187 lbl:SetWordWrap(false)
184 lbl:SetFont(Amr.CreateFont("Bold", 20, Amr.Colors.White)) 188 lbl:SetFont(Amr.CreateFont("Bold", 20, Amr.Colors.White))
185 lbl:SetText(count .. "x") 189 lbl:SetText(count .. "x")
186 lbl:SetPoint("LEFT", panel.content, "LEFT") 190 lbl:SetPoint("LEFT", panel.content, "LEFT")
187 panel:AddChild(lbl) 191 panel:AddChild(lbl)
213 end, { itemIcon = icon, itemText = btn }) 217 end, { itemIcon = icon, itemText = btn })
214 end 218 end
215 219
216 end 220 end
217 221
222 -- get the number of a specified gem/enchant/material that the player currently owns
223 local function getOwnedCount(itemId)
224 local ret = 0
225
226 local list = Amr.db.char.BagItemsAndCounts
227 if list and list[itemId] then
228 ret = ret + list[itemId]
229 end
230
231 list = Amr.db.char.BankItemsAndCounts
232 if list and list[itemId] then
233 ret = ret + list[itemId]
234 end
235
236 return ret
237 end
238
239 local function removeOwned(list, owned)
240
241 for itemId, count in pairs(list) do
242 -- load up how many of an item we have
243 if not owned.loaded[itemId] then
244 owned.counts[itemId] = getOwnedCount(itemId)
245 owned.loaded[itemId] = true
246 end
247
248 -- see how many we can remove from the required count
249 local used = math.min(owned.counts[itemId], count)
250
251 -- update owned count so we can't double-use something
252 owned.counts[itemId] = owned.counts[itemId] - used;
253
254 -- reduce the requirement, removing entirely if we have it completely covered
255 list[itemId] = list[itemId] - used;
256 if list[itemId] == 0 then
257 list[itemId] = nil
258 end
259 end
260 end
261
218 function Amr:RefreshShoppingUi() 262 function Amr:RefreshShoppingUi()
219 263
220 _chk1:SetVisible(false) 264 local posToCheck = { _chk1, _chk2, _chk3, _chk4 }
221 _chk2:SetVisible(false) 265 local chk
222 _chk3:SetVisible(false) 266
223 _chk4:SetVisible(false) 267 -- reset spec checkboxes
224 268 for specPos = 1,4 do
225 _chk1:SetChecked(false) 269 chk = posToCheck[specPos]
226 _chk2:SetChecked(false) 270 chk:SetVisible(false)
227 _chk3:SetChecked(false) 271 chk:SetChecked(false)
228 _chk4:SetChecked(false) 272 end
229 273
230 -- clear out any previous data 274 -- clear out any previous data
231 _panelContent:ReleaseChildren() 275 _panelContent:ReleaseChildren()
232 276
233 local data = Amr.db.global.Shopping[_selectedPlayer] 277 local data = Amr.db.global.Shopping[_selectedPlayer]
234 if not data then 278 if not data then
239 lbl:SetText(L.ShopEmpty) 283 lbl:SetText(L.ShopEmpty)
240 lbl:SetJustifyH("CENTER") 284 lbl:SetJustifyH("CENTER")
241 lbl:SetPoint("TOP", _panelContent.content, "TOP", 0, -30) 285 lbl:SetPoint("TOP", _panelContent.content, "TOP", 0, -30)
242 _panelContent:AddChild(lbl) 286 _panelContent:AddChild(lbl)
243 else 287 else
244 -- set labels on checkboxes 288 local allStuff = { gems = {}, enchants = {}, materials = {} }
245 if data.specs[1] and data.specs[1] ~= 0 then 289 local hasStuff = false
246 _chk1:SetText(L.SpecsShort[data.specs[1]]) 290 local visited = {}
247 _chk1:SetVisible(true) 291
248 _chk1:SetChecked(_specs[1]) 292 for specPos = 1,4 do
249 end 293 -- set labels on checkboxes
250 294 if data.specs[specPos] and data.specs[specPos] ~= 0 then
251 if data.specs[2] and data.specs[2] ~= 0 then 295 chk = posToCheck[specPos]
252 _chk2:SetText(L.SpecsShort[data.specs[2]]) 296 chk:SetText(L.SpecsShort[data.specs[specPos]])
253 _chk2:SetVisible(true) 297 chk:SetVisible(true)
254 _chk2:SetChecked(_specs[2]) 298 chk:SetChecked(_specs[specPos])
255 end 299
256 300 -- gather up all stuff for checked specs
257 if data.specs[3] and data.specs[3] ~= 0 then 301 if _specs[specPos] then
258 _chk3:SetText(L.SpecsShort[data.specs[3]]) 302 hasStuff = true
259 _chk3:SetVisible(true) 303
260 _chk3:SetChecked(_specs[3]) 304 for inventoryId, stuff in pairs(data.stuff[specPos]) do
261 end 305 if not visited[inventoryId] then
262 306 if stuff.gems then
263 if data.specs[4] and data.spes[4] ~= 0 then 307 for itemId, count in pairs(stuff.gems) do
264 _chk4:SetText(L.SpecsShort[data.specs[4]]) 308 incrementTableItem(allStuff.gems, itemId, count)
265 _chk4:SetVisible(true) 309 end
266 _chk4:SetChecked(_specs[4]) 310 end
267 end 311
268 312 if stuff.enchants then
269 local spec = 0 313 for itemId, count in pairs(stuff.enchants) do
270 if not _specs[1] and not _specs[2] and not _specs[3] and not _specs[4] then 314 incrementTableItem(allStuff.enchants, itemId, count)
271 -- all unchecked, show nothing 315 end
272 else 316 end
273 -- both is 0, otherwise the one that is selected 317
274 if not _specs[1] or not _specs[2] then 318 if stuff.materials then
275 spec = _specs[1] and 1 or 2 319 for itemId, count in pairs(stuff.materials) do
320 incrementTableItem(allStuff.materials, itemId, count)
321 end
322 end
323
324 -- make sure not to count the same physical item twice
325 if inventoryId ~= -1 then
326 visited[inventoryId] = true
327 end
328 end
329 end
330 end
331
276 end 332 end
333
334 end
335
336 if hasStuff then
337 -- remove what we already own
338 local owned = { counts = {}, loaded = {} }
339 removeOwned(allStuff.gems, owned)
340 removeOwned(allStuff.enchants, owned)
341 removeOwned(allStuff.materials, owned)
277 342
278 _panelContent:SetLayout("Fill") 343 _panelContent:SetLayout("Fill")
279 344
280 local scroll = AceGUI:Create("AmrUiScrollFrame") 345 local scroll = AceGUI:Create("AmrUiScrollFrame")
281 scroll:SetLayout("List") 346 scroll:SetLayout("List")
282 _panelContent:AddChild(scroll) 347 _panelContent:AddChild(scroll)
283 348
284 renderShopSection(data.gems[spec], scroll, L.ShopHeaderGems) 349 renderShopSection(allStuff.gems, scroll, L.ShopHeaderGems)
285 renderShopSection(data.enchants[spec], scroll, L.ShopHeaderEnchants) 350 renderShopSection(allStuff.enchants, scroll, L.ShopHeaderEnchants)
286 renderShopSection(data.materials[spec], scroll, L.ShopHeaderMaterials) 351 renderShopSection(allStuff.materials, scroll, L.ShopHeaderMaterials)
287 end 352 end
288 end 353 end
289 354
290 end 355 end
291 356
292 -- compare gear to everything the player owns, and return the minimum gems/enchants/materials needed to optimize 357 -- compare gear to everything the player owns, and return the minimum gems/enchants/materials needed to optimize, grouped by inventory ID so that we can combine multiple specs without double-counting
293 local function getShoppingData(player, gear, spec) 358 local function getShoppingData(player, gear, spec)
294 359
295 local ret = { 360 local ret = {}
296 gems = {},
297 enchants = {},
298 materials = {}
299 }
300 361
301 -- used to prevent considering the same item twice 362 -- used to prevent considering the same item twice
302 local usedItems = {} 363 local usedItems = {}
303 364
304 for slotId, optimalItem in pairs(gear) do 365 for slotId, optimalItem in pairs(gear) do
305 local matchItemLink, matchItem = Amr:FindMatchingItem(optimalItem, player, usedItems) 366 local matchItemLink, matchItem = Amr:FindMatchingItem(optimalItem, player, usedItems)
306 local itemInfo = Amr.db.char.ExtraItemData[spec][optimalItem.id] 367 local itemInfo = Amr.db.char.ExtraItemData[spec][optimalItem.id]
368 local inventoryId = optimalItem.inventoryId or -1
307 369
308 -- find gem/enchant differences on the best-matching item 370 -- find gem/enchant differences on the best-matching item
309 371
310 -- gems 372 -- gems, but skip artifact relics (will have relicBonusIds set)
311 if itemInfo and itemInfo.socketColors then 373 if not optimalItem.relicBonusIds and itemInfo and itemInfo.socketColors then
312 for i = 1, #itemInfo.socketColors do 374 for i = 1, #itemInfo.socketColors do
313 local g = optimalItem.gemIds[i] 375 local g = optimalItem.gemIds[i]
314 local isGemEquipped = g ~= 0 and matchItem and matchItem.gemIds and matchItem.gemIds[i] == g 376 local isGemEquipped = g ~= 0 and matchItem and matchItem.gemIds and matchItem.gemIds[i] == g
315 377
316 if not isGemEquipped then 378 if not isGemEquipped then
317 ret.gems[g] = ret.gems[g] and ret.gems[g] + 1 or 1 379 if not ret[inventoryId] then
380 ret[inventoryId] = { gems = {}, enchants = {}, materials = {} }
381 end
382 incrementTableItem(ret[inventoryId].gems, g, 1)
318 end 383 end
319 end 384 end
320 end 385 end
321 386
322 -- enchant 387 -- enchant
323 if optimalItem.enchantId and optimalItem.enchantId ~= 0 then 388 if optimalItem.enchantId and optimalItem.enchantId ~= 0 then
324 local e = optimalItem.enchantId 389 local e = optimalItem.enchantId
325 local isEnchantEquipped = matchItem and matchItem.enchantId and matchItem.enchantId == e 390 local isEnchantEquipped = matchItem and matchItem.enchantId and matchItem.enchantId == e
326 391
327 if not isEnchantEquipped then 392 if not isEnchantEquipped then
328 ret.enchants[e] = ret.enchants[e] and ret.enchants[e] + 1 or 1 393 -- enchant info, look in all spec extra info cache
394 local enchInfo = nil
395 for specPos = 1,4 do
396 if Amr.db.char.ExtraEnchantData[specPos] then
397 enchInfo = Amr.db.char.ExtraEnchantData[specPos][e]
398 if enchInfo then break end
399 end
400 end
401
402 if enchInfo then
403 if not ret[inventoryId] then
404 ret[inventoryId] = { gems = {}, enchants = {}, materials = {} }
405 end
406 incrementTableItem(ret[inventoryId].enchants, enchInfo.itemId, 1)
407
408 if enchInfo.materials then
409 for k, v in pairs(enchInfo.materials) do
410 incrementTableItem(ret[inventoryId].materials, k, v)
411 end
412 end
413 end
329 end 414 end
330 end 415 end
331 end
332
333 return ret
334 end
335
336 -- get the number of a specified item that the player currently owns
337 local function getOwnedCount(itemId)
338 local ret = 0
339
340 local list = Amr.db.char.BagItemsAndCounts
341 if list and list[itemId] then
342 ret = ret + list[itemId]
343 end
344
345 list = Amr.db.char.BankItemsAndCounts
346 if list and list[itemId] then
347 ret = ret + list[itemId]
348 end 416 end
349 417
350 return ret 418 return ret
351 end 419 end
352 420
353 -- look at both gear sets and find stuff that a player needs to acquire to gem/enchant their gear 421 -- look at both gear sets and find stuff that a player needs to acquire to gem/enchant their gear
354 function Amr:UpdateShoppingData(player) 422 function Amr:UpdateShoppingData(player)
355 423
356 -- TODO: re-enable shopping list when Legion comes out
357 do return end
358
359 -- 0 is combination of all specs
360 local required = { 424 local required = {
361 gems = { 425 stuff = {},
362 [0] = {},
363 [1] = {},
364 [2] = {},
365 [3] = {},
366 [4] = {}
367 },
368 enchants = {
369 [0] = {},
370 [1] = {},
371 [2] = {},
372 [3] = {},
373 [4] = {}
374 },
375 materials = {
376 [0] = {},
377 [1] = {},
378 [2] = {},
379 [3] = {},
380 [4] = {}
381 },
382 specs = player.Specs 426 specs = player.Specs
383 } 427 }
384 428
385 local enchantItemIdToId = {} 429 local enchantItemIdToId = {}
386 430
387 for spec, gear in pairs(Amr.db.char.GearSets) do 431 for spec, gear in pairs(Amr.db.char.GearSets) do
388 local obj = getShoppingData(player, gear, spec) 432 required.stuff[spec] = getShoppingData(player, gear, spec)
389 for k, v in pairs(obj.gems) do
390 local gemInfo = Amr.db.char.ExtraGemData[spec][k]
391 if gemInfo then
392 local prev = required.gems[spec][gemInfo.id]
393 required.gems[spec][gemInfo.id] = prev and prev + v or v
394
395 prev = required.gems[0][gemInfo.id]
396 required.gems[0][gemInfo.id] = prev and prev + v or v
397 end
398 end
399 for k, v in pairs(obj.enchants) do
400 local enchInfo = Amr.db.char.ExtraEnchantData[spec][k]
401 if enchInfo then
402 enchantItemIdToId[enchInfo.itemId] = k
403
404 local prev = required.enchants[spec][enchInfo.itemId]
405 required.enchants[spec][enchInfo.itemId] = prev and prev + v or v
406
407 prev = required.enchants[0][enchInfo.itemId]
408 required.enchants[0][enchInfo.itemId] = prev and prev + v or v
409 end
410 end
411 end
412
413 -- now subtract stuff the player already has, and generate a list of materials as well
414 for spec = 0, 4 do
415 local specId = spec == 0 and 1 or GetSpecializationInfo(spec)
416 if specId then
417 -- now check if the player has any of the gems or enchants in their inventory, and subtract those
418 for itemId, count in pairs(required.gems[spec]) do
419 required.gems[spec][itemId] = math.max(count - getOwnedCount(itemId), 0)
420
421 if required.gems[spec][itemId] == 0 then
422 required.gems[spec][itemId] = nil
423 end
424 end
425
426 for itemId, count in pairs(required.enchants[spec]) do
427 -- look in both spec extra info cache
428 local e = enchantItemIdToId[itemId]
429 local enchInfo = nil
430 if Amr.db.char.ExtraEnchantData[1] then
431 enchInfo = Amr.db.char.ExtraEnchantData[1][e]
432 end
433 if not enchInfo then
434 if Amr.db.char.ExtraEnchantData[2] then
435 enchInfo = Amr.db.char.ExtraEnchantData[2][e]
436 end
437 end
438
439 if enchInfo then
440 required.enchants[spec][itemId] = math.max(count - getOwnedCount(itemId), 0)
441
442 if required.enchants[spec][itemId] == 0 then
443 required.enchants[spec][itemId] = nil
444 else
445 -- count up required materials
446 if enchInfo.materials then
447 local c = required.enchants[spec][itemId]
448 for k, v in pairs(enchInfo.materials) do
449 local prev = required.materials[spec][k]
450 required.materials[spec][k] = prev and prev + (v * c) or (v * c)
451 end
452 end
453 end
454 end
455 end
456
457 -- check if player has any of the materials already
458 for itemId, count in pairs(required.materials[spec]) do
459 required.materials[spec][itemId] = math.max(count - getOwnedCount(itemId), 0)
460
461 if required.materials[spec][itemId] == 0 then
462 required.materials[spec][itemId] = nil
463 end
464 end
465 end
466 end 433 end
467 434
468 Amr.db.global.Shopping[player.Name .. "-" .. player.Realm] = required 435 Amr.db.global.Shopping[player.Name .. "-" .. player.Realm] = required
469 end 436 end
470 437
471 -- TODO: re-enable shopping list with Legion
472 --[[
473 Amr:AddEventHandler("AUCTION_HOUSE_SHOW", function() 438 Amr:AddEventHandler("AUCTION_HOUSE_SHOW", function()
474 _isAhOpen = true 439 _isAhOpen = true
475 if Amr.db.profile.options.shopAh then 440 if Amr.db.profile.options.shopAh then
476 Amr:ShowShopWindow() 441 Amr:ShowShopWindow()
477 end 442 end
481 _isAhOpen = false 446 _isAhOpen = false
482 if Amr.db.profile.options.shopAh then 447 if Amr.db.profile.options.shopAh then
483 Amr:HideShopWindow() 448 Amr:HideShopWindow()
484 end 449 end
485 end) 450 end)
486 ]]