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@57
|
10 if item1 == nil and item2 == nil then return 0 end
|
yellowfive@57
|
11
|
yellowfive@57
|
12 -- different items (id + bonus ids + suffix, constitutes a different physical drop)
|
yellowfive@57
|
13 if Amr.GetItemUniqueId(item1, true) ~= Amr.GetItemUniqueId(item2, true) then
|
yellowfive@57
|
14 return 1000
|
yellowfive@57
|
15 end
|
yellowfive@57
|
16
|
yellowfive@81
|
17 -- different upgrade levels of the same item
|
yellowfive@57
|
18 if item1.upgradeId ~= item2.upgradeId then
|
yellowfive@57
|
19 return 100
|
yellowfive@57
|
20 end
|
yellowfive@57
|
21
|
yellowfive@57
|
22 -- different gems
|
yellowfive@57
|
23 local gemDiffs = 0
|
yellowfive@57
|
24 for i = 1, 3 do
|
yellowfive@57
|
25 if item1.gemIds[i] ~= item2.gemIds[i] then
|
yellowfive@57
|
26 gemDiffs = gemDiffs + 1
|
yellowfive@57
|
27 end
|
yellowfive@57
|
28 end
|
yellowfive@57
|
29
|
yellowfive@57
|
30 -- different enchants
|
yellowfive@57
|
31 local enchantDiff = 0
|
yellowfive@57
|
32 if item1.enchantId ~= item2.enchantId then
|
yellowfive@57
|
33 enchantDiff = 1
|
yellowfive@57
|
34 end
|
yellowfive@57
|
35
|
yellowfive@57
|
36 return gemDiffs + enchantDiff
|
yellowfive@57
|
37 end
|
yellowfive@57
|
38
|
yellowfive@57
|
39 -- given a table of items (keyed or indexed doesn't matter) find closest match to item, or nil if none are a match
|
yellowfive@57
|
40 local function findMatchingItemFromTable(item, list, bestLink, bestItem, bestDiff, bestLoc, usedItems, tableType)
|
yellowfive@57
|
41 if not list then return nil end
|
yellowfive@57
|
42
|
yellowfive@73
|
43 local found = false
|
yellowfive@57
|
44 for k,v in pairs(list) do
|
yellowfive@57
|
45 local listItem = Amr.ParseItemLink(v)
|
yellowfive@57
|
46 if listItem then
|
yellowfive@57
|
47 local diff = countItemDifferences(item, listItem)
|
yellowfive@57
|
48 if diff < bestDiff then
|
yellowfive@57
|
49 -- each physical item can only be used once, the usedItems table has items we can't use in this search
|
yellowfive@57
|
50 local key = string.format("%s_%s", tableType, k)
|
yellowfive@57
|
51 if not usedItems[key] then
|
yellowfive@57
|
52 bestLink = v
|
yellowfive@57
|
53 bestItem = listItem
|
yellowfive@57
|
54 bestDiff = diff
|
yellowfive@57
|
55 bestLoc = string.format("%s_%s", tableType, k)
|
yellowfive@73
|
56 found = true
|
yellowfive@57
|
57 end
|
yellowfive@57
|
58 end
|
yellowfive@73
|
59 if found then break end
|
yellowfive@57
|
60 end
|
yellowfive@57
|
61 end
|
yellowfive@57
|
62
|
yellowfive@57
|
63 return bestLink, bestItem, bestDiff, bestLoc
|
yellowfive@57
|
64 end
|
yellowfive@57
|
65
|
yellowfive@57
|
66 -- search the player's equipped gear, bag, bank, and void storage for an item that best matches the specified item
|
yellowfive@57
|
67 function Amr:FindMatchingItem(item, player, usedItems)
|
yellowfive@57
|
68 if not item then return nil end
|
yellowfive@57
|
69
|
yellowfive@57
|
70 local equipped = player.Equipped and player.Equipped[player.ActiveSpec] or nil
|
yellowfive@57
|
71 local bestLink, bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, equipped, nil, nil, 1000, nil, usedItems, "equip")
|
yellowfive@57
|
72 bestLink, bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BagItems, bestLink, bestItem, bestDiff, bestLoc, usedItems, "bag")
|
yellowfive@57
|
73 bestLink, bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.BankItems, bestLink, bestItem, bestDiff, bestLoc, usedItems, "bank")
|
yellowfive@57
|
74 bestLink, bestItem, bestDiff, bestLoc = findMatchingItemFromTable(item, player.VoidItems, bestLink, bestItem, bestDiff, bestLoc, usedItems, "void")
|
yellowfive@57
|
75
|
yellowfive@57
|
76 if bestDiff >= 1000 then
|
yellowfive@57
|
77 return nil, nil, 1000
|
yellowfive@57
|
78 else
|
yellowfive@57
|
79 usedItems[bestLoc] = true
|
yellowfive@57
|
80 return bestLink, bestItem, bestDiff
|
yellowfive@57
|
81 end
|
yellowfive@57
|
82 end
|
yellowfive@57
|
83
|
yellowfive@57
|
84 local function renderEmptyGear(container)
|
yellowfive@57
|
85
|
yellowfive@57
|
86 local panelBlank = AceGUI:Create("AmrUiPanel")
|
yellowfive@57
|
87 panelBlank:SetLayout("None")
|
yellowfive@57
|
88 panelBlank:SetBackgroundColor(Amr.Colors.Black, 0.4)
|
yellowfive@57
|
89 panelBlank:SetPoint("TOPLEFT", container.content, "TOPLEFT", 6, 0)
|
yellowfive@57
|
90 panelBlank:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
|
yellowfive@57
|
91 container:AddChild(panelBlank)
|
yellowfive@57
|
92
|
yellowfive@57
|
93 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
94 lbl:SetText(L.GearBlank)
|
yellowfive@57
|
95 lbl:SetWidth(700)
|
yellowfive@57
|
96 lbl:SetJustifyH("MIDDLE")
|
yellowfive@57
|
97 lbl:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextTan))
|
yellowfive@57
|
98 lbl:SetPoint("BOTTOM", panelBlank.content, "CENTER", 0, 20)
|
yellowfive@57
|
99 panelBlank:AddChild(lbl)
|
yellowfive@57
|
100
|
yellowfive@57
|
101 local lbl2 = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
102 lbl2:SetText(L.GearBlank2)
|
yellowfive@57
|
103 lbl2:SetWidth(700)
|
yellowfive@57
|
104 lbl2:SetJustifyH("MIDDLE")
|
yellowfive@57
|
105 lbl2:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextTan))
|
yellowfive@57
|
106 lbl2:SetPoint("TOP", lbl.frame, "CENTER", 0, -20)
|
yellowfive@57
|
107 panelBlank:AddChild(lbl2)
|
yellowfive@57
|
108 end
|
yellowfive@57
|
109
|
yellowfive@57
|
110 local function renderGear(spec, container)
|
yellowfive@57
|
111
|
yellowfive@57
|
112 local player = Amr:ExportCharacter()
|
yellowfive@57
|
113 local gear = Amr.db.char.GearSets[spec]
|
yellowfive@57
|
114 local equipped = player.Equipped[player.ActiveSpec]
|
yellowfive@57
|
115
|
yellowfive@57
|
116 if not gear then
|
yellowfive@57
|
117 -- no gear has been imported for this spec so show a message
|
yellowfive@57
|
118 renderEmptyGear(container)
|
yellowfive@57
|
119 else
|
yellowfive@57
|
120 local panelGear = AceGUI:Create("AmrUiPanel")
|
yellowfive@57
|
121 panelGear:SetLayout("None")
|
yellowfive@57
|
122 panelGear:SetBackgroundColor(Amr.Colors.Black, 0.3)
|
yellowfive@57
|
123 panelGear:SetPoint("TOPLEFT", container.content, "TOPLEFT", 6, 0)
|
yellowfive@57
|
124 panelGear:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT", -300, 0)
|
yellowfive@57
|
125 container:AddChild(panelGear)
|
yellowfive@57
|
126
|
yellowfive@57
|
127 local panelMods = AceGUI:Create("AmrUiPanel")
|
yellowfive@57
|
128 panelMods:SetLayout("None")
|
yellowfive@57
|
129 panelMods:SetPoint("TOPLEFT", panelGear.frame, "TOPRIGHT", 15, 0)
|
yellowfive@57
|
130 panelMods:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
|
yellowfive@57
|
131 panelMods:SetBackgroundColor(Amr.Colors.Black, 0.3)
|
yellowfive@57
|
132 container:AddChild(panelMods)
|
yellowfive@57
|
133
|
yellowfive@57
|
134 -- spec icon
|
yellowfive@57
|
135 local icon = AceGUI:Create("AmrUiIcon")
|
yellowfive@57
|
136 icon:SetIconBorderColor(Amr.Colors.Classes[player.Class])
|
yellowfive@57
|
137 icon:SetWidth(48)
|
yellowfive@57
|
138 icon:SetHeight(48)
|
yellowfive@57
|
139
|
yellowfive@57
|
140 local iconSpec
|
yellowfive@81
|
141 if player.SubSpecs and player.SubSpecs[spec] then
|
yellowfive@57
|
142 iconSpec = player.SubSpecs[spec]
|
yellowfive@57
|
143 else
|
yellowfive@57
|
144 iconSpec = player.Specs[spec]
|
yellowfive@57
|
145 end
|
yellowfive@57
|
146
|
yellowfive@57
|
147 icon:SetIcon("Interface\\Icons\\" .. Amr.SpecIcons[iconSpec])
|
yellowfive@57
|
148 icon:SetPoint("TOPLEFT", panelGear.content, "TOPLEFT", 10, -10)
|
yellowfive@57
|
149 panelGear:AddChild(icon)
|
yellowfive@57
|
150
|
yellowfive@57
|
151 local btnEquip = AceGUI:Create("AmrUiButton")
|
yellowfive@81
|
152 btnEquip:SetText(L.GearButtonEquip(L.SpecsShort[player.Specs[spec]]))
|
yellowfive@57
|
153 btnEquip:SetBackgroundColor(Amr.Colors.Green)
|
yellowfive@57
|
154 btnEquip:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
|
yellowfive@57
|
155 btnEquip:SetWidth(300)
|
yellowfive@57
|
156 btnEquip:SetHeight(26)
|
yellowfive@57
|
157 btnEquip:SetPoint("LEFT", icon.frame, "RIGHT", 40, 0)
|
yellowfive@57
|
158 btnEquip:SetPoint("RIGHT", panelGear.content, "RIGHT", -40, 0)
|
yellowfive@57
|
159 btnEquip:SetCallback("OnClick", function(widget)
|
yellowfive@57
|
160 Amr:EquipGearSet(spec)
|
yellowfive@57
|
161 end)
|
yellowfive@57
|
162 panelGear:AddChild(btnEquip)
|
yellowfive@57
|
163
|
yellowfive@57
|
164 -- each physical item can only be used once, this tracks ones we have already used
|
yellowfive@57
|
165 local usedItems = {}
|
yellowfive@57
|
166
|
yellowfive@57
|
167 -- gear list
|
yellowfive@57
|
168 local prevElem = icon
|
yellowfive@57
|
169 for slotNum = 1, #Amr.SlotIds do
|
yellowfive@57
|
170 local slotId = Amr.SlotIds[slotNum]
|
yellowfive@57
|
171
|
yellowfive@57
|
172 local equippedItemLink = equipped and equipped[slotId] or nil
|
yellowfive@57
|
173 local equippedItem = Amr.ParseItemLink(equippedItemLink)
|
yellowfive@57
|
174 local optimalItem = gear[slotId]
|
yellowfive@57
|
175 local optimalItemLink = Amr.CreateItemLink(optimalItem)
|
yellowfive@57
|
176
|
yellowfive@57
|
177 -- 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
|
178 local isEquipped = false
|
yellowfive@57
|
179 if equippedItem and optimalItem and Amr.GetItemUniqueId(equippedItem) == Amr.GetItemUniqueId(optimalItem) then
|
yellowfive@57
|
180 isEquipped = true
|
yellowfive@57
|
181 end
|
yellowfive@57
|
182
|
yellowfive@57
|
183 -- find the item in the player's inventory that best matches what the optimization wants to use
|
yellowfive@57
|
184 local matchItemLink, matchItem = Amr:FindMatchingItem(optimalItem, player, usedItems)
|
yellowfive@57
|
185
|
yellowfive@57
|
186 -- slot label
|
yellowfive@57
|
187 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
188 lbl:SetText(Amr.SlotDisplayText[slotId])
|
yellowfive@57
|
189 lbl:SetWidth(85)
|
yellowfive@57
|
190 lbl:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
|
yellowfive@57
|
191 lbl:SetPoint("TOPLEFT", prevElem.frame, "BOTTOMLEFT", 0, -12)
|
yellowfive@57
|
192 panelGear:AddChild(lbl)
|
yellowfive@57
|
193 prevElem = lbl
|
yellowfive@57
|
194
|
yellowfive@57
|
195 -- ilvl label
|
yellowfive@57
|
196 local lblIlvl = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
197 lblIlvl:SetWidth(45)
|
yellowfive@57
|
198 lblIlvl:SetFont(Amr.CreateFont("Italic", 14, Amr.Colors.TextTan))
|
yellowfive@57
|
199 lblIlvl:SetPoint("TOPLEFT", lbl.frame, "TOPRIGHT", 0, 0)
|
yellowfive@57
|
200 panelGear:AddChild(lblIlvl)
|
yellowfive@57
|
201
|
yellowfive@57
|
202 -- equipped label
|
yellowfive@57
|
203 local lblEquipped = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
204 lblEquipped:SetWidth(20)
|
yellowfive@57
|
205 lblEquipped:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
|
yellowfive@57
|
206 lblEquipped:SetPoint("TOPLEFT", lblIlvl.frame, "TOPRIGHT", 0, 0)
|
yellowfive@57
|
207 lblEquipped:SetText(isEquipped and "E" or "")
|
yellowfive@57
|
208 panelGear:AddChild(lblEquipped)
|
yellowfive@57
|
209
|
yellowfive@57
|
210 -- item name/link label
|
yellowfive@57
|
211 local lblItem = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
212 lblItem:SetWordWrap(false)
|
yellowfive@57
|
213 lblItem:SetWidth(345)
|
yellowfive@57
|
214 lblItem:SetFont(Amr.CreateFont(isEquipped and "Regular" or "Bold", isEquipped and 14 or 15, Amr.Colors.White))
|
yellowfive@57
|
215 lblItem:SetPoint("TOPLEFT", lblEquipped.frame, "TOPRIGHT", 0, 0)
|
yellowfive@57
|
216 panelGear:AddChild(lblItem)
|
yellowfive@57
|
217
|
yellowfive@57
|
218 -- fill the name/ilvl labels, which may require asynchronous loading of item information
|
yellowfive@57
|
219 if optimalItemLink then
|
yellowfive@57
|
220 Amr.GetItemInfo(optimalItemLink, function(obj, name, link, quality, iLevel)
|
yellowfive@57
|
221 -- set item name, tooltip, and ilvl
|
yellowfive@57
|
222 obj.nameLabel:SetText(link:gsub("%[", ""):gsub("%]", ""))
|
yellowfive@100
|
223
|
yellowfive@100
|
224 -- not quite right but whatever... close enough
|
yellowfive@100
|
225 if quality == 6 then
|
yellowfive@100
|
226 local tmprel = optimalItem.relicBonusIds
|
yellowfive@100
|
227 optimalItem.relicBonusIds = nil
|
yellowfive@100
|
228 link = Amr.CreateItemLink(optimalItem)
|
yellowfive@100
|
229 optimalItem.relicBonusIds = tmprel
|
yellowfive@100
|
230 end
|
yellowfive@100
|
231
|
yellowfive@57
|
232 Amr:SetItemTooltip(obj.nameLabel, link)
|
yellowfive@89
|
233
|
yellowfive@89
|
234 -- the game's info gives the wrong item level, so we have to scan for it
|
yellowfive@100
|
235 --iLevel = (quality ~= 6 or optimalItem.relicBonusIds) and Amr.GetItemLevel(nil, nil, link) or ""
|
yellowfive@89
|
236 obj.ilvlLabel:SetText(iLevel)
|
yellowfive@89
|
237
|
yellowfive@57
|
238 end, { ilvlLabel = lblIlvl, nameLabel = lblItem })
|
yellowfive@57
|
239 end
|
yellowfive@57
|
240
|
yellowfive@57
|
241 -- modifications
|
yellowfive@57
|
242 if optimalItem then
|
yellowfive@57
|
243 local itemInfo = Amr.db.char.ExtraItemData[spec][optimalItem.id]
|
yellowfive@57
|
244
|
yellowfive@57
|
245 -- gems
|
yellowfive@57
|
246 if itemInfo and itemInfo.socketColors then
|
yellowfive@89
|
247 local prevSocket = nil
|
yellowfive@57
|
248 for i = 1, #itemInfo.socketColors do
|
yellowfive@57
|
249 local g = optimalItem.gemIds[i]
|
yellowfive@57
|
250 local isGemEquipped = g ~= 0 and matchItem and matchItem.gemIds and matchItem.gemIds[i] == g
|
yellowfive@57
|
251
|
yellowfive@57
|
252 -- highlight for gem that doesn't match
|
yellowfive@57
|
253 local socketBorder = AceGUI:Create("AmrUiPanel")
|
yellowfive@57
|
254 socketBorder:SetLayout("None")
|
yellowfive@57
|
255 socketBorder:SetBackgroundColor(Amr.Colors.Black, isGemEquipped and 0 or 1)
|
yellowfive@57
|
256 socketBorder:SetWidth(26)
|
yellowfive@57
|
257 socketBorder:SetHeight(26)
|
yellowfive@89
|
258 if not prevSocket then
|
yellowfive@89
|
259 socketBorder:SetPoint("LEFT", lblItem.frame, "RIGHT", 30, 0)
|
yellowfive@89
|
260 else
|
yellowfive@89
|
261 socketBorder:SetPoint("LEFT", prevSocket.frame, "RIGHT", 2, 0)
|
yellowfive@89
|
262 end
|
yellowfive@57
|
263 if isGemEquipped then
|
yellowfive@57
|
264 socketBorder:SetAlpha(0.3)
|
yellowfive@57
|
265 end
|
yellowfive@57
|
266 panelMods:AddChild(socketBorder)
|
yellowfive@57
|
267
|
yellowfive@57
|
268 local socketBg = AceGUI:Create("AmrUiIcon")
|
yellowfive@57
|
269 socketBg:SetLayout("None")
|
yellowfive@57
|
270 socketBg:SetBorderWidth(2)
|
yellowfive@57
|
271 socketBg:SetIconBorderColor(Amr.Colors.Green, isGemEquipped and 0 or 1)
|
yellowfive@57
|
272 socketBg:SetWidth(24)
|
yellowfive@57
|
273 socketBg:SetHeight(24)
|
yellowfive@57
|
274 socketBg:SetPoint("TOPLEFT", socketBorder.content, "TOPLEFT", 1, -1)
|
yellowfive@57
|
275 socketBorder:AddChild(socketBg)
|
yellowfive@57
|
276
|
yellowfive@57
|
277 local socketIcon = AceGUI:Create("AmrUiIcon")
|
yellowfive@57
|
278 socketIcon:SetBorderWidth(1)
|
yellowfive@57
|
279 socketIcon:SetIconBorderColor(Amr.Colors.White)
|
yellowfive@57
|
280 socketIcon:SetWidth(18)
|
yellowfive@57
|
281 socketIcon:SetHeight(18)
|
yellowfive@57
|
282 socketIcon:SetPoint("CENTER", socketBg.content, "CENTER")
|
yellowfive@57
|
283 socketBg:AddChild(socketIcon)
|
yellowfive@57
|
284
|
yellowfive@57
|
285 -- get icon for optimized gem
|
yellowfive@57
|
286 if g ~= 0 then
|
yellowfive@57
|
287 local gemInfo = Amr.db.char.ExtraGemData[spec][g]
|
yellowfive@57
|
288 if gemInfo then
|
yellowfive@89
|
289 local gident = gemInfo.id
|
yellowfive@89
|
290 if optimalItem.relicBonusIds then
|
yellowfive@89
|
291 gident = Amr.CreateItemLink({ id = gemInfo.id, enchantId = 0, gemIds = {0,0,0,0}, suffixId = 0, bonusIds = optimalItem.relicBonusIds[i]})
|
yellowfive@89
|
292 end
|
yellowfive@89
|
293 Amr.GetItemInfo(gident, function(obj, name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture)
|
yellowfive@57
|
294 -- set icon and a tooltip
|
yellowfive@57
|
295 obj:SetIcon(texture)
|
yellowfive@57
|
296 Amr:SetItemTooltip(obj, link)
|
yellowfive@57
|
297 end, socketIcon)
|
yellowfive@57
|
298 end
|
yellowfive@57
|
299 end
|
yellowfive@89
|
300
|
yellowfive@89
|
301 prevSocket = socketBorder
|
yellowfive@57
|
302 end
|
yellowfive@57
|
303 end
|
yellowfive@57
|
304
|
yellowfive@57
|
305 -- enchant
|
yellowfive@57
|
306 if optimalItem.enchantId and optimalItem.enchantId ~= 0 then
|
yellowfive@57
|
307 local isEnchantEquipped = matchItem and matchItem.enchantId and matchItem.enchantId == optimalItem.enchantId
|
yellowfive@57
|
308
|
yellowfive@57
|
309 local lblEnchant = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
310 lblEnchant:SetWordWrap(false)
|
yellowfive@57
|
311 lblEnchant:SetWidth(170)
|
yellowfive@57
|
312 lblEnchant:SetFont(Amr.CreateFont(isEnchantEquipped and "Regular" or "Bold", 14, isEnchantEquipped and Amr.Colors.TextGray or Amr.Colors.White))
|
yellowfive@57
|
313 lblEnchant:SetPoint("TOPLEFT", lblItem.frame, "TOPRIGHT", 130, 0)
|
yellowfive@57
|
314
|
yellowfive@57
|
315 local enchInfo = Amr.db.char.ExtraEnchantData[spec][optimalItem.enchantId]
|
yellowfive@57
|
316 if enchInfo then
|
yellowfive@57
|
317 lblEnchant:SetText(enchInfo.text)
|
yellowfive@57
|
318
|
yellowfive@57
|
319 Amr.GetItemInfo(enchInfo.itemId, function(obj, name, link)
|
yellowfive@57
|
320 Amr:SetItemTooltip(obj, link)
|
yellowfive@57
|
321 end, lblEnchant)
|
yellowfive@57
|
322 --Amr:SetSpellTooltip(lblEnchant, enchInfo.spellId)
|
yellowfive@57
|
323 end
|
yellowfive@57
|
324 panelMods:AddChild(lblEnchant)
|
yellowfive@57
|
325 end
|
yellowfive@57
|
326 end
|
yellowfive@57
|
327
|
yellowfive@57
|
328 prevElem = lbl
|
yellowfive@57
|
329 end
|
yellowfive@57
|
330 end
|
yellowfive@57
|
331 end
|
yellowfive@57
|
332
|
yellowfive@57
|
333 local function onGearTabSelected(container, event, group)
|
yellowfive@57
|
334 container:ReleaseChildren()
|
yellowfive@57
|
335 _activeTab = group
|
yellowfive@57
|
336 renderGear(tonumber(group), container)
|
yellowfive@57
|
337 end
|
yellowfive@57
|
338
|
yellowfive@57
|
339 local function onImportClick(widget)
|
yellowfive@57
|
340 Amr:ShowImportWindow()
|
yellowfive@57
|
341 end
|
yellowfive@57
|
342
|
yellowfive@57
|
343 -- renders the main UI for the Gear tab
|
yellowfive@57
|
344 function Amr:RenderTabGear(container)
|
yellowfive@57
|
345
|
yellowfive@57
|
346 local btnImport = AceGUI:Create("AmrUiButton")
|
yellowfive@57
|
347 btnImport:SetText(L.GearButtonImportText)
|
yellowfive@57
|
348 btnImport:SetBackgroundColor(Amr.Colors.Orange)
|
yellowfive@57
|
349 btnImport:SetFont(Amr.CreateFont("Bold", 16, Amr.Colors.White))
|
yellowfive@57
|
350 btnImport:SetWidth(120)
|
yellowfive@57
|
351 btnImport:SetHeight(26)
|
yellowfive@57
|
352 btnImport:SetPoint("TOPLEFT", container.content, "TOPLEFT", 0, -81)
|
yellowfive@57
|
353 btnImport:SetCallback("OnClick", onImportClick)
|
yellowfive@57
|
354 container:AddChild(btnImport)
|
yellowfive@57
|
355
|
yellowfive@57
|
356 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
357 lbl:SetText(L.GearImportNote)
|
yellowfive@57
|
358 lbl:SetWidth(100)
|
yellowfive@57
|
359 lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.TextTan))
|
yellowfive@57
|
360 lbl:SetJustifyH("MIDDLE")
|
yellowfive@57
|
361 lbl:SetPoint("TOP", btnImport.frame, "BOTTOM", 0, -5)
|
yellowfive@57
|
362 container:AddChild(lbl)
|
yellowfive@57
|
363
|
yellowfive@57
|
364 local lbl2 = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
365 lbl2:SetText(L.GearTipTitle)
|
yellowfive@57
|
366 lbl2:SetWidth(140)
|
yellowfive@57
|
367 lbl2:SetFont(Amr.CreateFont("Italic", 20, Amr.Colors.Text))
|
yellowfive@57
|
368 lbl2:SetJustifyH("MIDDLE")
|
yellowfive@57
|
369 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 0, -50)
|
yellowfive@57
|
370 container:AddChild(lbl2)
|
yellowfive@57
|
371
|
yellowfive@57
|
372 lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
373 lbl:SetText(L.GearTipText)
|
yellowfive@57
|
374 lbl:SetWidth(140)
|
yellowfive@57
|
375 lbl:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text))
|
yellowfive@57
|
376 lbl:SetJustifyH("MIDDLE")
|
yellowfive@57
|
377 lbl:SetPoint("TOP", lbl2.frame, "BOTTOM", 0, -5)
|
yellowfive@57
|
378 container:AddChild(lbl)
|
yellowfive@57
|
379
|
yellowfive@57
|
380 lbl2 = AceGUI:Create("AmrUiLabel")
|
yellowfive@57
|
381 lbl2:SetText(L.GearTipCommands)
|
yellowfive@57
|
382 lbl2:SetWidth(130)
|
yellowfive@57
|
383 lbl2:SetFont(Amr.CreateFont("Italic", 12, Amr.Colors.Text))
|
yellowfive@57
|
384 lbl2:SetPoint("TOP", lbl.frame, "BOTTOM", 10, -5)
|
yellowfive@57
|
385 container:AddChild(lbl2)
|
yellowfive@57
|
386
|
yellowfive@57
|
387 local t = AceGUI:Create("AmrUiTabGroup")
|
yellowfive@57
|
388 t:SetLayout("None")
|
yellowfive@81
|
389
|
yellowfive@81
|
390 local tabz = {}
|
yellowfive@81
|
391 for pos = 1, 4 do
|
yellowfive@81
|
392 local specId = GetSpecializationInfo(pos)
|
yellowfive@81
|
393 if specId then
|
yellowfive@81
|
394 table.insert(tabz, { text = L.SpecsShort[Amr.SpecIds[specId]], value = pos .. "", style = "bold" })
|
yellowfive@81
|
395 end
|
yellowfive@81
|
396 end
|
yellowfive@81
|
397
|
yellowfive@81
|
398 t:SetTabs(tabz)
|
yellowfive@57
|
399 t:SetCallback("OnGroupSelected", onGearTabSelected)
|
yellowfive@57
|
400 t:SetPoint("TOPLEFT", container.content, "TOPLEFT", 144, -30)
|
yellowfive@57
|
401 t:SetPoint("BOTTOMRIGHT", container.content, "BOTTOMRIGHT")
|
yellowfive@57
|
402 container:AddChild(t)
|
yellowfive@57
|
403 _gearTabs = t;
|
yellowfive@57
|
404
|
yellowfive@61
|
405 local btnShop = AceGUI:Create("AmrUiButton")
|
yellowfive@61
|
406 btnShop:SetText(L.GearButtonShop)
|
yellowfive@61
|
407 btnShop:SetBackgroundColor(Amr.Colors.Blue)
|
yellowfive@61
|
408 btnShop:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.White))
|
yellowfive@61
|
409 btnShop:SetWidth(245)
|
yellowfive@61
|
410 btnShop:SetHeight(26)
|
yellowfive@61
|
411 btnShop:SetPoint("TOPRIGHT", container.content, "TOPRIGHT", -20, -25)
|
yellowfive@61
|
412 btnShop:SetCallback("OnClick", function(widget) Amr:ShowShopWindow() end)
|
yellowfive@61
|
413 container:AddChild(btnShop)
|
yellowfive@61
|
414
|
yellowfive@57
|
415 if not _activeTab then
|
yellowfive@81
|
416 _activeTab = tostring(GetSpecialization())
|
yellowfive@57
|
417 end
|
yellowfive@57
|
418
|
yellowfive@57
|
419 t:SelectTab(_activeTab)
|
yellowfive@57
|
420 end
|
yellowfive@57
|
421
|
yellowfive@57
|
422 -- do cleanup when the gear tab is released
|
yellowfive@57
|
423 function Amr:ReleaseTabGear()
|
yellowfive@57
|
424 _gearTabs = nil
|
yellowfive@57
|
425 end
|
yellowfive@57
|
426
|
yellowfive@57
|
427 -- show and update the gear tab for the specified spec
|
yellowfive@57
|
428 function Amr:ShowGearTab(spec)
|
yellowfive@57
|
429 if not _gearTabs then return end
|
yellowfive@57
|
430
|
yellowfive@57
|
431 _activeTab = tostring(spec)
|
yellowfive@57
|
432 _gearTabs:SelectTab(_activeTab)
|
yellowfive@57
|
433 end
|
yellowfive@57
|
434
|
yellowfive@57
|
435 -- refresh display of the current gear tab
|
yellowfive@57
|
436 function Amr:RefreshGearTab()
|
yellowfive@57
|
437 if not _gearTabs then return end
|
yellowfive@57
|
438 _gearTabs:SelectTab(_activeTab)
|
yellowfive@57
|
439 end
|
yellowfive@57
|
440
|
yellowfive@57
|
441
|
yellowfive@57
|
442 ------------------------------------------------------------------------------------------------
|
yellowfive@57
|
443 -- Gear Set Management
|
yellowfive@57
|
444 ------------------------------------------------------------------------------------------------
|
yellowfive@57
|
445 local _waitingForSpec = 0
|
yellowfive@57
|
446 local _waitingForItemLock = nil
|
yellowfive@57
|
447 local _pendingEquip = nil
|
yellowfive@89
|
448 local _pendingRemove = nil
|
yellowfive@57
|
449
|
yellowfive@57
|
450 -- scan a bag for the best matching item
|
yellowfive@57
|
451 local function scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
|
yellowfive@57
|
452 local numSlots = GetContainerNumSlots(bagId)
|
yellowfive@57
|
453 for slotId = 1, numSlots do
|
yellowfive@57
|
454 local _, _, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
|
yellowfive@57
|
455 -- we skip any stackable item, as far as we know, there is no equippable gear that can be stacked
|
yellowfive@57
|
456 if itemLink then
|
yellowfive@57
|
457 local bagItem = Amr.ParseItemLink(itemLink)
|
yellowfive@57
|
458 if bagItem ~= nil then
|
yellowfive@57
|
459 local diff = countItemDifferences(item, bagItem)
|
yellowfive@57
|
460 if diff < bestDiff then
|
yellowfive@57
|
461 bestItem = { bag = bagId, slot = slotId }
|
yellowfive@57
|
462 bestDiff = diff
|
yellowfive@57
|
463 bestLink = itemLink
|
yellowfive@57
|
464 end
|
yellowfive@57
|
465 end
|
yellowfive@57
|
466 end
|
yellowfive@57
|
467 end
|
yellowfive@57
|
468 return bestItem, bestDiff, bestLink
|
yellowfive@57
|
469 end
|
yellowfive@57
|
470
|
yellowfive@89
|
471 local function onEquipGearSetComplete()
|
yellowfive@91
|
472 if Amr.db.profile.options.disableEm then return end
|
yellowfive@91
|
473
|
yellowfive@89
|
474 -- create an equipment manager set
|
yellowfive@89
|
475 local specId, specName = GetSpecializationInfo(GetSpecialization())
|
yellowfive@89
|
476
|
yellowfive@89
|
477 local item = Amr.ParseItemLink(GetInventoryItemLink("player", INVSLOT_MAINHAND))
|
yellowfive@89
|
478 if not item or not Amr.ArtifactIdToSpecNumber[item.id] then
|
yellowfive@89
|
479 item = Amr.ParseItemLink(GetInventoryItemLink("player", INVSLOT_OFFHAND))
|
yellowfive@89
|
480 if item and not Amr.ArtifactIdToSpecNumber[item.id] then
|
yellowfive@89
|
481 item = nil
|
yellowfive@89
|
482 end
|
yellowfive@89
|
483 end
|
yellowfive@89
|
484 if item then
|
yellowfive@89
|
485 Amr.GetItemInfo(item.id, function(customArg, name, link, quality, iLevel, reqLevel, class, subclass, maxStack, equipSlot, texture)
|
yellowfive@108
|
486 local setname = "AMR " .. specName
|
yellowfive@108
|
487 local setid = C_EquipmentSet.GetEquipmentSetID(setname)
|
yellowfive@108
|
488 if setid then
|
yellowfive@108
|
489 C_EquipmentSet.SaveEquipmentSet(setid, texture)
|
yellowfive@108
|
490 else
|
yellowfive@108
|
491 C_EquipmentSet.CreateEquipmentSet(setname, texture)
|
yellowfive@108
|
492 end
|
yellowfive@89
|
493 end)
|
yellowfive@89
|
494 end
|
yellowfive@89
|
495 end
|
yellowfive@89
|
496
|
yellowfive@57
|
497 -- find the first empty slot in the player's backpack+bags
|
yellowfive@57
|
498 local function findFirstEmptyBagSlot()
|
yellowfive@57
|
499
|
yellowfive@57
|
500 local bagIds = {}
|
yellowfive@57
|
501 table.insert(bagIds, BACKPACK_CONTAINER)
|
yellowfive@57
|
502 for bagId = 1, NUM_BAG_SLOTS do
|
yellowfive@57
|
503 table.insert(bagIds, bagId)
|
yellowfive@57
|
504 end
|
yellowfive@57
|
505
|
yellowfive@57
|
506 for i, bagId in ipairs(bagIds) do
|
yellowfive@57
|
507 local numSlots = GetContainerNumSlots(bagId)
|
yellowfive@57
|
508 for slotId = 1, numSlots do
|
yellowfive@57
|
509 local _, _, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
|
yellowfive@57
|
510 if not itemLink then
|
yellowfive@57
|
511 return bagId, slotId
|
yellowfive@57
|
512 end
|
yellowfive@57
|
513 end
|
yellowfive@57
|
514 end
|
yellowfive@57
|
515
|
yellowfive@57
|
516 return nil, nil
|
yellowfive@57
|
517 end
|
yellowfive@57
|
518
|
yellowfive@57
|
519 local function finishEquipGearSet()
|
yellowfive@57
|
520 if not _pendingEquip then return end
|
yellowfive@57
|
521
|
yellowfive@57
|
522 _pendingEquip.tries = _pendingEquip.tries + 1
|
yellowfive@57
|
523 if _pendingEquip.tries > 16 then
|
yellowfive@61
|
524 -- too many tries, just give up (shouldn't happen but just to be safe)
|
yellowfive@57
|
525 _pendingEquip = nil
|
yellowfive@57
|
526 else
|
yellowfive@57
|
527 -- start over again, trying any items that could not be equipped in the previous pass (unique constraints)
|
yellowfive@57
|
528 Amr:EquipGearSet(_pendingEquip.spec)
|
yellowfive@57
|
529 end
|
yellowfive@57
|
530 end
|
yellowfive@57
|
531
|
yellowfive@57
|
532 -- equip the next slot in a pending equip
|
yellowfive@57
|
533 local function tryEquipNextItem()
|
yellowfive@57
|
534 if not _pendingEquip then return end
|
yellowfive@57
|
535
|
yellowfive@57
|
536 local item = _pendingEquip.itemsToEquip[_pendingEquip.nextSlot]
|
yellowfive@57
|
537
|
yellowfive@57
|
538 local bestItem = nil
|
yellowfive@57
|
539 local bestLink = nil
|
yellowfive@57
|
540 local bestDiff = 1000
|
yellowfive@57
|
541
|
yellowfive@57
|
542 -- find the best matching item
|
yellowfive@57
|
543
|
yellowfive@73
|
544 -- inventory
|
yellowfive@73
|
545 bestItem, bestDiff, bestLink = scanBagForItem(item, BACKPACK_CONTAINER, bestItem, bestDiff, bestLink)
|
yellowfive@73
|
546 for bagId = 1, NUM_BAG_SLOTS do
|
yellowfive@73
|
547 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
|
yellowfive@73
|
548 end
|
yellowfive@73
|
549
|
yellowfive@61
|
550 -- 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
|
551 for slotNum = 1, #Amr.SlotIds do
|
yellowfive@57
|
552 local slotId = Amr.SlotIds[slotNum]
|
yellowfive@61
|
553 if not _pendingEquip.doneSlots[slotId] then
|
yellowfive@61
|
554 local itemLink = GetInventoryItemLink("player", slotId)
|
yellowfive@61
|
555 if itemLink then
|
yellowfive@61
|
556 local invItem = Amr.ParseItemLink(itemLink)
|
yellowfive@61
|
557 if invItem ~= nil then
|
yellowfive@61
|
558 local diff = countItemDifferences(item, invItem)
|
yellowfive@61
|
559 if diff < bestDiff then
|
yellowfive@61
|
560 bestItem = { slot = slotId }
|
yellowfive@61
|
561 bestDiff = diff
|
yellowfive@61
|
562 bestLink = itemLink
|
yellowfive@61
|
563 end
|
yellowfive@57
|
564 end
|
yellowfive@57
|
565 end
|
yellowfive@57
|
566 end
|
yellowfive@57
|
567 end
|
yellowfive@57
|
568
|
yellowfive@57
|
569 -- bank
|
yellowfive@67
|
570 bestItem, bestDiff, bestLink = scanBagForItem(item, BANK_CONTAINER, bestItem, bestDiff, bestLink)
|
yellowfive@57
|
571 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
|
yellowfive@67
|
572 bestItem, bestDiff, bestLink = scanBagForItem(item, bagId, bestItem, bestDiff, bestLink)
|
yellowfive@57
|
573 end
|
yellowfive@57
|
574
|
yellowfive@57
|
575 ClearCursor()
|
yellowfive@57
|
576
|
yellowfive@57
|
577 if not bestItem then
|
yellowfive@57
|
578 -- stop if we can't find an item
|
yellowfive@57
|
579 Amr:Print(L.GearEquipErrorNotFound)
|
yellowfive@57
|
580 Amr:Print(L.GearEquipErrorNotFound2)
|
yellowfive@57
|
581 _pendingEquip = nil
|
yellowfive@57
|
582 return
|
yellowfive@57
|
583
|
yellowfive@71
|
584 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@57
|
585 -- find first empty bag slot
|
yellowfive@57
|
586 local invBag, invSlot = findFirstEmptyBagSlot()
|
yellowfive@57
|
587 if not invBag then
|
yellowfive@57
|
588 -- stop if bags are too full
|
yellowfive@57
|
589 Amr:Print(L.GearEquipErrorBagFull)
|
yellowfive@57
|
590 _pendingEquip = nil
|
yellowfive@57
|
591 return
|
yellowfive@57
|
592 end
|
yellowfive@57
|
593
|
yellowfive@57
|
594 -- move from bank to bag
|
yellowfive@57
|
595 PickupContainerItem(bestItem.bag, bestItem.slot)
|
yellowfive@57
|
596 PickupContainerItem(invBag, invSlot)
|
yellowfive@57
|
597
|
yellowfive@57
|
598 -- set flag so that when we clear cursor and release the item lock, we can respond to the event and continue
|
yellowfive@57
|
599 _waitingForItemLock = {
|
yellowfive@57
|
600 bagId = invBag,
|
yellowfive@57
|
601 slotId = invSlot
|
yellowfive@57
|
602 }
|
yellowfive@57
|
603
|
yellowfive@57
|
604 ClearCursor()
|
yellowfive@57
|
605
|
yellowfive@57
|
606 -- now we need to wait for game event to continue and try this item again after it is in our bag
|
yellowfive@57
|
607 return
|
yellowfive@57
|
608 else
|
yellowfive@59
|
609 if not Amr:CanEquip(bestItem.bag, bestItem.slot) then
|
yellowfive@57
|
610 -- if an item is not soulbound, then warn the user and quit
|
yellowfive@57
|
611 Amr:Print(L.GearEquipErrorSoulbound(bestLink))
|
yellowfive@57
|
612 _pendingEquip = nil
|
yellowfive@57
|
613 return
|
yellowfive@57
|
614 else
|
yellowfive@57
|
615 local slotId = _pendingEquip.nextSlot
|
yellowfive@57
|
616
|
yellowfive@57
|
617 -- an item in the player's bags or already equipped, equip it
|
yellowfive@57
|
618 _pendingEquip.bag = bestItem.bag
|
yellowfive@57
|
619 _pendingEquip.slot = bestItem.slot
|
yellowfive@57
|
620 _pendingEquip.destSlot = slotId
|
yellowfive@57
|
621
|
yellowfive@57
|
622 if bestItem.bag then
|
yellowfive@57
|
623 PickupContainerItem(bestItem.bag, bestItem.slot)
|
yellowfive@57
|
624 else
|
yellowfive@57
|
625 PickupInventoryItem(bestItem.slot)
|
yellowfive@57
|
626 end
|
yellowfive@57
|
627 PickupInventoryItem(slotId)
|
yellowfive@57
|
628 ClearCursor()
|
yellowfive@61
|
629
|
yellowfive@61
|
630 -- wait for game events to continue
|
yellowfive@57
|
631 end
|
yellowfive@57
|
632 end
|
yellowfive@57
|
633
|
yellowfive@57
|
634 end
|
yellowfive@57
|
635
|
yellowfive@89
|
636 local function removeNextItem()
|
yellowfive@89
|
637 if not _pendingRemove then return end
|
yellowfive@89
|
638
|
yellowfive@89
|
639 local list = _pendingRemove.slotsToRemove
|
yellowfive@89
|
640 local slot = list[#list - _pendingRemove.remaining + 1]
|
yellowfive@89
|
641
|
yellowfive@89
|
642 -- find first empty bag slot
|
yellowfive@89
|
643 local invBag, invSlot = findFirstEmptyBagSlot()
|
yellowfive@89
|
644 if not invBag then
|
yellowfive@89
|
645 -- stop if bags are too full
|
yellowfive@89
|
646 Amr:Print(L.GearEquipErrorBagFull)
|
yellowfive@89
|
647 _pendingRemove = nil
|
yellowfive@89
|
648 _pendingEquip = nil
|
yellowfive@89
|
649 return
|
yellowfive@89
|
650 end
|
yellowfive@89
|
651
|
yellowfive@89
|
652 PickupInventoryItem(slot)
|
yellowfive@89
|
653 PickupContainerItem(invBag, invSlot)
|
yellowfive@89
|
654
|
yellowfive@89
|
655 -- set flag so that when we clear cursor and release the item lock, we can respond to the event and continue
|
yellowfive@89
|
656 _waitingForItemLock = {
|
yellowfive@89
|
657 bagId = invBag,
|
yellowfive@89
|
658 slotId = invSlot,
|
yellowfive@89
|
659 isRemove = true
|
yellowfive@89
|
660 }
|
yellowfive@89
|
661
|
yellowfive@89
|
662 ClearCursor()
|
yellowfive@89
|
663 end
|
yellowfive@89
|
664
|
yellowfive@57
|
665 local function onItemUnlocked(bagId, slotId)
|
yellowfive@89
|
666
|
yellowfive@57
|
667 if _waitingForItemLock then
|
yellowfive@89
|
668 -- waiting on a move from bank to bags to complete, or waiting on removing an item to complete, just continue as normal afterwards
|
yellowfive@57
|
669 if bagId == _waitingForItemLock.bagId and slotId == _waitingForItemLock.slotId then
|
yellowfive@89
|
670 local isremove = _waitingForItemLock.isRemove
|
yellowfive@57
|
671 _waitingForItemLock = nil
|
yellowfive@89
|
672
|
yellowfive@89
|
673 if isremove then
|
yellowfive@89
|
674 _pendingRemove.remaining = _pendingRemove.remaining - 1
|
yellowfive@89
|
675 if _pendingRemove.remaining > 0 then
|
yellowfive@89
|
676 removeNextItem()
|
yellowfive@89
|
677 else
|
yellowfive@89
|
678 -- we have removed all items that we want to remove, now do the equip
|
yellowfive@89
|
679 _pendingRemove = nil
|
yellowfive@89
|
680 tryEquipNextItem()
|
yellowfive@89
|
681 end
|
yellowfive@89
|
682 else
|
yellowfive@89
|
683 tryEquipNextItem()
|
yellowfive@89
|
684 end
|
yellowfive@57
|
685 end
|
yellowfive@57
|
686
|
yellowfive@57
|
687 elseif _pendingEquip and _pendingEquip.destSlot then
|
yellowfive@57
|
688 -- waiting on an item swap to complete successfully so that we can go on to the next item
|
yellowfive@57
|
689
|
yellowfive@57
|
690 -- inventory slot we're swapping to is still locked, can't continue yet
|
yellowfive@57
|
691 if IsInventoryItemLocked(_pendingEquip.destSlot) then return end
|
yellowfive@57
|
692
|
yellowfive@57
|
693 if _pendingEquip.bag then
|
yellowfive@57
|
694 local _, _, locked = GetContainerItemInfo(_pendingEquip.bag, _pendingEquip.slot)
|
yellowfive@57
|
695 -- the bag slot we're swapping from is still locked, can't continue yet
|
yellowfive@57
|
696 if locked then return end
|
yellowfive@57
|
697 else
|
yellowfive@57
|
698 -- inventory slot we're swapping from is still locked, can't continue yet
|
yellowfive@57
|
699 if IsInventoryItemLocked(_pendingEquip.slot) then return end
|
yellowfive@57
|
700 end
|
yellowfive@57
|
701
|
yellowfive@83
|
702 -- move on to the next item, this item is done or could not be swapped
|
yellowfive@83
|
703
|
yellowfive@83
|
704 local item = _pendingEquip.itemsToEquip[_pendingEquip.destSlot]
|
yellowfive@83
|
705 local itemLink = GetInventoryItemLink("player", _pendingEquip.destSlot)
|
yellowfive@83
|
706 if itemLink then
|
yellowfive@83
|
707 local invItem = Amr.ParseItemLink(itemLink)
|
yellowfive@83
|
708 if invItem ~= nil then
|
yellowfive@83
|
709 local diff = countItemDifferences(item, invItem)
|
yellowfive@83
|
710 if diff == 0 then
|
yellowfive@83
|
711 _pendingEquip.doneSlots[_pendingEquip.destSlot] = true
|
yellowfive@83
|
712 end
|
yellowfive@83
|
713 end
|
yellowfive@83
|
714 end
|
yellowfive@83
|
715
|
yellowfive@57
|
716 _pendingEquip.itemsToEquip[_pendingEquip.destSlot] = nil
|
yellowfive@57
|
717 _pendingEquip.destSlot = nil
|
yellowfive@57
|
718 _pendingEquip.bag = nil
|
yellowfive@57
|
719 _pendingEquip.slot = nil
|
yellowfive@57
|
720
|
yellowfive@57
|
721 _pendingEquip.remaining = _pendingEquip.remaining - 1
|
yellowfive@57
|
722 if _pendingEquip.remaining > 0 then
|
yellowfive@57
|
723 for slotId, item in pairs(_pendingEquip.itemsToEquip) do
|
yellowfive@57
|
724 _pendingEquip.nextSlot = slotId
|
yellowfive@57
|
725 break
|
yellowfive@57
|
726 end
|
yellowfive@57
|
727 tryEquipNextItem()
|
yellowfive@57
|
728 else
|
yellowfive@57
|
729 finishEquipGearSet()
|
yellowfive@57
|
730 end
|
yellowfive@57
|
731
|
yellowfive@57
|
732 end
|
yellowfive@57
|
733 end
|
yellowfive@57
|
734
|
yellowfive@57
|
735 local function startEquipGearSet(spec)
|
yellowfive@57
|
736
|
yellowfive@57
|
737 local gear = Amr.db.char.GearSets[spec]
|
yellowfive@57
|
738 if not gear then
|
yellowfive@57
|
739 Amr:Print(L.GearEquipErrorEmpty)
|
yellowfive@57
|
740 return
|
yellowfive@57
|
741 end
|
yellowfive@57
|
742
|
yellowfive@57
|
743 local player = Amr:ExportCharacter()
|
yellowfive@57
|
744
|
yellowfive@57
|
745 local itemsToEquip = {}
|
yellowfive@57
|
746 local remaining = 0
|
yellowfive@57
|
747 local usedItems = {}
|
yellowfive@57
|
748 local firstSlot = nil
|
yellowfive@57
|
749
|
yellowfive@57
|
750 -- check for items that need to be equipped
|
yellowfive@57
|
751 for slotNum = 1, #Amr.SlotIds do
|
yellowfive@57
|
752 local slotId = Amr.SlotIds[slotNum]
|
yellowfive@57
|
753
|
yellowfive@57
|
754 local old = player.Equipped[spec][slotId]
|
yellowfive@57
|
755 old = Amr.ParseItemLink(old)
|
yellowfive@57
|
756
|
yellowfive@57
|
757 local new = gear[slotId]
|
yellowfive@69
|
758 if new then
|
yellowfive@69
|
759 local diff = countItemDifferences(old, new)
|
yellowfive@69
|
760 if diff < 1000 then
|
yellowfive@69
|
761 -- same item, see if inventory has one that is closer (e.g. a duplicate item with correct enchants/gems)
|
yellowfive@69
|
762 local bestLink, bestItem, bestDiff = Amr:FindMatchingItem(new, player, usedItems)
|
yellowfive@69
|
763 if bestDiff and bestDiff < diff then
|
yellowfive@69
|
764 itemsToEquip[slotId] = new
|
yellowfive@69
|
765 remaining = remaining + 1
|
yellowfive@69
|
766 end
|
yellowfive@69
|
767 else
|
yellowfive@57
|
768 itemsToEquip[slotId] = new
|
yellowfive@57
|
769 remaining = remaining + 1
|
yellowfive@57
|
770 end
|
yellowfive@57
|
771 end
|
yellowfive@57
|
772 end
|
yellowfive@57
|
773
|
yellowfive@57
|
774 if remaining > 0 then
|
yellowfive@89
|
775 -- if this is not our first try, then remove weapons before starting
|
yellowfive@89
|
776 local toRemove = {}
|
yellowfive@89
|
777 local removesRemaining = 0
|
yellowfive@89
|
778 if _pendingEquip and _pendingEquip.tries > 0 then
|
yellowfive@89
|
779 for slotId, item in pairs(itemsToEquip) do
|
yellowfive@89
|
780 if slotId == 16 or slotId == 17 then
|
yellowfive@89
|
781 table.insert(toRemove, slotId)
|
yellowfive@89
|
782 removesRemaining = removesRemaining + 1
|
yellowfive@89
|
783 end
|
yellowfive@89
|
784 end
|
yellowfive@89
|
785 end
|
yellowfive@89
|
786
|
yellowfive@57
|
787 _pendingEquip = {
|
yellowfive@57
|
788 tries = _pendingEquip and _pendingEquip.spec == spec and _pendingEquip.tries or 0,
|
yellowfive@57
|
789 spec = spec,
|
yellowfive@57
|
790 itemsToEquip = itemsToEquip,
|
yellowfive@57
|
791 remaining = remaining,
|
yellowfive@73
|
792 doneSlots = _pendingEquip and _pendingEquip.spec == spec and _pendingEquip.doneSlots or {},
|
yellowfive@57
|
793 nextSlot = firstSlot
|
yellowfive@57
|
794 }
|
yellowfive@57
|
795
|
yellowfive@57
|
796 -- starting item
|
yellowfive@57
|
797 for slotId, item in pairs(_pendingEquip.itemsToEquip) do
|
yellowfive@57
|
798 _pendingEquip.nextSlot = slotId
|
yellowfive@57
|
799 break
|
yellowfive@57
|
800 end
|
yellowfive@57
|
801
|
yellowfive@89
|
802 if removesRemaining > 0 then
|
yellowfive@89
|
803 _pendingRemove = {
|
yellowfive@89
|
804 slotsToRemove = toRemove,
|
yellowfive@89
|
805 remaining = removesRemaining
|
yellowfive@89
|
806 }
|
yellowfive@89
|
807 removeNextItem()
|
yellowfive@89
|
808 else
|
yellowfive@89
|
809 tryEquipNextItem()
|
yellowfive@89
|
810 end
|
yellowfive@57
|
811 else
|
yellowfive@57
|
812 _pendingEquip = nil
|
yellowfive@89
|
813 onEquipGearSetComplete()
|
yellowfive@57
|
814 end
|
yellowfive@57
|
815 end
|
yellowfive@57
|
816
|
yellowfive@57
|
817 local function onActiveTalentGroupChanged()
|
yellowfive@81
|
818
|
yellowfive@57
|
819 local auto = Amr.db.profile.options.autoGear
|
yellowfive@81
|
820 local currentSpec = GetSpecialization()
|
yellowfive@57
|
821
|
yellowfive@57
|
822 if currentSpec == _waitingForSpec or auto then
|
yellowfive@57
|
823 -- spec is what we want, now equip the gear
|
yellowfive@57
|
824 startEquipGearSet(currentSpec)
|
yellowfive@57
|
825 end
|
yellowfive@57
|
826
|
yellowfive@57
|
827 _waitingForSpec = 0
|
yellowfive@57
|
828 end
|
yellowfive@57
|
829
|
yellowfive@81
|
830 -- activate the specified spec and then equip the saved gear set
|
yellowfive@57
|
831 function Amr:EquipGearSet(spec)
|
yellowfive@57
|
832
|
yellowfive@81
|
833 -- if no argument, then cycle spec
|
yellowfive@57
|
834 if not spec then
|
yellowfive@81
|
835 spec = GetSpecialization() + 1
|
yellowfive@57
|
836 end
|
yellowfive@81
|
837
|
yellowfive@57
|
838 -- allow some flexibility in the arguments
|
yellowfive@81
|
839 if spec == "1" or spec == "2" or spec == "3" or spec == "4" then spec = tonumber(spec) end
|
yellowfive@81
|
840
|
yellowfive@81
|
841 local specId = GetSpecializationInfo(spec)
|
yellowfive@81
|
842 if not specId then spec = 1 end
|
yellowfive@57
|
843
|
yellowfive@57
|
844 if UnitAffectingCombat("player") then
|
yellowfive@57
|
845 Amr:Print(L.GearEquipErrorCombat)
|
yellowfive@57
|
846 return
|
yellowfive@57
|
847 end
|
yellowfive@57
|
848
|
yellowfive@57
|
849 _waitingForSpec = spec
|
yellowfive@57
|
850
|
yellowfive@81
|
851 local currentSpec = GetSpecialization()
|
yellowfive@57
|
852 if currentSpec ~= spec then
|
yellowfive@81
|
853 SetSpecialization(spec)
|
yellowfive@57
|
854 else
|
yellowfive@57
|
855 onActiveTalentGroupChanged()
|
yellowfive@57
|
856 end
|
yellowfive@57
|
857 end
|
yellowfive@57
|
858
|
yellowfive@57
|
859 -- moves any gear in bags to the bank if not part of main or off spec gear set
|
yellowfive@57
|
860 function Amr:CleanBags()
|
yellowfive@57
|
861 -- TODO: implement
|
yellowfive@57
|
862 end
|
yellowfive@57
|
863
|
yellowfive@81
|
864 --[[
|
yellowfive@81
|
865 local function testfunc(message)
|
yellowfive@81
|
866 print(strsub(message, 13))
|
yellowfive@81
|
867 end
|
yellowfive@81
|
868 ]]
|
yellowfive@81
|
869
|
yellowfive@57
|
870 function Amr:InitializeGear()
|
yellowfive@87
|
871 Amr:AddEventHandler("ACTIVE_TALENT_GROUP_CHANGED", onActiveTalentGroupChanged)
|
yellowfive@57
|
872
|
yellowfive@81
|
873 --Amr:AddEventHandler("CHAT_MSG_CHANNEL", testfunc)
|
yellowfive@81
|
874
|
yellowfive@57
|
875 Amr:AddEventHandler("UNIT_INVENTORY_CHANGED", function(unitID)
|
yellowfive@57
|
876 if unitID and unitID ~= "player" then return end
|
yellowfive@57
|
877 Amr:RefreshGearTab()
|
yellowfive@57
|
878 end)
|
yellowfive@57
|
879
|
yellowfive@57
|
880 Amr:AddEventHandler("ITEM_UNLOCKED", onItemUnlocked)
|
yellowfive@122
|
881 end
|