Mercurial > wow > askmrrobot
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 ]] |