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 ]] |
