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