annotate Gear.lua @ 187:180cb1458674 v91

Fixed an issue with the junk list after the pre-patch.
author yellowfive
date Tue, 13 Oct 2020 17:08:49 -0700
parents a7f2ba17c39a
children 4aeedce4c995
rev   line source
yellowfive@57 1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot")
yellowfive@57 2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true)
yellowfive@57 3 local AceGUI = LibStub("AceGUI-3.0")
yellowfive@57 4
yellowfive@139 5 local _cboSetups
yellowfive@139 6 local _panelGear
yellowfive@139 7 local _activeSetupId
yellowfive@139 8
yellowfive@139 9 local function getSetupById(id)
yellowfive@139 10 if not id then
yellowfive@139 11 id = _activeSetupId
yellowfive@139 12 end
yellowfive@139 13 local setup
yellowfive@139 14 for i,s in ipairs(Amr.db.char.GearSetups) do
yellowfive@139 15 if s.Id == id then
yellowfive@139 16 setup = s
yellowfive@139 17 break
yellowfive@139 18 end
yellowfive@139 19 end
yellowfive@139 20 return setup
yellowfive@139 21 end
yellowfive@57 22
yellowfive@57 23 -- Returns a number indicating how different two items are (0 means the same, higher means more different)
yellowfive@57 24 local function countItemDifferences(item1, item2)
yellowfive@124 25 -- both nil, the same
yellowfive@124 26 if not item1 and not item2 then
yellowfive@124 27 return 0
yellowfive@124 28 end
yellowfive@124 29
yellowfive@124 30 -- one nil and other not, or different id, totally different
yellowfive@124 31 if (not item1 and item2) or (item1 and not item2) or item1.id ~= item2.id then
yellowfive@149 32 return 100000
yellowfive@124 33 end
yellowfive@124 34
yellowfive@124 35 -- different versions of same item (id + bonus ids + suffix + drop level, constitutes a different physical drop)
yellowfive@135 36 if Amr.GetItemUniqueId(item1, true, true) ~= Amr.GetItemUniqueId(item2, true, true) then
yellowfive@149 37 return 10000
yellowfive@57 38 end
yellowfive@57 39
yellowfive@81 40 -- different upgrade levels of the same item
yellowfive@57 41 if item1.upgradeId ~= item2.upgradeId then
yellowfive@149 42 return 1000
yellowfive@124 43 end
yellowfive@124 44
yellowfive@149 45 -- a change that requires reforging is considered more different than a change that does not;
yellowfive@149 46 -- it is assumed that item1 is how we want the item to be in the end, and item2 is how it currently is
yellowfive@149 47 local aztReforges = 0
yellowfive@149 48 local aztSelects = 0
yellowfive@149 49
yellowfive@149 50 if item1.id == item2.id and (item1.azerite or item2.azerite) then
yellowfive@149 51 -- azerite that needs to be reforged
yellowfive@149 52 if item2.azerite and not item1.azerite then
yellowfive@149 53 -- kind of a dumb case... but we would need to blank all azerite on item2 to match item1
yellowfive@149 54 aztReforges = #item2.azerite * 100
yellowfive@149 55 elseif item2.azerite then
yellowfive@149 56 -- count up azerite on item2 but not on item1, these would need to be reforged
yellowfive@149 57 for i = 1, #item2.azerite do
yellowfive@149 58 local missing = true
yellowfive@149 59 for j = 1, #item1.azerite do
yellowfive@149 60 if item1.azerite[j] == item2.azerite[i] then
yellowfive@149 61 missing = false
yellowfive@149 62 end
yellowfive@149 63 end
yellowfive@149 64 if missing then
yellowfive@149 65 aztReforges = aztReforges + 100
yellowfive@149 66 end
yellowfive@149 67 end
yellowfive@149 68 end
yellowfive@149 69
yellowfive@149 70 -- azerite that needs to be selected
yellowfive@124 71 if item1.azerite and not item2.azerite then
yellowfive@149 72 -- item2 is blank, so just need to choose all the right ones
yellowfive@149 73 aztSelects = #item1.azerite * 10
yellowfive@149 74 elseif item1.azerite then
yellowfive@149 75 -- count up azerite on item1 but not on item2, these would need to be selected
yellowfive@145 76 for i = 1, #item1.azerite do
yellowfive@145 77 local missing = true
yellowfive@124 78 for j = 1, #item2.azerite do
yellowfive@145 79 if item2.azerite[j] == item1.azerite[i] then
yellowfive@124 80 missing = false
yellowfive@124 81 end
yellowfive@124 82 end
yellowfive@124 83 if missing then
yellowfive@149 84 aztSelects = aztSelects + 10
yellowfive@124 85 end
yellowfive@124 86 end
yellowfive@149 87 end
yellowfive@124 88 end
yellowfive@57 89
yellowfive@57 90 -- different gems
yellowfive@57 91 local gemDiffs = 0
yellowfive@57 92 for i = 1, 3 do
yellowfive@57 93 if item1.gemIds[i] ~= item2.gemIds[i] then
yellowfive@57 94 gemDiffs = gemDiffs + 1
yellowfive@57 95 end
yellowfive@57 96 end
yellowfive@57 97
yellowfive@57 98 -- different enchants
yellowfive@57 99 local enchantDiff = 0
yellowfive@57 100 if item1.enchantId ~= item2.enchantId then
yellowfive@57 101 enchantDiff = 1
yellowfive@57 102 end
yellowfive@57 103
yellowfive@149 104 return aztReforges + aztSelects + gemDiffs + enchantDiff
yellowfive@57 105 end
yellowfive@57 106
yellowfive@57 107 -- given a table of items (keyed or indexed doesn't matter) find closest match to item, or nil if none are a match
yellowfive@124 108 local function findMatchingItemFromTable(item, list, bestItem, bestDiff, bestLoc, usedItems, tableType)
yellowfive@57 109 if not list then return nil end
yellowfive@57 110
yellowfive@73 111 local found = false
yellowfive@129 112 for k,listItem in pairs(list) do
yellowfive@57 113 if listItem then
yellowfive@57 114 local diff = countItemDifferences(item, listItem)
yellowfive@57 115 if diff < bestDiff then
yellowfive@57 116 -- each physical item can only be used once, the usedItems table has items we can't use in this search
yellowfive@57 117 local key = string.format("%s_%s", tableType, k)
yellowfive@57 118 if not usedItems[key] then
yellowfive@57 119 bestItem = listItem
yellowfive@57 120 bestDiff = diff
yellowfive@124 121 bestLoc = key
yellowfive@73 122 found = true
yellowfive@57 123 end
yellowfive@57 124 end
yellowfive@73 125 if found then break end
yellowfive@57 126 end
yellowfive@57 127 end
yellowfive@57 128
yellowfive@124 129 return bestItem, bestDiff, bestLoc
yellowfive@57 130 end
yellowfive@57 131
yellowfive@124 132 -- search the player's equipped gear, bag, and bank for an item that best matches the specified item
yellowfive@57 133 function Amr:FindMatchingItem(item, player, usedItems)
yellowfive@57 134 if not item then return nil end
yellowfive@57 135
yellowfive@57 136 local equipped = player.Equipped and player.Equipped[player.ActiveSpec] or nil
yellowfive@151 137 local bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, equipped, nil, 100000, nil, usedItems, "equip")
yellowfive@124 138 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BagItems, bestItem, bestDiff, bestLoc, usedItems, "bag")
yellowfive@124 139 if player.BankItems then
yellowfive@129 140 bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BankItems, bestItem, bestDiff, bestLoc, usedItems, "bank")
yellowfive@124 141 end
yellowfive@57 142
yellowfive@149 143 if bestDiff >= 100000 then
yellowfive@149 144 return nil, 100000
yellowfive@57 145 else
yellowfive@57 146 usedItems[bestLoc] = true
yellowfive@124 147 return bestItem, bestDiff
yellowfive@57 148 end
yellowfive@57 149 end
yellowfive@57 150
yellowfive@57 151 local function renderEmptyGear(container)
yellowfive@57 152
yellowfive@57 153 local panelBlank = AceGUI:Create("AmrUiPanel")
yellowfive@57 154 panelBlank:SetLayout("None")
yellowfive@57 155 panelBlank:SetBackgroundColor(Amr.Colors.Black, 0.4)
yellowfive@124 156 container:AddChild(panelBlank)
yellowfive@57 157 panelBlank:SetPoint("TOPLEFT", container.content, "TOPLEFT", 6, 0)
yellowfive@57 158 panelBlank:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
yellowfive@57 159
yellowfive@57 160 local lbl = AceGUI:Create("AmrUiLabel")
yellowfive@124 161 panelBlank:AddChild(lbl)
yellowfive@57 162 lbl:SetText(L.GearBlank)
yellowfive@57 163 lbl:SetWidth(700)
yellowfive@57 164 lbl:SetJustifyH("MIDDLE")
yellowfive@57 165 lbl:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextTan))
yellowfive@57 166 lbl:SetPoint("BOTTOM", panelBlank.content, "CENTER", 0, 20)
yellowfive@57 167
yellowfive@57 168 local lbl2 = AceGUI:Create("AmrUiLabel")
yellowfive@124 169 panelBlank:AddChild(lbl2)
yellowfive@57 170 lbl2:SetText(L.GearBlank2)
yellowfive@57 171 lbl2:SetWidth(700)
yellowfive@57 172 lbl2:SetJustifyH("MIDDLE")
yellowfive@57 173 lbl2:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextTan))
yellowfive@57 174 lbl2:SetPoint("TOP", lbl.frame, "CENTER", 0, -20)
yellowfive@124 175 end
yellowfive@124 176
yellowfive@124 177 -- helper to create a widget for showing a socket or azerite power
yellowfive@124 178 local function createSocketWidget(panelMods, prevWidget, prevIsSocket, isEquipped)
yellowfive@124 179
yellowfive@124 180 -- highlight for socket that doesn't match
yellowfive@124 181 local socketBorder = AceGUI:Create("AmrUiPanel")
yellowfive@124 182 panelMods:AddChild(socketBorder)
yellowfive@124 183 if not prevIsSocket then
yellowfive@124 184 socketBorder:SetPoint("LEFT", prevWidget.frame, "RIGHT", 30, 0)
yellowfive@124 185 else
yellowfive@124 186 socketBorder:SetPoint("LEFT", prevWidget.frame, "RIGHT", 2, 0)
yellowfive@124 187 end
yellowfive@124 188 socketBorder:SetLayout("None")
yellowfive@124 189 socketBorder:SetBackgroundColor(Amr.Colors.Black, isEquipped and 0 or 1)
yellowfive@124 190 socketBorder:SetWidth(26)
yellowfive@124 191 socketBorder:SetHeight(26)
yellowfive@124 192 if isEquipped then
yellowfive@124 193 socketBorder:SetAlpha(0.3)
yellowfive@124 194 end
yellowfive@124 195
yellowfive@124 196 local socketBg = AceGUI:Create("AmrUiIcon")
yellowfive@124 197 socketBorder:AddChild(socketBg)
yellowfive@124 198 socketBg:SetPoint("TOPLEFT", socketBorder.content, "TOPLEFT", 1, -1)
yellowfive@124 199 socketBg:SetLayout("None")
yellowfive@124 200 socketBg:SetBorderWidth(2)
yellowfive@124 201 socketBg:SetIconBorderColor(Amr.Colors.Green, isEquipped and 0 or 1)
yellowfive@124 202 socketBg:SetWidth(24)
yellowfive@124 203 socketBg:SetHeight(24)
yellowfive@124 204
yellowfive@124 205 local socketIcon = AceGUI:Create("AmrUiIcon")
yellowfive@124 206 socketBg:AddChild(socketIcon)
yellowfive@124 207 socketIcon:SetPoint("CENTER", socketBg.content, "CENTER")
yellowfive@124 208 socketIcon:SetBorderWidth(1)
yellowfive@124 209 socketIcon:SetIconBorderColor(Amr.Colors.White)
yellowfive@124 210 socketIcon:SetWidth(18)
yellowfive@124 211 socketIcon:SetHeight(18)
yellowfive@124 212
yellowfive@124 213 return socketBorder, socketIcon
yellowfive@57 214 end
yellowfive@57 215
yellowfive@139 216 local function renderGear(setupId, container)
yellowfive@139 217
yellowfive@139 218 -- release all children that were previously rendered, we gonna redo it now
yellowfive@139 219 container:ReleaseChildren()
yellowfive@57 220
yellowfive@57 221 local player = Amr:ExportCharacter()
yellowfive@139 222
yellowfive@139 223 local gear
yellowfive@139 224 local spec
yellowfive@139 225 local setupIndex
yellowfive@181 226 local essences
yellowfive@139 227 for i, setup in ipairs(Amr.db.char.GearSetups) do
yellowfive@139 228 if setup.Id == setupId then
yellowfive@139 229 setupIndex = i
yellowfive@139 230 gear = setup.Gear
yellowfive@139 231 spec = setup.SpecSlot
yellowfive@165 232 essences = setup.Essences
yellowfive@139 233 break
yellowfive@139 234 end
yellowfive@139 235 end
yellowfive@139 236
yellowfive@57 237 local equipped = player.Equipped[player.ActiveSpec]
yellowfive@185 238 --local equippedEssences = player.Essences[player.ActiveSpec]
yellowfive@181 239
yellowfive@57 240 if not gear then
yellowfive@57 241 -- no gear has been imported for this spec so show a message
yellowfive@57 242 renderEmptyGear(container)
yellowfive@57 243 else
yellowfive@57 244 local panelGear = AceGUI:Create("AmrUiPanel")
yellowfive@57 245 panelGear:SetLayout("None")
yellowfive@57 246 panelGear:SetBackgroundColor(Amr.Colors.Black, 0.3)
yellowfive@124 247 container:AddChild(panelGear)
yellowfive@57 248 panelGear:SetPoint("TOPLEFT", container.content, "TOPLEFT", 6, 0)
yellowfive@57 249 panelGear:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT", -300, 0)
yellowfive@57 250
yellowfive@57 251 local panelMods = AceGUI:Create("AmrUiPanel")
yellowfive@57 252 panelMods:SetLayout("None")
yellowfive@124 253 panelMods:SetBackgroundColor(Amr.Colors.Black, 0.3)
yellowfive@124 254 container:AddChild(panelMods)
yellowfive@57 255 panelMods:SetPoint("TOPLEFT", panelGear.frame, "TOPRIGHT", 15, 0)
yellowfive@57 256 panelMods:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
yellowfive@57 257
yellowfive@57 258 -- spec icon
yellowfive@57 259 local icon = AceGUI:Create("AmrUiIcon")
yellowfive@57 260 icon:SetIconBorderColor(Amr.Colors.Classes[player.Class])
yellowfive@57 261 icon:SetWidth(48)
yellowfive@57 262 icon:SetHeight(48)
yellowfive@57 263
yellowfive@57 264 local iconSpec
yellowfive@81 265 if player.SubSpecs and player.SubSpecs[spec] then
yellowfive@57 266 iconSpec = player.SubSpecs[spec]
yellowfive@57 267 else
yellowfive@57 268 iconSpec = player.Specs[spec]
yellowfive@57 269 end
yellowfive@57 270
yellowfive@57 271 icon:SetIcon("Interface\\Icons\\" .. Amr.SpecIcons[iconSpec])
yellowfive@124 272 panelGear:AddChild(icon)
yellowfive@57 273 icon:SetPoint("TOPLEFT", panelGear.content, "TOPLEFT", 10, -10)
yellowfive@57 274
yellowfive@57 275 local btnEquip = AceGUI:Create("AmrUiButton")
yellowfive@81 276 btnEquip:SetText(L.GearButtonEquip(L.SpecsShort[player.Specs[spec]]))
yellowfive@57 277 btnEquip:SetBackgroundColor(Amr.Colors.Green)
yellowfive@57 278 btnEquip:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
yellowfive@57 279 btnEquip:SetWidth(300)
yellowfive@57 280 btnEquip:SetHeight(26)
yellowfive@57 281 btnEquip:SetCallback("OnClick", function(widget)
yellowfive@139 282 Amr:EquipGearSet(setupIndex)
yellowfive@57 283 end)
yellowfive@57 284 panelGear:AddChild(btnEquip)
yellowfive@124 285 btnEquip:SetPoint("LEFT", icon.frame, "RIGHT", 40, 0)
yellowfive@124 286 btnEquip:SetPoint("RIGHT", panelGear.content, "RIGHT", -40, 0)
yellowfive@57 287
yellowfive@57 288 -- each physical item can only be used once, this tracks ones we have already used
yellowfive@57 289 local usedItems = {}
yellowfive@57 290
yellowfive@57 291 -- gear list
yellowfive@57 292 local prevElem = icon
yellowfive@57 293 for slotNum = 1, #Amr.SlotIds do
yellowfive@57 294 local slotId = Amr.SlotIds[slotNum]
yellowfive@57 295
yellowfive@124 296 local equippedItem = equipped and equipped[slotId] or nil
yellowfive@133 297 --local equippedItemLink = equipped and equipped.link or nil
yellowfive@57 298 local optimalItem = gear[slotId]
yellowfive@57 299 local optimalItemLink = Amr.CreateItemLink(optimalItem)
yellowfive@57 300
yellowfive@57 301 -- see if item is currently equipped, is false if don't have any item for that slot (e.g. OH for a 2-hander)
yellowfive@57 302 local isEquipped = false
yellowfive@135 303 if equippedItem and optimalItem and Amr.GetItemUniqueId(equippedItem, false, true) == Amr.GetItemUniqueId(optimalItem, false, true) then
yellowfive@145 304
yellowfive@145 305 if slotId == 1 or slotId == 3 or slotId == 5 then
yellowfive@145 306 -- show the item as not equipped if azerite doesn't match... might mean they have to switch to another version of same item
yellowfive@149 307 local aztDiff = countItemDifferences(optimalItem, equippedItem)
yellowfive@153 308 if aztDiff < 10 then
yellowfive@145 309 isEquipped = true
yellowfive@145 310 end
yellowfive@145 311 else
yellowfive@145 312 isEquipped = true
yellowfive@145 313 end
yellowfive@57 314 end
yellowfive@124 315
yellowfive@185 316 --local isAzerite = optimalItem and C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItemByID(optimalItem.id)
yellowfive@185 317 --local isEssence = essences and optimalItem and optimalItem.id == 158075
yellowfive@185 318 local isAzerite = false
yellowfive@185 319 local isEssence = false
yellowfive@57 320
yellowfive@57 321 -- find the item in the player's inventory that best matches what the optimization wants to use
yellowfive@124 322 local matchItem = Amr:FindMatchingItem(optimalItem, player, usedItems)
yellowfive@57 323
yellowfive@57 324 -- slot label
yellowfive@57 325 local lbl = AceGUI:Create("AmrUiLabel")
yellowfive@124 326 panelGear:AddChild(lbl)
yellowfive@124 327 lbl:SetPoint("TOPLEFT", prevElem.frame, "BOTTOMLEFT", 0, -12)
yellowfive@57 328 lbl:SetText(Amr.SlotDisplayText[slotId])
yellowfive@57 329 lbl:SetWidth(85)
yellowfive@57 330 lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
yellowfive@57 331 prevElem = lbl
yellowfive@57 332
yellowfive@57 333 -- ilvl label
yellowfive@57 334 local lblIlvl = AceGUI:Create("AmrUiLabel")
yellowfive@124 335 panelGear:AddChild(lblIlvl)
yellowfive@124 336 lblIlvl:SetPoint("TOPLEFT", lbl.frame, "TOPRIGHT", 0, 0)
yellowfive@57 337 lblIlvl:SetWidth(45)
yellowfive@57 338 lblIlvl:SetFont(Amr.CreateFont("Italic", 14, Amr.Colors.TextTan))
yellowfive@57 339
yellowfive@57 340 -- equipped label
yellowfive@57 341 local lblEquipped = AceGUI:Create("AmrUiLabel")
yellowfive@124 342 panelGear:AddChild(lblEquipped)
yellowfive@124 343 lblEquipped:SetPoint("TOPLEFT", lblIlvl.frame, "TOPRIGHT", 0, 0)
yellowfive@57 344 lblEquipped:SetWidth(20)
yellowfive@57 345 lblEquipped:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
yellowfive@57 346 lblEquipped:SetText(isEquipped and "E" or "")
yellowfive@57 347
yellowfive@57 348 -- item name/link label
yellowfive@57 349 local lblItem = AceGUI:Create("AmrUiLabel")
yellowfive@124 350 panelGear:AddChild(lblItem)
yellowfive@124 351 lblItem:SetPoint("TOPLEFT", lblEquipped.frame, "TOPRIGHT", 0, 0)
yellowfive@57 352 lblItem:SetWordWrap(false)
yellowfive@57 353 lblItem:SetWidth(345)
yellowfive@57 354 lblItem:SetFont(Amr.CreateFont(isEquipped and "Regular" or "Bold", isEquipped and 14 or 15, Amr.Colors.White))
yellowfive@57 355
yellowfive@133 356 -- fill the name/ilvl labels, which may require asynchronous loading of item information
yellowfive@57 357 if optimalItemLink then
yellowfive@133 358 local gameItem = Item:CreateFromItemLink(optimalItemLink)
yellowfive@133 359 if gameItem then
yellowfive@133 360 local q = gameItem:GetItemQuality()
yellowfive@133 361 if q == 6 then
yellowfive@133 362 -- for artifacts, we consider it equipped if the item id alone matches
yellowfive@133 363 if equippedItem and equippedItem.id == optimalItem.id then
yellowfive@133 364 isEquipped = true
yellowfive@133 365 end
yellowfive@133 366 lblEquipped:SetText(isEquipped and "E" or "")
yellowfive@133 367 end
yellowfive@124 368
yellowfive@137 369 lblItem:SetFont(Amr.CreateFont(isEquipped and "Regular" or "Bold", isEquipped and 14 or 15, Amr.Colors.Qualities[q] or Amr.Colors.White))
yellowfive@133 370 lblItem:SetText(gameItem:GetItemName())
yellowfive@133 371 lblIlvl:SetText(gameItem:GetCurrentItemLevel())
yellowfive@133 372 Amr:SetItemTooltip(lblItem, gameItem:GetItemLink(), "ANCHOR_TOPRIGHT")
yellowfive@133 373 end
yellowfive@57 374 end
yellowfive@57 375
yellowfive@57 376 -- modifications
yellowfive@57 377 if optimalItem then
yellowfive@57 378
yellowfive@165 379 -- gems or azerite powers or essences
yellowfive@124 380 local prevSocket = nil
yellowfive@124 381
yellowfive@124 382 if isAzerite then
yellowfive@124 383 local azt = optimalItem.azerite or {}
yellowfive@124 384 for i,spellId in ipairs(azt) do
yellowfive@124 385 if spellId and spellId ~= 0 then
yellowfive@135 386 local equippedAzt = matchItem and matchItem.azerite or {}
yellowfive@124 387 local isPowerActive = Amr.Contains(equippedAzt, spellId)
yellowfive@124 388
yellowfive@124 389 local socketBorder, socketIcon = createSocketWidget(panelMods, prevSocket or lblItem, prevSocket, isPowerActive)
yellowfive@124 390
yellowfive@124 391 -- set icon and tooltip
yellowfive@133 392 local _, _, spellIcon = GetSpellInfo(spellId)
yellowfive@124 393 socketIcon:SetIcon(spellIcon)
yellowfive@124 394 Amr:SetSpellTooltip(socketIcon, spellId, "ANCHOR_TOPRIGHT")
yellowfive@124 395
yellowfive@124 396 prevSocket = socketBorder
yellowfive@124 397 end
yellowfive@124 398 end
yellowfive@165 399 elseif isEssence then
yellowfive@181 400 for i = 1, 4 do
yellowfive@181 401 if essences and #essences >= i then
yellowfive@181 402 local essence = essences[i]
yellowfive@181 403 local equippedEssence = equippedEssences and #equippedEssences >= i and equippedEssences[i] or nil
yellowfive@181 404 if essence then
yellowfive@181 405 local essenceInfo = C_AzeriteEssence.GetEssenceInfo(essence[2])
yellowfive@181 406 if essenceInfo then
yellowfive@181 407 local isEssenceActive = equippedEssence and equippedEssence[2] == essence[2]
yellowfive@181 408
yellowfive@181 409 local socketBorder, socketIcon = createSocketWidget(panelMods, prevSocket or lblItem, prevSocket, isEssenceActive)
yellowfive@181 410
yellowfive@181 411 -- set icon and tooltip
yellowfive@181 412 socketIcon:SetIcon(essenceInfo.icon)
yellowfive@181 413 Amr:SetEssenceTooltip(socketIcon, string.format("azessence:%d:%d", essence[2], essence[3]) , "ANCHOR_TOPRIGHT")
yellowfive@181 414
yellowfive@181 415 --[[
yellowfive@181 416 if essence[1] and essence[1] > 4 then
yellowfive@181 417 Amr:SetSpellTooltip(socketIcon, essence[1], "ANCHOR_TOPRIGHT")
yellowfive@181 418 end]]
yellowfive@181 419
yellowfive@181 420 prevSocket = socketBorder
yellowfive@181 421 end
yellowfive@181 422 end
yellowfive@181 423 end
yellowfive@181 424 end
yellowfive@124 425 else
yellowfive@124 426 for i = 1, #optimalItem.gemIds do
yellowfive@124 427 -- we rely on the fact that the gear sets coming back from the site will almost always have all sockets filled,
yellowfive@124 428 -- because it's a pain to get the actual number of sockets on an item from within the game
yellowfive@57 429 local g = optimalItem.gemIds[i]
yellowfive@124 430 if g == 0 then break end
yellowfive@124 431
yellowfive@124 432 local isGemEquipped = matchItem and matchItem.gemIds and matchItem.gemIds[i] == g
yellowfive@57 433
yellowfive@124 434 local socketBorder, socketIcon = createSocketWidget(panelMods, prevSocket or lblItem, prevSocket, isGemEquipped)
yellowfive@57 435
yellowfive@57 436 -- get icon for optimized gem
yellowfive@133 437 local gameItem = Item:CreateFromItemID(g)
yellowfive@133 438 if gameItem then
yellowfive@133 439 socketIcon:SetIcon(gameItem:GetItemIcon())
yellowfive@133 440 Amr:SetItemTooltip(socketIcon, gameItem:GetItemLink(), "ANCHOR_TOPRIGHT")
yellowfive@133 441 end
yellowfive@89 442
yellowfive@89 443 prevSocket = socketBorder
yellowfive@57 444 end
yellowfive@57 445 end
yellowfive@124 446
yellowfive@57 447 -- enchant
yellowfive@57 448 if optimalItem.enchantId and optimalItem.enchantId ~= 0 then
yellowfive@57 449 local isEnchantEquipped = matchItem and matchItem.enchantId and matchItem.enchantId == optimalItem.enchantId
yellowfive@135 450
yellowfive@57 451 local lblEnchant = AceGUI:Create("AmrUiLabel")
yellowfive@124 452 panelMods:AddChild(lblEnchant)
yellowfive@124 453 lblEnchant:SetPoint("TOPLEFT", lblItem.frame, "TOPRIGHT", 130, 0)
yellowfive@57 454 lblEnchant:SetWordWrap(false)
yellowfive@57 455 lblEnchant:SetWidth(170)
yellowfive@57 456 lblEnchant:SetFont(Amr.CreateFont(isEnchantEquipped and "Regular" or "Bold", 14, isEnchantEquipped and Amr.Colors.TextGray or Amr.Colors.White))
yellowfive@57 457
yellowfive@124 458 local enchInfo = Amr.db.char.ExtraEnchantData[optimalItem.enchantId]
yellowfive@57 459 if enchInfo then
yellowfive@57 460 lblEnchant:SetText(enchInfo.text)
yellowfive@57 461
yellowfive@133 462 local gameItem = Item:CreateFromItemID(enchInfo.itemId)
yellowfive@133 463 if gameItem then
yellowfive@133 464 Amr:SetItemTooltip(lblEnchant, gameItem:GetItemLink(), "ANCHOR_TOPRIGHT")
yellowfive@133 465 end
yellowfive@57 466 end
yellowfive@124 467
yellowfive@57 468 end
yellowfive@57 469 end
yellowfive@57 470
yellowfive@57 471 prevElem = lbl
yellowfive@57 472 end
yellowfive@57 473 end
yellowfive@57 474 end
yellowfive@57 475
yellowfive@139 476 local function onSetupChange(widget, eventName, value)
yellowfive@139 477 _activeSetupId = value
yellowfive@139 478 renderGear(_activeSetupId, _panelGear)
yellowfive@57 479 end
yellowfive@57 480
yellowfive@57 481 local function onImportClick(widget)
yellowfive@57 482 Amr:ShowImportWindow()
yellowfive@57 483 end
yellowfive@57 484
yellowfive@139 485 function Amr:PickFirstSetupForSpec()
yellowfive@139 486 local specSlot = GetSpecialization()
yellowfive@139 487 for i, setup in ipairs(Amr.db.char.GearSetups) do
yellowfive@139 488 if setup.SpecSlot == specSlot then
yellowfive@139 489 _activeSetupId = setup.Id
yellowfive@139 490 break
yellowfive@139 491 end
yellowfive@139 492 end
yellowfive@139 493 end
yellowfive@139 494
yellowfive@139 495 function Amr:GetActiveSetupId()
yellowfive@139 496 return _activeSetupId
yellowfive@139 497 end
yellowfive@139 498
yellowfive@139 499 function Amr:SetActiveSetupId(setupId)
yellowfive@139 500 _activeSetupId = setupId
yellowfive@139 501 end
yellowfive@139 502
yellowfive@139 503 function Amr:GetActiveSetupLabel()
yellowfive@139 504 if not _activeSetupId then
yellowfive@139 505 return nil
yellowfive@139 506 end
yellowfive@139 507 local setup = getSetupById(_activeSetupId)
yellowfive@139 508 if not setup then
yellowfive@139 509 return nil
yellowfive@139 510 else
yellowfive@139 511 return setup.Label
yellowfive@139 512 end
yellowfive@139 513 end
yellowfive@139 514
yellowfive@57 515 -- renders the main UI for the Gear tab
yellowfive@57 516 function Amr:RenderTabGear(container)
yellowfive@57 517
yellowfive@57 518 local btnImport = AceGUI:Create("AmrUiButton")
yellowfive@57 519 btnImport:SetText(L.GearButtonImportText)
yellowfive@57 520 btnImport:SetBackgroundColor(Amr.Colors.Orange)
yellowfive@57 521 btnImport:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White))
yellowfive@57 522 btnImport:SetWidth(120)
yellowfive@57 523 btnImport:SetHeight(26)
yellowfive@57 524 btnImport:SetCallback("OnClick", onImportClick)
yellowfive@57 525 container:AddChild(btnImport)
yellowfive@124 526 btnImport:SetPoint("TOPLEFT", container.content, "TOPLEFT", 0, -81)
yellowfive@57 527
yellowfive@57 528 local lbl = AceGUI:Create("AmrUiLabel")
yellowfive@124 529 container:AddChild(lbl)
yellowfive@57 530 lbl:SetText(L.GearImportNote)
yellowfive@57 531 lbl:SetWidth(100)
yellowfive@57 532 lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.TextTan))
yellowfive@57 533 lbl:SetJustifyH("MIDDLE")
yellowfive@57 534 lbl:SetPoint("TOP", btnImport.frame, "BOTTOM", 0, -5)
yellowfive@57 535
yellowfive@57 536 local lbl2 = AceGUI:Create("AmrUiLabel")
yellowfive@124 537 container:AddChild(lbl2)
yellowfive@57 538 lbl2:SetText(L.GearTipTitle)
yellowfive@57 539 lbl2:SetWidth(140)
yellowfive@57 540 lbl2:SetFont(Amr.CreateFont("Italic", 20, Amr.Colors.Text))
yellowfive@57 541 lbl2:SetJustifyH("MIDDLE")
yellowfive@57 542 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -50)
yellowfive@57 543
yellowfive@57 544 lbl = AceGUI:Create("AmrUiLabel")
yellowfive@124 545 container:AddChild(lbl)
yellowfive@57 546 lbl:SetText(L.GearTipText)
yellowfive@57 547 lbl:SetWidth(140)
yellowfive@57 548 lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text))
yellowfive@57 549 lbl:SetJustifyH("MIDDLE")
yellowfive@57 550 lbl:SetPoint("TOP", lbl2.frame, "BOTTOM", 0, -5)
yellowfive@57 551
yellowfive@57 552 lbl2 = AceGUI:Create("AmrUiLabel")
yellowfive@124 553 container:AddChild(lbl2)
yellowfive@57 554 lbl2:SetText(L.GearTipCommands)
yellowfive@57 555 lbl2:SetWidth(130)
yellowfive@57 556 lbl2:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text))
yellowfive@57 557 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 10, -5)
yellowfive@57 558
yellowfive@139 559 _cboSetups = AceGUI:Create("AmrUiDropDown")
yellowfive@139 560 _cboSetups:SetWidth(300)
yellowfive@139 561 container:AddChild(_cboSetups)
yellowfive@139 562 _cboSetups:SetPoint("TOPLEFT", container.content, "TOPLEFT", 150, -27.5)
yellowfive@81 563
yellowfive@139 564 _panelGear = AceGUI:Create("AmrUiPanel")
yellowfive@139 565 _panelGear:SetLayout("None")
yellowfive@139 566 _panelGear:SetBackgroundColor(Amr.Colors.Bg)
yellowfive@139 567 container:AddChild(_panelGear)
yellowfive@139 568 _panelGear:SetPoint("TOPLEFT", container.content, "TOPLEFT", 144, -58)
yellowfive@139 569 _panelGear:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
yellowfive@57 570
yellowfive@61 571 local btnShop = AceGUI:Create("AmrUiButton")
yellowfive@161 572 container:AddChild(btnShop)
yellowfive@61 573 btnShop:SetText(L.GearButtonShop)
yellowfive@61 574 btnShop:SetBackgroundColor(Amr.Colors.Blue)
yellowfive@61 575 btnShop:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
yellowfive@161 576 btnShop:SetWidth(200)
yellowfive@61 577 btnShop:SetHeight(26)
yellowfive@61 578 btnShop:SetCallback("OnClick", function(widget) Amr:ShowShopWindow() end)
yellowfive@161 579 btnShop:SetPoint("TOPRIGHT", container.content, "TOPRIGHT", -42, -25)
yellowfive@161 580
yellowfive@161 581 local btnJunk = AceGUI:Create("AmrUiButton")
yellowfive@161 582 container:AddChild(btnJunk)
yellowfive@161 583 btnJunk:SetText(L.GearButtonJunk)
yellowfive@161 584 btnJunk:SetBackgroundColor(Amr.Colors.Blue)
yellowfive@161 585 btnJunk:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
yellowfive@161 586 btnJunk:SetWidth(200)
yellowfive@161 587 btnJunk:SetHeight(26)
yellowfive@161 588 btnJunk:SetCallback("OnClick", function(widget) Amr:ShowJunkWindow() end)
yellowfive@161 589 btnJunk:SetPoint("CENTER", btnShop.frame, "CENTER", 0, 36)
yellowfive@139 590
yellowfive@139 591 -- pick a default tab based on player's current spec if none is already specified
yellowfive@139 592 if not _activeSetupId then
yellowfive@139 593 Amr:PickFirstSetupForSpec()
yellowfive@57 594 end
yellowfive@139 595
yellowfive@139 596 Amr:RefreshGearDisplay()
yellowfive@139 597
yellowfive@139 598 -- set event on dropdown after UI has been initially rendered
yellowfive@139 599 _cboSetups:SetCallback("OnChange", onSetupChange)
yellowfive@57 600 end
yellowfive@57 601
yellowfive@57 602 function Amr:ReleaseTabGear()
yellowfive@139 603 _cboSetups = nil
yellowfive@139 604 _panelGear = nil
yellowfive@57 605 end
yellowfive@57 606
yellowfive@57 607 -- refresh display of the current gear tab
yellowfive@139 608 function Amr:RefreshGearDisplay()
yellowfive@139 609
yellowfive@139 610 if not _panelGear then
yellowfive@139 611 return
yellowfive@139 612 end
yellowfive@139 613
yellowfive@139 614 -- fill the gear setup picker
yellowfive@139 615 local setupList = {}
yellowfive@139 616 for i, setup in ipairs(Amr.db.char.GearSetups) do
yellowfive@139 617 table.insert(setupList, { text = setup.Label, value = setup.Id })
yellowfive@139 618 end
yellowfive@139 619 _cboSetups:SetItems(setupList)
yellowfive@139 620
yellowfive@139 621 -- set selected value
yellowfive@139 622 local prev = _activeSetupId
yellowfive@139 623 _cboSetups:SelectItem(_activeSetupId)
yellowfive@139 624
yellowfive@139 625 if prev == _activeSetupId then
yellowfive@139 626 -- selecting will trigger the change event if it changed; if it didn't change, do a render now
yellowfive@139 627 renderGear(_activeSetupId, _panelGear)
yellowfive@139 628 end
yellowfive@57 629 end
yellowfive@57 630
yellowfive@57 631
yellowfive@57 632 ------------------------------------------------------------------------------------------------
yellowfive@57 633 -- Gear Set Management
yellowfive@57 634 ------------------------------------------------------------------------------------------------
yellowfive@57 635 local _waitingForSpec = 0
yellowfive@124 636 local _pendingGearOps = nil
yellowfive@124 637 local _currentGearOp = nil
yellowfive@124 638 local _itemLockAction = nil
yellowfive@124 639 local _gearOpPasses = 0
yellowfive@124 640 local _gearOpWaiting = nil
yellowfive@57 641
yellowfive@124 642 local beginEquipGearSet, processCurrentGearOp, nextGearOp
yellowfive@89 643
yellowfive@57 644 -- find the first empty slot in the player's backpack+bags
yellowfive@161 645 local function findFirstEmptyBagSlot(usedBagSlots)
yellowfive@57 646
yellowfive@57 647 local bagIds = {}
yellowfive@57 648 table.insert(bagIds, BACKPACK_CONTAINER)
yellowfive@57 649 for bagId = 1, NUM_BAG_SLOTS do
yellowfive@57 650 table.insert(bagIds, bagId)
yellowfive@57 651 end
yellowfive@57 652
yellowfive@57 653 for i, bagId in ipairs(bagIds) do
yellowfive@57 654 local numSlots = GetContainerNumSlots(bagId)
yellowfive@57 655 for slotId = 1, numSlots do
yellowfive@161 656 if not usedBagSlots or not usedBagSlots[bagId] or not usedBagSlots[bagId][slotId] then
yellowfive@161 657 local _, _, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
yellowfive@161 658 if not itemLink then
yellowfive@161 659 -- this prevents repeated calls to this from returning the same bag slot if desired
yellowfive@161 660 if usedBagSlots then
yellowfive@161 661 if not usedBagSlots[bagId] then
yellowfive@161 662 usedBagSlots[bagId] = {}
yellowfive@161 663 end
yellowfive@161 664 usedBagSlots[bagId][slotId] = true
yellowfive@161 665 end
yellowfive@161 666
yellowfive@161 667 return bagId, slotId
yellowfive@161 668 end
yellowfive@57 669 end
yellowfive@57 670 end
yellowfive@57 671 end
yellowfive@57 672
yellowfive@57 673 return nil, nil
yellowfive@57 674 end
yellowfive@57 675
yellowfive@161 676
yellowfive@161 677
yellowfive@124 678 -- scan a bag for the best matching item
yellowfive@124 679 local function scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
yellowfive@124 680 local numSlots = GetContainerNumSlots(bagId)
yellowfive@149 681 local loc = ItemLocation.CreateEmpty()
yellowfive@124 682 for slotId = 1, numSlots do
yellowfive@124 683 local _, _, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
yellowfive@124 684 -- we skip any stackable item, as far as we know, there is no equippable gear that can be stacked
yellowfive@124 685 if itemLink then
yellowfive@124 686 local bagItem = Amr.ParseItemLink(itemLink)
yellowfive@124 687 if bagItem ~= nil then
yellowfive@149 688 -- see if this is an azerite item and read azerite power ids
yellowfive@185 689 --[[loc:SetBagAndSlot(bagId, slotId)
yellowfive@149 690 if C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItem(loc) then
yellowfive@149 691 local powers = Amr.ReadAzeritePowers(loc)
yellowfive@149 692 if powers then
yellowfive@149 693 bagItem.azerite = powers
yellowfive@149 694 end
yellowfive@185 695 end]]
yellowfive@149 696
yellowfive@124 697 local diff = countItemDifferences(item, bagItem)
yellowfive@124 698 if diff < bestDiff then
yellowfive@124 699 bestItem = { bag = bagId, slot = slotId }
yellowfive@124 700 bestDiff = diff
yellowfive@124 701 bestLink = itemLink
yellowfive@124 702 end
yellowfive@124 703 end
yellowfive@124 704 end
yellowfive@57 705 end
yellowfive@124 706 return bestItem, bestDiff, bestLink
yellowfive@57 707 end
yellowfive@57 708
yellowfive@124 709 -- find the item in the player's inventory that best matches the current gear op item, favoring stuff already equipped, then in bags, then in bank
yellowfive@124 710 local function findCurrentGearOpItem()
yellowfive@124 711
yellowfive@124 712 local item = _currentGearOp.items[_currentGearOp.nextSlot]
yellowfive@124 713
yellowfive@57 714 local bestItem = nil
yellowfive@57 715 local bestLink = nil
yellowfive@124 716 local bestDiff = 10000
yellowfive@57 717
yellowfive@73 718 -- inventory
yellowfive@73 719 bestItem, bestDiff, bestLink = scanBagForItem(item, BACKPACK_CONTAINER, bestItem, bestDiff, bestLink)
yellowfive@73 720 for bagId = 1, NUM_BAG_SLOTS do
yellowfive@73 721 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
yellowfive@73 722 end
yellowfive@73 723
yellowfive@129 724 -- with new approach, the item to use should never be equipped, should be in bags at this point
yellowfive@129 725 --[[
yellowfive@61 726 -- equipped items, but skip slots we have just equipped (to avoid e.g. just moving 2 of the same item back and forth between mh oh weapon slots)
yellowfive@57 727 for slotNum = 1, #Amr.SlotIds do
yellowfive@57 728 local slotId = Amr.SlotIds[slotNum]
yellowfive@124 729 if _currentGearOp.slotsRemaining[slotId] then
yellowfive@61 730 local itemLink = GetInventoryItemLink("player", slotId)
yellowfive@61 731 if itemLink then
yellowfive@61 732 local invItem = Amr.ParseItemLink(itemLink)
yellowfive@124 733 if invItem then
yellowfive@61 734 local diff = countItemDifferences(item, invItem)
yellowfive@61 735 if diff < bestDiff then
yellowfive@61 736 bestItem = { slot = slotId }
yellowfive@61 737 bestDiff = diff
yellowfive@61 738 bestLink = itemLink
yellowfive@61 739 end
yellowfive@57 740 end
yellowfive@57 741 end
yellowfive@57 742 end
yellowfive@57 743 end
yellowfive@129 744 ]]
yellowfive@129 745
yellowfive@57 746 -- bank
yellowfive@124 747 if bestDiff > 0 then
yellowfive@124 748 bestItem, bestDiff, bestLink = scanBagForItem(item, BANK_CONTAINER, bestItem, bestDiff, bestLink)
yellowfive@124 749 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
yellowfive@124 750 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
yellowfive@124 751 end
yellowfive@57 752 end
yellowfive@124 753
yellowfive@124 754 return bestItem, bestDiff, bestLink
yellowfive@124 755 end
yellowfive@124 756
yellowfive@143 757 local function createAmrEquipmentSet()
yellowfive@133 758
yellowfive@143 759 -- clear any currently ignored slots, ignore shirt and tabard
yellowfive@143 760 C_EquipmentSet.ClearIgnoredSlotsForSave()
yellowfive@133 761 C_EquipmentSet.IgnoreSlotForSave(INVSLOT_BODY) -- shirt
yellowfive@133 762 C_EquipmentSet.IgnoreSlotForSave(INVSLOT_TABARD)
yellowfive@133 763
yellowfive@133 764 -- for now use icon of the spec
yellowfive@133 765 local _, specName, _, setIcon = GetSpecializationInfo(GetSpecialization())
yellowfive@57 766
yellowfive@133 767 --[[
yellowfive@124 768 local item = Amr.ParseItemLink(GetInventoryItemLink("player", INVSLOT_MAINHAND))
yellowfive@124 769 if not item then
yellowfive@124 770 item = Amr.ParseItemLink(GetInventoryItemLink("player", INVSLOT_OFFHAND))
yellowfive@124 771 end
yellowfive@124 772 if item then
yellowfive@133 773 local itemObj = Item:CreateFromItemID(item.id)
yellowfive@133 774 if itemObj then
yellowfive@133 775 setIcon = itemObj:GetItemIcon()
yellowfive@133 776 end
yellowfive@133 777 end
yellowfive@133 778 ]]
yellowfive@133 779
yellowfive@139 780 local setup = getSetupById(_activeSetupId)
yellowfive@139 781 local setname = setup.Label -- "AMR " .. specName
yellowfive@133 782 local setid = C_EquipmentSet.GetEquipmentSetID(setname)
yellowfive@133 783 if setid then
yellowfive@145 784 local oldName, oldIcon = C_EquipmentSet.GetEquipmentSetInfo(setid)
yellowfive@145 785 setIcon = oldIcon
yellowfive@133 786 C_EquipmentSet.SaveEquipmentSet(setid, setIcon)
yellowfive@133 787 else
yellowfive@133 788 C_EquipmentSet.CreateEquipmentSet(setname, setIcon)
yellowfive@124 789 end
yellowfive@124 790 end
yellowfive@124 791
yellowfive@143 792 -- on completion, create an equipment manager set if desired
yellowfive@143 793 local function onEquipGearSetComplete()
yellowfive@143 794 if Amr.db.profile.options.disableEm then return end
yellowfive@143 795
yellowfive@143 796 -- create an equipment manager set
yellowfive@143 797 createAmrEquipmentSet()
yellowfive@143 798
yellowfive@143 799 -- need to call it twice because on first load the WoW equipment manager just doesn't work
yellowfive@143 800 Amr.Wait(1, function()
yellowfive@143 801 createAmrEquipmentSet()
yellowfive@143 802 end)
yellowfive@143 803 end
yellowfive@143 804
yellowfive@124 805 -- stop any currently in-progress gear swapping operation and clean up
yellowfive@124 806 local function disposeGearOp()
yellowfive@124 807 _pendingGearOps = nil
yellowfive@124 808 _currentGearOp = nil
yellowfive@124 809 _itemLockAction = nil
yellowfive@124 810 _gearOpPasses = 0
yellowfive@124 811 _gearOpWaiting = nil
yellowfive@124 812
yellowfive@124 813 -- make sure the gear tab is still in sync
yellowfive@139 814 Amr:RefreshGearDisplay()
yellowfive@124 815 end
yellowfive@124 816
yellowfive@124 817 -- initialize a gear op to start running it
yellowfive@139 818 local function initializeGearOp(op, setupId, pos)
yellowfive@124 819 op.pos = pos
yellowfive@139 820 op.setupId = setupId
yellowfive@124 821
yellowfive@124 822 -- fill the remaining slot list and set the starting slot
yellowfive@124 823 op.nextSlot = nil
yellowfive@124 824 op.slotsRemaining = {}
yellowfive@124 825 op.isWaiting = false
yellowfive@124 826 for slotId, item in pairs(op.items) do
yellowfive@124 827 op.slotsRemaining[slotId] = true
yellowfive@124 828 if not op.nextSlot then
yellowfive@124 829 op.nextSlot = slotId
yellowfive@124 830 end
yellowfive@124 831 end
yellowfive@124 832 end
yellowfive@124 833
yellowfive@124 834 function processCurrentGearOp()
yellowfive@124 835 if not _currentGearOp then return end
yellowfive@124 836
yellowfive@124 837 if _currentGearOp.remove then
yellowfive@124 838 -- remove the next item
yellowfive@124 839
yellowfive@124 840 -- check if the slot is already empty
yellowfive@124 841 local itemLink = GetInventoryItemLink("player", _currentGearOp.nextSlot)
yellowfive@124 842 if not itemLink then
yellowfive@124 843 nextGearOp()
yellowfive@124 844 return
yellowfive@124 845 end
yellowfive@124 846
yellowfive@57 847 -- find first empty bag slot
yellowfive@57 848 local invBag, invSlot = findFirstEmptyBagSlot()
yellowfive@57 849 if not invBag then
yellowfive@57 850 -- stop if bags are too full
yellowfive@57 851 Amr:Print(L.GearEquipErrorBagFull)
yellowfive@124 852 disposeGearOp()
yellowfive@57 853 return
yellowfive@57 854 end
yellowfive@57 855
yellowfive@124 856 PickupInventoryItem(_currentGearOp.nextSlot)
yellowfive@57 857 PickupContainerItem(invBag, invSlot)
yellowfive@57 858
yellowfive@124 859 -- set an action to happen on ITEM_UNLOCKED, triggered by ClearCursor
yellowfive@124 860 _itemLockAction = {
yellowfive@57 861 bagId = invBag,
yellowfive@124 862 slotId = invSlot,
yellowfive@124 863 isRemove = true
yellowfive@57 864 }
yellowfive@124 865
yellowfive@124 866 ClearCursor()
yellowfive@124 867 -- wait for remove to complete
yellowfive@124 868 else
yellowfive@124 869 -- equip the next item
yellowfive@57 870
yellowfive@124 871 local bestItem, bestDiff, bestLink = findCurrentGearOpItem()
yellowfive@124 872
yellowfive@124 873 _itemLockAction = nil
yellowfive@57 874 ClearCursor()
yellowfive@124 875
yellowfive@124 876 if not bestItem then
yellowfive@124 877 -- stop if we can't find an item
yellowfive@124 878 Amr:Print(L.GearEquipErrorNotFound)
yellowfive@124 879 Amr:Print(L.GearEquipErrorNotFound2)
yellowfive@124 880 disposeGearOp()
yellowfive@124 881
yellowfive@124 882 elseif bestItem and bestItem.bag and (bestItem.bag == BANK_CONTAINER or bestItem.bag >= NUM_BAG_SLOTS + 1 and bestItem.bag <= NUM_BAG_SLOTS + NUM_BANKBAGSLOTS) then
yellowfive@124 883 -- find first empty bag slot
yellowfive@124 884 local invBag, invSlot = findFirstEmptyBagSlot()
yellowfive@124 885 if not invBag then
yellowfive@124 886 -- stop if bags are too full
yellowfive@124 887 Amr:Print(L.GearEquipErrorBagFull)
yellowfive@124 888 disposeGearOp()
yellowfive@124 889 return
yellowfive@124 890 end
yellowfive@124 891
yellowfive@124 892 -- move from bank to bag
yellowfive@124 893 PickupContainerItem(bestItem.bag, bestItem.slot)
yellowfive@124 894 PickupContainerItem(invBag, invSlot)
yellowfive@124 895
yellowfive@124 896 -- set an action to happen on ITEM_UNLOCKED, triggered by ClearCursor
yellowfive@124 897 _itemLockAction = {
yellowfive@124 898 bagId = invBag,
yellowfive@124 899 slotId = invSlot,
yellowfive@124 900 isBank = true
yellowfive@124 901 }
yellowfive@124 902
yellowfive@124 903 ClearCursor()
yellowfive@124 904 -- now we need to wait for game event to continue and try this item again after it is in our bag and unlocked
yellowfive@124 905
yellowfive@124 906 elseif (bestItem.bag or bestItem.bag == 0) and not Amr:CanEquip(bestItem.bag, bestItem.slot) then
yellowfive@57 907 -- if an item is not soulbound, then warn the user and quit
yellowfive@57 908 Amr:Print(L.GearEquipErrorSoulbound(bestLink))
yellowfive@124 909 disposeGearOp()
yellowfive@124 910
yellowfive@57 911 else
yellowfive@124 912
yellowfive@129 913 --print("equipping " .. bestLink .. " in slot " .. _currentGearOp.nextSlot)
yellowfive@129 914
yellowfive@57 915 -- an item in the player's bags or already equipped, equip it
yellowfive@57 916 if bestItem.bag then
yellowfive@57 917 PickupContainerItem(bestItem.bag, bestItem.slot)
yellowfive@57 918 else
yellowfive@124 919 _gearOpWaiting.inventory[bestItem.slot] = true
yellowfive@57 920 PickupInventoryItem(bestItem.slot)
yellowfive@57 921 end
yellowfive@124 922 _gearOpWaiting.inventory[_currentGearOp.nextSlot] = true
yellowfive@124 923 PickupInventoryItem(_currentGearOp.nextSlot)
yellowfive@124 924
yellowfive@124 925 -- don't wait for now, do all equips at once
yellowfive@124 926 --[[
yellowfive@124 927 -- set an action to happen on ITEM_UNLOCKED, triggered by ClearCursor
yellowfive@124 928 _itemLockAction = {
yellowfive@124 929 bagId = bestItem.bag,
yellowfive@124 930 slotId = bestItem.slot,
yellowfive@124 931 invSlot = _currentGearOp.nextSlot,
yellowfive@124 932 isEquip = true
yellowfive@124 933 }
yellowfive@124 934 ]]
yellowfive@124 935
yellowfive@124 936 ClearCursor()
yellowfive@124 937 nextGearOp()
yellowfive@124 938 end
yellowfive@124 939
yellowfive@124 940 end
yellowfive@124 941 end
yellowfive@124 942
yellowfive@124 943 -- when a gear op completes successfully, this will advance to the next op or finish
yellowfive@124 944 function nextGearOp()
yellowfive@124 945 if not _currentGearOp then return end
yellowfive@124 946
yellowfive@139 947 local setupId = _currentGearOp.setupId
yellowfive@124 948 local pos = _currentGearOp.pos
yellowfive@124 949 local passes = _gearOpPasses
yellowfive@124 950
yellowfive@124 951 -- mark the slot as done and move to the next
yellowfive@124 952 if _currentGearOp.nextSlot then
yellowfive@124 953 _currentGearOp.slotsRemaining[_currentGearOp.nextSlot] = nil
yellowfive@124 954 _currentGearOp.nextSlot = nil
yellowfive@124 955 for slotId, item in pairs(_currentGearOp.items) do
yellowfive@124 956 if _currentGearOp.slotsRemaining[slotId] then
yellowfive@124 957 _currentGearOp.nextSlot = slotId
yellowfive@124 958 break
yellowfive@124 959 end
yellowfive@124 960 end
yellowfive@124 961 end
yellowfive@124 962
yellowfive@124 963 if not _currentGearOp.nextSlot then
yellowfive@124 964 -- see if anything is still in progress and we want to wait for it before continuing
yellowfive@124 965 local inProgress = not Amr.IsEmpty(_gearOpWaiting.inventory)
yellowfive@124 966
yellowfive@124 967 if (_currentGearOp.wait or _currentGearOp.remove) and inProgress then
yellowfive@124 968 -- this will cause the item unlock handler to call nextGearOp again when all in-progress swaps have unlocked related slots
yellowfive@124 969 _currentGearOp.isWaiting = true
yellowfive@124 970 else
yellowfive@124 971 _currentGearOp = _pendingGearOps[pos + 1]
yellowfive@124 972 if _currentGearOp then
yellowfive@124 973 -- we have another op, do it
yellowfive@139 974 initializeGearOp(_currentGearOp, setupId, pos + 1)
yellowfive@124 975 processCurrentGearOp()
yellowfive@124 976 else
yellowfive@124 977 -- we are done
yellowfive@124 978 disposeGearOp()
yellowfive@124 979
yellowfive@124 980 -- this will check if not all items were swapped, and either finish up, try again, or abort if have tried too many times
yellowfive@139 981 beginEquipGearSet(setupId, passes + 1)
yellowfive@124 982 end
yellowfive@124 983 end
yellowfive@124 984 else
yellowfive@124 985 -- do the next item
yellowfive@124 986 processCurrentGearOp()
yellowfive@124 987 end
yellowfive@124 988
yellowfive@124 989 end
yellowfive@124 990
yellowfive@124 991 local function handleItemUnlocked(bagId, slotId)
yellowfive@124 992
yellowfive@124 993 -- mark anything that is waiting as unlocked if it is no longer locked
yellowfive@124 994 if _currentGearOp and _gearOpWaiting then
yellowfive@124 995 for i,s in ipairs(Amr.SlotIds) do
yellowfive@124 996 if not IsInventoryItemLocked(s) then
yellowfive@124 997 _gearOpWaiting.inventory[s] = nil
yellowfive@124 998 end
yellowfive@124 999 end
yellowfive@124 1000 end
yellowfive@124 1001
yellowfive@124 1002 if _itemLockAction then
yellowfive@124 1003 if _itemLockAction.isRemove then
yellowfive@124 1004 -- waiting for a specific remove op to finish before continuing
yellowfive@124 1005 if bagId == _itemLockAction.bagId and slotId == _itemLockAction.slotId then
yellowfive@124 1006 _itemLockAction = nil
yellowfive@124 1007 nextGearOp()
yellowfive@124 1008 end
yellowfive@124 1009 elseif _itemLockAction.isBank then
yellowfive@124 1010 -- waiting for an item to move from bank into inventory, then reprocess the current op
yellowfive@124 1011 if bagId == _itemLockAction.bagId and slotId == _itemLockAction.slotId then
yellowfive@124 1012 _itemLockAction = nil
yellowfive@124 1013 processCurrentGearOp()
yellowfive@124 1014 end
yellowfive@124 1015
yellowfive@124 1016 elseif _itemLockAction.isEquip then
yellowfive@124 1017 -- this is not currently used... we do all equips at once usually, but could go back to this if it causes problems
yellowfive@124 1018
yellowfive@124 1019 -- waiting for a specific equip op to finish
yellowfive@61 1020
yellowfive@124 1021 -- inventory slot we're swapping to is still locked, can't continue yet
yellowfive@124 1022 if IsInventoryItemLocked(_itemLockAction.invSlot) then return end
yellowfive@124 1023
yellowfive@124 1024 if _itemLockAction.bagId then
yellowfive@124 1025 local _, _, locked = GetContainerItemInfo(_itemLockAction.bagId, _itemLockAction.slotId)
yellowfive@124 1026 -- the bag slot we're swapping from is still locked, can't continue yet
yellowfive@124 1027 if locked then return end
yellowfive@124 1028 else
yellowfive@124 1029 -- inventory slot we're swapping from is still locked, can't continue yet
yellowfive@124 1030 if IsInventoryItemLocked(_itemLockAction.slotId) then return end
yellowfive@124 1031 end
yellowfive@124 1032
yellowfive@124 1033 _itemLockAction = nil
yellowfive@124 1034 nextGearOp()
yellowfive@124 1035 else
yellowfive@124 1036 -- unknown... shouldn't happen
yellowfive@124 1037 _itemLockAction = nil
yellowfive@57 1038 end
yellowfive@124 1039 else
yellowfive@124 1040
yellowfive@124 1041 -- not waiting on a specific action, check if we are waiting for all locked slots to open up and they are done
yellowfive@124 1042 if _currentGearOp and _gearOpWaiting and _currentGearOp.isWaiting and Amr.IsEmpty(_gearOpWaiting.inventory) then
yellowfive@124 1043 nextGearOp()
yellowfive@124 1044 end
yellowfive@57 1045 end
yellowfive@57 1046
yellowfive@57 1047 end
yellowfive@57 1048
yellowfive@124 1049 local function shuffle(tbl)
yellowfive@124 1050 local size = #tbl
yellowfive@124 1051 for i = size, 1, -1 do
yellowfive@124 1052 local rand = math.random(size)
yellowfive@124 1053 tbl[i], tbl[rand] = tbl[rand], tbl[i]
yellowfive@89 1054 end
yellowfive@124 1055 return tbl
yellowfive@89 1056 end
yellowfive@89 1057
yellowfive@129 1058 local _ohFirst = {
yellowfive@129 1059 [20] = true, -- PaladinProtection
yellowfive@129 1060 [32] = true, -- WarlockDemonology
yellowfive@129 1061 [36] = true -- WarriorProtection
yellowfive@129 1062 }
yellowfive@129 1063
yellowfive@139 1064 function beginEquipGearSet(setupId, passes)
yellowfive@57 1065
yellowfive@139 1066 local setup = getSetupById(setupId)
yellowfive@139 1067
yellowfive@139 1068 if not setup or not setup.Gear then
yellowfive@57 1069 Amr:Print(L.GearEquipErrorEmpty)
yellowfive@57 1070 return
yellowfive@57 1071 end
yellowfive@124 1072
yellowfive@139 1073 local gear = setup.Gear
yellowfive@139 1074 local spec = setup.SpecSlot
yellowfive@139 1075
yellowfive@139 1076 -- ensure all our stored data is up to date
yellowfive@57 1077 local player = Amr:ExportCharacter()
yellowfive@129 1078 local doOhFirst = _ohFirst[player.Specs[spec]]
yellowfive@57 1079
yellowfive@124 1080 local itemsToEquip = {
yellowfive@124 1081 legendaries = {},
yellowfive@124 1082 weapons = {},
yellowfive@129 1083 mh = {},
yellowfive@129 1084 oh = {},
yellowfive@124 1085 rings = {},
yellowfive@124 1086 trinkets = {},
yellowfive@124 1087 others = {},
yellowfive@124 1088 blanks = {}
yellowfive@124 1089 }
yellowfive@57 1090 local remaining = 0
yellowfive@129 1091 local usedItems = {}
yellowfive@124 1092
yellowfive@124 1093 -- check for items that need to be equipped, do in a random order to try and defeat any unique constraint issues we might hit
yellowfive@124 1094 local slots = {}
yellowfive@124 1095 for i,s in ipairs(Amr.SlotIds) do
yellowfive@124 1096 table.insert(slots, s)
yellowfive@124 1097 end
yellowfive@124 1098 shuffle(slots)
yellowfive@124 1099
yellowfive@124 1100 for i,slotId in ipairs(slots) do
yellowfive@124 1101
yellowfive@124 1102 -- we do stuff in batches that avoids most unique conflicts
yellowfive@124 1103 local list = itemsToEquip.others
yellowfive@129 1104 if slotId == 16 then
yellowfive@129 1105 list = itemsToEquip.mh
yellowfive@129 1106 elseif slotId == 17 then
yellowfive@129 1107 list = itemsToEquip.oh
yellowfive@124 1108 elseif slotId == 11 or slotId == 12 then
yellowfive@124 1109 list = itemsToEquip.rings
yellowfive@124 1110 elseif slotId == 13 or slotId == 14 then
yellowfive@124 1111 list = itemsToEquip.trinkets
yellowfive@124 1112 end
yellowfive@124 1113
yellowfive@57 1114 local old = player.Equipped[spec][slotId]
yellowfive@57 1115 local new = gear[slotId]
yellowfive@124 1116 local prevRemaining = remaining
yellowfive@69 1117 if new then
yellowfive@124 1118 -- if the new thing is an artifact, only match the item id
yellowfive@124 1119 local newItem = Item:CreateFromItemID(new.id)
yellowfive@124 1120 local quality = newItem and newItem:GetItemQuality() or 0
yellowfive@124 1121 if quality == 6 then
yellowfive@124 1122 if not old or new.id ~= old.id then
yellowfive@124 1123 list[slotId] = new
yellowfive@129 1124 if list == itemsToEquip.mh or list == itemsToEquip.oh then
yellowfive@129 1125 itemsToEquip.weapons[slotId] = {}
yellowfive@129 1126 end
yellowfive@69 1127 remaining = remaining + 1
yellowfive@69 1128 end
yellowfive@129 1129 else
yellowfive@145 1130
yellowfive@129 1131 -- find the best matching item anywhere in the player's gear
yellowfive@129 1132 local bestItem, bestDiff = Amr:FindMatchingItem(new, player, usedItems)
yellowfive@129 1133 new = bestItem
yellowfive@129 1134
yellowfive@149 1135 local diff = countItemDifferences(new, old)
yellowfive@124 1136
yellowfive@129 1137 if diff > 0 then
yellowfive@124 1138 list[slotId] = new
yellowfive@129 1139 if list == itemsToEquip.mh or list == itemsToEquip.oh then
yellowfive@129 1140 itemsToEquip.weapons[slotId] = {}
yellowfive@129 1141 end
yellowfive@124 1142 remaining = remaining + 1
yellowfive@124 1143 end
yellowfive@124 1144 end
yellowfive@129 1145 elseif old then
yellowfive@124 1146 -- need to remove this item
yellowfive@124 1147 itemsToEquip.blanks[slotId] = {}
yellowfive@124 1148 remaining = remaining + 1
yellowfive@124 1149 end
yellowfive@124 1150
yellowfive@124 1151 if remaining > prevRemaining then
yellowfive@124 1152 -- if we need to swap this slot, see if the old item is a legendary, add a step to remove those first to avoid conflicts
yellowfive@124 1153 if old then
yellowfive@124 1154 local oldItem = Item:CreateFromItemID(old.id)
yellowfive@124 1155 if oldItem and oldItem:GetItemQuality() == 5 then
yellowfive@124 1156 itemsToEquip.legendaries[slotId] = {}
yellowfive@124 1157 end
yellowfive@57 1158 end
yellowfive@57 1159 end
yellowfive@57 1160 end
yellowfive@124 1161
yellowfive@124 1162 if remaining > 0 then
yellowfive@57 1163
yellowfive@124 1164 if passes < 5 then
yellowfive@124 1165 _pendingGearOps = {}
yellowfive@124 1166
yellowfive@129 1167 if not Amr.IsEmpty(itemsToEquip.blanks) then
yellowfive@124 1168 -- if gear set wants slots to be blank, do that first
yellowfive@124 1169 table.insert(_pendingGearOps, { items = itemsToEquip.blanks, remove = true, label = "blanks" })
yellowfive@129 1170 end
yellowfive@124 1171 if not Amr.IsEmpty(itemsToEquip.weapons) then
yellowfive@129 1172 -- change weapons first: remove both, wait, then equip each weapon one by one, waiting after each
yellowfive@129 1173 table.insert(_pendingGearOps, { items = itemsToEquip.weapons, remove = true, label = "remove weapons" })
yellowfive@129 1174 local thisWeapon = doOhFirst and itemsToEquip.oh or itemsToEquip.mh
yellowfive@129 1175 if not Amr.IsEmpty(thisWeapon) then
yellowfive@129 1176 table.insert(_pendingGearOps, { items = thisWeapon, wait = true, label = "equip weapon 1" })
yellowfive@129 1177 end
yellowfive@129 1178 thisWeapon = doOhFirst and itemsToEquip.mh or itemsToEquip.oh
yellowfive@129 1179 if not Amr.IsEmpty(thisWeapon) then
yellowfive@129 1180 table.insert(_pendingGearOps, { items = thisWeapon, wait = true, label = "equip weapon 2" })
yellowfive@129 1181 end
yellowfive@124 1182 end
yellowfive@124 1183 if not Amr.IsEmpty(itemsToEquip.legendaries) then
yellowfive@124 1184 -- remove any legendaries, wait
yellowfive@124 1185 table.insert(_pendingGearOps, { items = itemsToEquip.legendaries, remove = true, label = "remove legendaries" })
yellowfive@124 1186 end
yellowfive@124 1187 if not Amr.IsEmpty(itemsToEquip.rings) then
yellowfive@124 1188 -- remove both rings, wait, then equip new ones
yellowfive@124 1189 table.insert(_pendingGearOps, { items = itemsToEquip.rings, remove = true, label = "remove rings" })
yellowfive@124 1190 table.insert(_pendingGearOps, { items = itemsToEquip.rings, wait = true, label = "equip rings" })
yellowfive@124 1191 end
yellowfive@124 1192 if not Amr.IsEmpty(itemsToEquip.trinkets) then
yellowfive@124 1193 -- remove both trinkets, wait, then equip new ones
yellowfive@124 1194 table.insert(_pendingGearOps, { items = itemsToEquip.trinkets, remove = true, label = "remove trinkets" })
yellowfive@124 1195 table.insert(_pendingGearOps, { items = itemsToEquip.trinkets, wait = true, label = "equip trinkets" })
yellowfive@124 1196 end
yellowfive@124 1197 if not Amr.IsEmpty(itemsToEquip.others) then
yellowfive@124 1198 -- equip all other items, wait for completion
yellowfive@124 1199 table.insert(_pendingGearOps, { items = itemsToEquip.others, wait = true, label = "equip others" })
yellowfive@124 1200 end
yellowfive@124 1201
yellowfive@169 1202 if #_pendingGearOps > 0 then
yellowfive@169 1203 -- make the last operation wait no matter what, before this gets called again to check if everything succeeded
yellowfive@169 1204 _pendingGearOps[#_pendingGearOps].wait = true
yellowfive@124 1205
yellowfive@169 1206 if not _gearOpWaiting then
yellowfive@169 1207 _gearOpWaiting = { inventory = {} }
yellowfive@169 1208 end
yellowfive@169 1209
yellowfive@169 1210 _gearOpPasses = passes
yellowfive@169 1211 _currentGearOp = _pendingGearOps[1]
yellowfive@169 1212 initializeGearOp(_currentGearOp, setupId, 1)
yellowfive@169 1213
yellowfive@169 1214 processCurrentGearOp()
yellowfive@169 1215 else
yellowfive@169 1216 -- TODO: print message that gear set couldn't be equipped
yellowfive@124 1217 end
yellowfive@169 1218
yellowfive@124 1219 else
yellowfive@124 1220 -- TODO: print message that gear set couldn't be equipped
yellowfive@89 1221 end
yellowfive@57 1222
yellowfive@57 1223 else
yellowfive@89 1224 onEquipGearSetComplete()
yellowfive@124 1225 end
yellowfive@57 1226 end
yellowfive@57 1227
yellowfive@57 1228 local function onActiveTalentGroupChanged()
yellowfive@81 1229
yellowfive@57 1230 local auto = Amr.db.profile.options.autoGear
yellowfive@81 1231 local currentSpec = GetSpecialization()
yellowfive@129 1232 local waitingSpec = _waitingForSpec
yellowfive@129 1233 _waitingForSpec = 0
yellowfive@57 1234
yellowfive@139 1235 -- when spec changes, change active setup to first one for this spec (does nothing if they have no setups for this spec)
yellowfive@139 1236 if _activeSetupId then
yellowfive@139 1237 local currentSetup = getSetupById(_activeSetupId)
yellowfive@139 1238 if currentSetup.SpecSlot ~= currentSpec then
yellowfive@139 1239 Amr:PickFirstSetupForSpec()
yellowfive@139 1240 end
yellowfive@139 1241 end
yellowfive@139 1242
yellowfive@129 1243 if currentSpec == waitingSpec or auto then
yellowfive@129 1244 -- spec is what we want, now equip the gear but after a short delay because the game auto-swaps artifact weapons
yellowfive@129 1245 Amr.Wait(2, function()
yellowfive@139 1246 beginEquipGearSet(_activeSetupId, 0)
yellowfive@129 1247 end)
yellowfive@57 1248 end
yellowfive@57 1249 end
yellowfive@57 1250
yellowfive@81 1251 -- activate the specified spec and then equip the saved gear set
yellowfive@139 1252 function Amr:EquipGearSet(setupIndex)
yellowfive@57 1253
yellowfive@139 1254 -- if no argument, then cycle
yellowfive@139 1255 if not setupIndex then
yellowfive@139 1256 if not _activeSetupId then
yellowfive@139 1257 Amr:PickFirstSetupForSpec()
yellowfive@139 1258 end
yellowfive@139 1259 for i,setup in ipairs(Amr.db.char.GearSetups) do
yellowfive@139 1260 if setup.Id == _activeSetupId then
yellowfive@139 1261 setupIndex = i
yellowfive@139 1262 break
yellowfive@139 1263 end
yellowfive@139 1264 end
yellowfive@139 1265 if not setupIndex then
yellowfive@139 1266 setupIndex = 1
yellowfive@139 1267 else
yellowfive@139 1268 setupIndex = setupIndex + 1
yellowfive@139 1269 end
yellowfive@57 1270 end
yellowfive@81 1271
yellowfive@139 1272 setupIndex = tonumber(setupIndex)
yellowfive@81 1273
yellowfive@139 1274 if setupIndex > #Amr.db.char.GearSetups then
yellowfive@139 1275 setupIndex = 1
yellowfive@139 1276 end
yellowfive@139 1277
yellowfive@57 1278 if UnitAffectingCombat("player") then
yellowfive@57 1279 Amr:Print(L.GearEquipErrorCombat)
yellowfive@57 1280 return
yellowfive@57 1281 end
yellowfive@57 1282
yellowfive@139 1283 _activeSetupId = Amr.db.char.GearSetups[setupIndex].Id
yellowfive@139 1284 Amr:RefreshGearDisplay()
yellowfive@139 1285
yellowfive@139 1286 local setup = Amr.db.char.GearSetups[setupIndex]
yellowfive@81 1287 local currentSpec = GetSpecialization()
yellowfive@139 1288 if currentSpec ~= setup.SpecSlot then
yellowfive@139 1289 _waitingForSpec = setup.SpecSlot
yellowfive@139 1290 SetSpecialization(setup.SpecSlot)
yellowfive@57 1291 else
yellowfive@129 1292 -- spec is what we want, now equip the gear
yellowfive@139 1293 beginEquipGearSet(_activeSetupId, 0)
yellowfive@57 1294 end
yellowfive@57 1295 end
yellowfive@57 1296
yellowfive@124 1297 -- moves any gear in bags to the bank if not part of a gear set
yellowfive@57 1298 function Amr:CleanBags()
yellowfive@57 1299 -- TODO: implement
yellowfive@57 1300 end
yellowfive@57 1301
yellowfive@183 1302 --[[
yellowfive@81 1303 local function testfunc(message)
yellowfive@81 1304 print(strsub(message, 13))
yellowfive@81 1305 end
yellowfive@183 1306 ]]
yellowfive@81 1307
yellowfive@57 1308 function Amr:InitializeGear()
yellowfive@87 1309 Amr:AddEventHandler("ACTIVE_TALENT_GROUP_CHANGED", onActiveTalentGroupChanged)
yellowfive@57 1310
yellowfive@183 1311 --Amr:AddEventHandler("CHAT_MSG_CHANNEL", testfunc)
yellowfive@81 1312
yellowfive@57 1313 Amr:AddEventHandler("UNIT_INVENTORY_CHANGED", function(unitID)
yellowfive@57 1314 if unitID and unitID ~= "player" then return end
yellowfive@124 1315
yellowfive@124 1316 -- don't update during a gear operation, wait until it is totally finished
yellowfive@124 1317 if _pendingGearOps then return end
yellowfive@124 1318
yellowfive@139 1319 Amr:RefreshGearDisplay()
yellowfive@57 1320 end)
yellowfive@57 1321
yellowfive@124 1322 Amr:AddEventHandler("ITEM_UNLOCKED", handleItemUnlocked)
yellowfive@122 1323 end
yellowfive@161 1324
yellowfive@161 1325
yellowfive@161 1326 -- export some local methods we need elsewhere
yellowfive@161 1327 Amr.CountItemDifferences = countItemDifferences
yellowfive@161 1328 Amr.FindFirstEmptyBagSlot = findFirstEmptyBagSlot