yellowfive@161
|
1 local Amr = LibStub("AceAddon-3.0"):GetAddon("AskMrRobot")
|
yellowfive@161
|
2 local L = LibStub("AceLocale-3.0"):GetLocale("AskMrRobot", true)
|
yellowfive@161
|
3 local AceGUI = LibStub("AceGUI-3.0")
|
yellowfive@161
|
4
|
yellowfive@161
|
5 local _frameJunk
|
yellowfive@161
|
6 local _lblAction
|
yellowfive@161
|
7 local _lblBank
|
yellowfive@161
|
8 local _btnBank
|
yellowfive@161
|
9 local _panelContent
|
yellowfive@161
|
10
|
yellowfive@161
|
11 local _canDisenchant = false
|
yellowfive@161
|
12 local _isScrapOpen = false
|
yellowfive@161
|
13 local _isMerchantOpen = false
|
yellowfive@161
|
14 local _isBankOpen = false
|
yellowfive@161
|
15
|
yellowfive@161
|
16 --
|
yellowfive@161
|
17 -- Scan a bag for the specified item, returning the first exact match found
|
yellowfive@161
|
18 --
|
yellowfive@161
|
19 local function scanBag(bagId, matchItem, usedItems)
|
yellowfive@161
|
20
|
yellowfive@161
|
21 local numSlots = GetContainerNumSlots(bagId)
|
yellowfive@161
|
22 local loc = ItemLocation.CreateEmpty()
|
yellowfive@161
|
23
|
yellowfive@161
|
24 if not usedItems[bagId] then
|
yellowfive@161
|
25 usedItems[bagId] = {}
|
yellowfive@161
|
26 end
|
yellowfive@161
|
27
|
yellowfive@163
|
28 local bestMatchDiffs = 1000000
|
yellowfive@163
|
29 local bestMatch = nil
|
yellowfive@163
|
30 local threshold
|
yellowfive@163
|
31
|
yellowfive@161
|
32 for slotId = 1, numSlots do
|
yellowfive@161
|
33 if not usedItems[bagId][slotId] then
|
yellowfive@161
|
34 local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
|
yellowfive@161
|
35 if itemLink ~= nil then
|
yellowfive@161
|
36 local itemData = Amr.Serializer.ParseItemLink(itemLink)
|
yellowfive@161
|
37 if itemData ~= nil then
|
yellowfive@161
|
38 -- see if this is an azerite item and read azerite power ids
|
yellowfive@161
|
39 loc:SetBagAndSlot(bagId, slotId)
|
yellowfive@161
|
40 if C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItem(loc) then
|
yellowfive@161
|
41 local powers = Amr.ReadAzeritePowers(loc)
|
yellowfive@161
|
42 if powers then
|
yellowfive@161
|
43 itemData.azerite = powers
|
yellowfive@161
|
44 end
|
yellowfive@161
|
45 end
|
yellowfive@161
|
46
|
yellowfive@161
|
47 -- see if it matches
|
yellowfive@163
|
48 local diffs = Amr.CountItemDifferences(matchItem, itemData)
|
yellowfive@163
|
49 if diffs == 0 then
|
yellowfive@161
|
50 usedItems[bagId][slotId] = true
|
yellowfive@161
|
51 itemData.bagId = bagId
|
yellowfive@161
|
52 itemData.slotId = slotId
|
yellowfive@161
|
53 return itemData
|
yellowfive@163
|
54 elseif diffs < 10000 then
|
yellowfive@163
|
55 if itemData.azerite and #itemData.azerite > 0 then
|
yellowfive@163
|
56 threshold = 100
|
yellowfive@163
|
57 else
|
yellowfive@163
|
58 threshold = 10000
|
yellowfive@163
|
59 end
|
yellowfive@163
|
60 if diffs < threshold and diffs < bestMatchDiffs then
|
yellowfive@163
|
61 -- closest match we could find
|
yellowfive@163
|
62 bestMatchDiffs = diffs
|
yellowfive@163
|
63 itemData.bagId = bagId
|
yellowfive@163
|
64 itemData.slotId = slotId
|
yellowfive@163
|
65 bestMatch = itemData
|
yellowfive@163
|
66 end
|
yellowfive@161
|
67 end
|
yellowfive@161
|
68 end
|
yellowfive@161
|
69 end
|
yellowfive@161
|
70 end
|
yellowfive@161
|
71 end
|
yellowfive@163
|
72
|
yellowfive@163
|
73 -- if we couldn't get a perfect match, take the best match that might have some small differences like
|
yellowfive@163
|
74 -- an old school enchant or upgrade ID that didn't load
|
yellowfive@163
|
75 if bestMatch then
|
yellowfive@163
|
76 usedItems[bestMatch.bagId][bestMatch.slotId] = true
|
yellowfive@163
|
77 return bestMatch
|
yellowfive@163
|
78 else
|
yellowfive@163
|
79 return nil
|
yellowfive@163
|
80 end
|
yellowfive@161
|
81 end
|
yellowfive@161
|
82
|
yellowfive@161
|
83 --
|
yellowfive@161
|
84 -- Find a matching item in the player's bags
|
yellowfive@161
|
85 --
|
yellowfive@161
|
86 local function findMatchingBagItem(item, usedItems)
|
yellowfive@161
|
87
|
yellowfive@161
|
88 local matchItem = scanBag(BACKPACK_CONTAINER, item, usedItems) -- backpack
|
yellowfive@161
|
89 if not matchItem then
|
yellowfive@161
|
90 for bagId = 1, NUM_BAG_SLOTS do
|
yellowfive@161
|
91 matchItem = scanBag(bagId, item, usedItems)
|
yellowfive@161
|
92 if matchItem then break end
|
yellowfive@161
|
93 end
|
yellowfive@161
|
94 end
|
yellowfive@161
|
95
|
yellowfive@161
|
96 return matchItem
|
yellowfive@161
|
97 end
|
yellowfive@161
|
98
|
yellowfive@161
|
99
|
yellowfive@161
|
100 --
|
yellowfive@161
|
101 -- item actions
|
yellowfive@161
|
102 --
|
yellowfive@161
|
103 local _deSpellName = GetSpellInfo(13262);
|
yellowfive@161
|
104 local _deMacro = "/stopmacro [combat][btn:2]\n/stopcasting\n/cast %s\n/use %s %s";
|
yellowfive@161
|
105
|
yellowfive@161
|
106 local function onItemPreClick(widget)
|
yellowfive@161
|
107
|
yellowfive@161
|
108 local item = widget:GetUserData("itemData")
|
yellowfive@161
|
109
|
yellowfive@161
|
110 if item and _canDisenchant and (not _isScrapOpen and not _isMerchantOpen) then
|
yellowfive@161
|
111 -- only way i can find to disenchant and item on click is to call a macro, gross but works
|
yellowfive@161
|
112 local matchItem = findMatchingBagItem(item, {})
|
yellowfive@161
|
113 if matchItem then
|
yellowfive@161
|
114 widget:SetMacroText(_deMacro:format(_deSpellName, matchItem.bagId, matchItem.slotId))
|
yellowfive@161
|
115 else
|
yellowfive@161
|
116 widget:SetMacroText(nil)
|
yellowfive@161
|
117 Amr:Print(L.JunkItemNotFound)
|
yellowfive@161
|
118 end
|
yellowfive@161
|
119 else
|
yellowfive@161
|
120 widget:SetMacroText(nil)
|
yellowfive@161
|
121 end
|
yellowfive@161
|
122 end
|
yellowfive@161
|
123
|
yellowfive@161
|
124 local function onItemClick(widget)
|
yellowfive@161
|
125
|
yellowfive@161
|
126 local item = widget:GetUserData("itemData")
|
yellowfive@161
|
127 if not item then return end
|
yellowfive@161
|
128
|
yellowfive@161
|
129 local action = nil
|
yellowfive@161
|
130 if _isScrapOpen then
|
yellowfive@161
|
131 action = "scrap"
|
yellowfive@161
|
132 elseif _isMerchantOpen then
|
yellowfive@161
|
133 action = "sell"
|
yellowfive@161
|
134 elseif _canDisenchant then
|
yellowfive@161
|
135 action = "disenchant"
|
yellowfive@161
|
136 end
|
yellowfive@161
|
137
|
yellowfive@161
|
138 if not action then return end
|
yellowfive@161
|
139
|
yellowfive@161
|
140 local matchItem = findMatchingBagItem(item, {})
|
yellowfive@161
|
141 if matchItem then
|
yellowfive@161
|
142 if action == "scrap" then
|
yellowfive@161
|
143 UseContainerItem(matchItem.bagId, matchItem.slotId)
|
yellowfive@161
|
144 elseif action == "sell" then
|
yellowfive@161
|
145 UseContainerItem(matchItem.bagId, matchItem.slotId)
|
yellowfive@161
|
146 end
|
yellowfive@161
|
147
|
yellowfive@161
|
148 -- note for disenchant, the macro has handled the action, this will simply remove the item from the list
|
yellowfive@161
|
149
|
yellowfive@161
|
150 -- re-render the list with this item removed;
|
yellowfive@161
|
151 -- AceGUI doesn't give a good way to remove a ui element from a container and re-render,
|
yellowfive@161
|
152 -- so we sort of hack it and modify the collection of children directly,
|
yellowfive@161
|
153 -- avoids the expensive logic of finding and matching all the items when the list changes as a user sells stuff
|
yellowfive@161
|
154 local scroll = widget.parent.parent
|
yellowfive@161
|
155 local newChildren = {}
|
yellowfive@161
|
156 for i = 1, #scroll.children do
|
yellowfive@161
|
157 local child = scroll.children[i]
|
yellowfive@161
|
158 if child ~= widget.parent then
|
yellowfive@161
|
159 table.insert(newChildren, child)
|
yellowfive@161
|
160 end
|
yellowfive@161
|
161 end
|
yellowfive@161
|
162 scroll.children = newChildren
|
yellowfive@161
|
163
|
yellowfive@161
|
164 -- dispose the item just removed, then re-render the list
|
yellowfive@161
|
165 widget.parent:Release()
|
yellowfive@161
|
166 widget.parent.parent:DoLayout()
|
yellowfive@161
|
167 else
|
yellowfive@161
|
168 Amr:Print(L.JunkItemNotFound)
|
yellowfive@161
|
169 end
|
yellowfive@161
|
170 end
|
yellowfive@161
|
171
|
yellowfive@161
|
172
|
yellowfive@161
|
173 --
|
yellowfive@161
|
174 -- bank withdraw stuff
|
yellowfive@161
|
175 --
|
yellowfive@161
|
176 local _bankUsedBagSlots = nil
|
yellowfive@161
|
177 local finishBankWithdraw
|
yellowfive@161
|
178 local doBankWithdraw
|
yellowfive@161
|
179
|
yellowfive@161
|
180 finishBankWithdraw = function()
|
yellowfive@161
|
181
|
yellowfive@161
|
182 local done = true
|
yellowfive@161
|
183
|
yellowfive@161
|
184 if _isBankOpen and _bankUsedBagSlots then
|
yellowfive@161
|
185 for bagId,v in pairs(_bankUsedBagSlots) do
|
yellowfive@161
|
186 for slotId,v in pairs(v) do
|
yellowfive@161
|
187 local _, _, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
|
yellowfive@161
|
188 if not itemLink then
|
yellowfive@161
|
189 done = false
|
yellowfive@161
|
190 break
|
yellowfive@161
|
191 end
|
yellowfive@161
|
192 end
|
yellowfive@161
|
193 if not done then break end
|
yellowfive@161
|
194 end
|
yellowfive@161
|
195 end
|
yellowfive@161
|
196
|
yellowfive@161
|
197 if not done then
|
yellowfive@161
|
198 -- wait a second and try again
|
yellowfive@161
|
199 Amr.Wait(1, function()
|
yellowfive@161
|
200 doBankWithdraw()
|
yellowfive@161
|
201 end)
|
yellowfive@161
|
202 else
|
yellowfive@161
|
203
|
yellowfive@161
|
204 -- reset state
|
yellowfive@161
|
205 _bankUsedBagSlots = nil
|
yellowfive@161
|
206 _btnBank:SetDisabled(not _isBankOpen)
|
yellowfive@161
|
207
|
yellowfive@161
|
208 -- re-render the junk list
|
yellowfive@161
|
209 Amr:RefreshJunkUi()
|
yellowfive@161
|
210 end
|
yellowfive@161
|
211 end
|
yellowfive@161
|
212
|
yellowfive@161
|
213 doBankWithdraw = function()
|
yellowfive@161
|
214 if not _isBankOpen then return end
|
yellowfive@161
|
215
|
yellowfive@161
|
216 local data = Amr.db.char.JunkData
|
yellowfive@161
|
217 if not data.Junk then return end
|
yellowfive@161
|
218
|
yellowfive@161
|
219 -- disable button while processing
|
yellowfive@161
|
220 _btnBank:SetDisabled(true)
|
yellowfive@161
|
221
|
yellowfive@161
|
222 local bagList = {}
|
yellowfive@161
|
223 table.insert(bagList, BANK_CONTAINER)
|
yellowfive@161
|
224 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
|
yellowfive@161
|
225 table.insert(bagList, bagId)
|
yellowfive@161
|
226 end
|
yellowfive@161
|
227
|
yellowfive@161
|
228 local usedItems = {}
|
yellowfive@161
|
229 _bankUsedBagSlots = {}
|
yellowfive@161
|
230
|
yellowfive@161
|
231 for i,item in ipairs(data.Junk) do
|
yellowfive@161
|
232 -- stop immediately if the bank is closed
|
yellowfive@161
|
233 if not _isBankOpen then
|
yellowfive@161
|
234 finishBankWithdraw()
|
yellowfive@161
|
235 return
|
yellowfive@161
|
236 end
|
yellowfive@161
|
237
|
yellowfive@161
|
238 -- check if already in bags
|
yellowfive@161
|
239 local matchItem = findMatchingBagItem(item, usedItems)
|
yellowfive@161
|
240 if not matchItem then
|
yellowfive@161
|
241 -- find it in the bank
|
yellowfive@161
|
242 for j = 1, #bagList do
|
yellowfive@161
|
243 matchItem = scanBag(bagList[j], item, usedItems)
|
yellowfive@161
|
244 if matchItem then break end
|
yellowfive@161
|
245 end
|
yellowfive@161
|
246 else
|
yellowfive@161
|
247 matchItem = nil
|
yellowfive@161
|
248 end
|
yellowfive@161
|
249
|
yellowfive@161
|
250 if matchItem then
|
yellowfive@161
|
251 -- move it to the player's bags if there is space
|
yellowfive@161
|
252 local bagId, slotId = Amr.FindFirstEmptyBagSlot(_bankUsedBagSlots)
|
yellowfive@161
|
253 if bagId then
|
yellowfive@161
|
254 UseContainerItem(matchItem.bagId, matchItem.slotId)
|
yellowfive@161
|
255 else
|
yellowfive@161
|
256 -- no more empty bag slots
|
yellowfive@161
|
257 break
|
yellowfive@161
|
258 end
|
yellowfive@161
|
259 end
|
yellowfive@161
|
260 end
|
yellowfive@161
|
261
|
yellowfive@161
|
262 -- wait a second and see if all the moves actually finished
|
yellowfive@161
|
263 Amr.Wait(1, function()
|
yellowfive@161
|
264 finishBankWithdraw()
|
yellowfive@161
|
265 end)
|
yellowfive@161
|
266 end
|
yellowfive@161
|
267
|
yellowfive@161
|
268 local function onBankClick()
|
yellowfive@161
|
269 if not _frameJunk or not _isBankOpen then return end
|
yellowfive@161
|
270
|
yellowfive@161
|
271 doBankWithdraw()
|
yellowfive@161
|
272 end
|
yellowfive@161
|
273
|
yellowfive@161
|
274
|
yellowfive@161
|
275 local function onJunkFrameClose(widget)
|
yellowfive@161
|
276 AceGUI:Release(widget)
|
yellowfive@161
|
277 _frameJunk = nil
|
yellowfive@161
|
278 _lblAction = nil
|
yellowfive@161
|
279 _lblBank = nil
|
yellowfive@161
|
280 _btnBank = nil
|
yellowfive@161
|
281 _panelContent = nil
|
yellowfive@161
|
282 end
|
yellowfive@161
|
283
|
yellowfive@161
|
284 function Amr:HideJunkWindow()
|
yellowfive@161
|
285 if not _frameJunk then return end
|
yellowfive@161
|
286 _frameJunk:Hide()
|
yellowfive@161
|
287 end
|
yellowfive@161
|
288
|
yellowfive@161
|
289 function Amr:ShowJunkWindow()
|
yellowfive@161
|
290
|
yellowfive@179
|
291 if InCombatLockdown() then return end
|
yellowfive@179
|
292
|
yellowfive@161
|
293 if not _frameJunk then
|
yellowfive@161
|
294 _frameJunk = AceGUI:Create("AmrUiFrame")
|
yellowfive@161
|
295 _frameJunk:SetStatusTable(Amr.db.profile.junkWindow) -- window position is remembered in db
|
yellowfive@161
|
296 _frameJunk:SetCallback("OnClose", onJunkFrameClose)
|
yellowfive@161
|
297 _frameJunk:SetLayout("None")
|
yellowfive@161
|
298 _frameJunk:SetWidth(400)
|
yellowfive@161
|
299 _frameJunk:SetHeight(700)
|
yellowfive@161
|
300 _frameJunk:SetBorderColor(Amr.Colors.BorderBlue)
|
yellowfive@161
|
301 _frameJunk:SetBackgroundColor(Amr.Colors.Bg)
|
yellowfive@161
|
302
|
yellowfive@161
|
303 if Amr.db.profile.options.uiScale ~= 1 then
|
yellowfive@161
|
304 local scale = tonumber(Amr.db.profile.options.uiScale)
|
yellowfive@161
|
305 _frameJunk:SetScale(scale)
|
yellowfive@161
|
306 end
|
yellowfive@161
|
307
|
yellowfive@161
|
308 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
309 _frameJunk:AddChild(lbl)
|
yellowfive@161
|
310 lbl:SetWidth(300)
|
yellowfive@161
|
311 lbl:SetFont(Amr.CreateFont("Bold", 28, Amr.Colors.White))
|
yellowfive@161
|
312 lbl:SetText(L.JunkTitle)
|
yellowfive@161
|
313 lbl:SetWordWrap(false)
|
yellowfive@161
|
314 lbl:SetJustifyH("CENTER")
|
yellowfive@161
|
315 lbl:SetPoint("TOP", _frameJunk.content, "TOP", 0, 30)
|
yellowfive@161
|
316 lbl:SetCallback("OnMouseDown", function(widget) _frameJunk:StartMove() end)
|
yellowfive@161
|
317 lbl:SetCallback("OnMouseUp", function(widget) _frameJunk:EndMove() end)
|
yellowfive@161
|
318
|
yellowfive@161
|
319 _lblAction = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
320 _frameJunk:AddChild(_lblAction)
|
yellowfive@161
|
321 _lblAction:SetWidth(380)
|
yellowfive@161
|
322 _lblAction:SetFont(Amr.CreateFont("Regular", 14, Amr.Colors.TextTan))
|
yellowfive@161
|
323 _lblAction:SetText(" ")
|
yellowfive@161
|
324 _lblAction:SetWordWrap(false)
|
yellowfive@161
|
325 _lblAction:SetPoint("TOPLEFT", _frameJunk.content, "TOPLEFT", 0, -10)
|
yellowfive@161
|
326
|
yellowfive@161
|
327 _btnBank = AceGUI:Create("AmrUiButton")
|
yellowfive@161
|
328 _frameJunk:AddChild(_btnBank)
|
yellowfive@161
|
329 _btnBank:SetText(L.JunkButtonBank)
|
yellowfive@161
|
330 _btnBank:SetBackgroundColor(Amr.Colors.Green)
|
yellowfive@161
|
331 _btnBank:SetFont(Amr.CreateFont("Bold", 14, Amr.Colors.White))
|
yellowfive@161
|
332 _btnBank:SetWidth(180)
|
yellowfive@161
|
333 _btnBank:SetHeight(26)
|
yellowfive@161
|
334 _btnBank:SetDisabled(true)
|
yellowfive@161
|
335 _btnBank:SetCallback("OnClick", onBankClick)
|
yellowfive@161
|
336 _btnBank:SetPoint("BOTTOMLEFT", _frameJunk.content, "BOTTOMLEFT")
|
yellowfive@161
|
337
|
yellowfive@161
|
338 _lblBank = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
339 _frameJunk:AddChild(_lblBank)
|
yellowfive@161
|
340 _lblBank:SetWidth(380)
|
yellowfive@161
|
341 _lblBank:SetFont(Amr.CreateFont("Bold", 15, Amr.Colors.TextHeaderActive))
|
yellowfive@161
|
342 _lblBank:SetText(L.JunkBankText(0))
|
yellowfive@161
|
343 _lblBank:SetPoint("BOTTOMLEFT", _btnBank.frame, "TOPLEFT", 0, 10)
|
yellowfive@161
|
344
|
yellowfive@161
|
345 local line = AceGUI:Create("AmrUiPanel")
|
yellowfive@161
|
346 _frameJunk:AddChild(line)
|
yellowfive@161
|
347 line:SetHeight(1)
|
yellowfive@161
|
348 line:SetBackgroundColor(Amr.Colors.White)
|
yellowfive@161
|
349 line:SetPoint("TOPLEFT", _frameJunk.content, "TOPLEFT", 0, -30)
|
yellowfive@161
|
350 line:SetPoint("TOPRIGHT", _frameJunk.content, "TOPRIGHT", 0, -30)
|
yellowfive@161
|
351
|
yellowfive@161
|
352 line = AceGUI:Create("AmrUiPanel")
|
yellowfive@161
|
353 _frameJunk:AddChild(line)
|
yellowfive@161
|
354 line:SetHeight(1)
|
yellowfive@161
|
355 line:SetBackgroundColor(Amr.Colors.White)
|
yellowfive@161
|
356 line:SetPoint("TOPLEFT", _frameJunk.content, "BOTTOMLEFT", 0, 60)
|
yellowfive@161
|
357 line:SetPoint("TOPRIGHT", _frameJunk.content, "BOTTOMRIGHT", 0, 60)
|
yellowfive@161
|
358
|
yellowfive@161
|
359 _panelContent = AceGUI:Create("AmrUiPanel")
|
yellowfive@161
|
360 _panelContent:SetLayout("None")
|
yellowfive@161
|
361 _panelContent:SetTransparent()
|
yellowfive@161
|
362 _frameJunk:AddChild(_panelContent)
|
yellowfive@161
|
363 _panelContent:SetPoint("TOPLEFT", _frameJunk.content, "TOPLEFT", 0, -31)
|
yellowfive@161
|
364 _panelContent:SetPoint("BOTTOMRIGHT", _frameJunk.content, "BOTTOMRIGHT", 0, 60)
|
yellowfive@161
|
365
|
yellowfive@161
|
366
|
yellowfive@161
|
367 Amr:RefreshJunkUi()
|
yellowfive@161
|
368 else
|
yellowfive@161
|
369 _frameJunk:Show()
|
yellowfive@161
|
370 Amr:RefreshJunkUi()
|
yellowfive@161
|
371 end
|
yellowfive@161
|
372
|
yellowfive@161
|
373 _frameJunk:Raise()
|
yellowfive@161
|
374 end
|
yellowfive@161
|
375
|
yellowfive@161
|
376 local function canDisenchant()
|
yellowfive@161
|
377
|
yellowfive@161
|
378 local prof1, prof2 = GetProfessions();
|
yellowfive@161
|
379 local profs = {}
|
yellowfive@161
|
380 table.insert(profs, prof1)
|
yellowfive@161
|
381 table.insert(profs, prof2)
|
yellowfive@161
|
382 for i,prof in ipairs(profs) do
|
yellowfive@161
|
383 if prof then
|
yellowfive@161
|
384 local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof);
|
yellowfive@161
|
385 if Amr.ProfessionSkillLineToName[skillLine] == "Enchanting" and skillLevel > 0 then
|
yellowfive@161
|
386 return true
|
yellowfive@161
|
387 end
|
yellowfive@161
|
388 end
|
yellowfive@161
|
389 end
|
yellowfive@161
|
390
|
yellowfive@161
|
391 return false
|
yellowfive@161
|
392 end
|
yellowfive@161
|
393
|
yellowfive@161
|
394 --
|
yellowfive@161
|
395 -- Find a matching item that is not in the player's inventory (bank or equipped)
|
yellowfive@161
|
396 --
|
yellowfive@161
|
397 local function findMatchingNonBagItem(matchItem, usedItems)
|
yellowfive@161
|
398
|
yellowfive@161
|
399 local loc = ItemLocation.CreateEmpty()
|
yellowfive@161
|
400
|
yellowfive@161
|
401 -- check equipped
|
yellowfive@161
|
402 local equippedBagId = -1000
|
yellowfive@161
|
403 if not usedItems[equippedBagId] then
|
yellowfive@161
|
404 usedItems[equippedBagId] = {}
|
yellowfive@161
|
405 end
|
yellowfive@161
|
406
|
yellowfive@161
|
407 for slotNum = 1, #Amr.SlotIds do
|
yellowfive@161
|
408 local slotId = Amr.SlotIds[slotNum]
|
yellowfive@161
|
409 if not usedItems[equippedBagId][slotId] then
|
yellowfive@161
|
410 local itemLink = GetInventoryItemLink("player", slotId)
|
yellowfive@161
|
411 if itemLink then
|
yellowfive@161
|
412 local itemData = Amr.ParseItemLink(itemLink)
|
yellowfive@161
|
413 if itemData then
|
yellowfive@161
|
414 -- see if this is an azerite item and read azerite power ids
|
yellowfive@161
|
415 loc:SetEquipmentSlot(slotId)
|
yellowfive@161
|
416 if C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItem(loc) then
|
yellowfive@161
|
417 local powers = Amr.ReadAzeritePowers(loc)
|
yellowfive@161
|
418 if powers then
|
yellowfive@161
|
419 itemData.azerite = powers
|
yellowfive@161
|
420 end
|
yellowfive@161
|
421 end
|
yellowfive@161
|
422
|
yellowfive@161
|
423 -- see if it matches
|
yellowfive@161
|
424 if Amr.CountItemDifferences(matchItem, itemData) == 0 then
|
yellowfive@161
|
425 usedItems[equippedBagId][slotId] = true
|
yellowfive@161
|
426 itemData.bagId = bagId
|
yellowfive@161
|
427 itemData.slotId = slotId
|
yellowfive@161
|
428 return itemData
|
yellowfive@161
|
429 end
|
yellowfive@161
|
430 end
|
yellowfive@161
|
431 end
|
yellowfive@161
|
432 end
|
yellowfive@161
|
433 end
|
yellowfive@161
|
434
|
yellowfive@161
|
435 -- check bank data
|
yellowfive@163
|
436 local bestMatchDiffs = 100000
|
yellowfive@163
|
437 local bestMatch = nil
|
yellowfive@163
|
438 local threshold
|
yellowfive@163
|
439
|
yellowfive@161
|
440 if Amr.db.char.BankItems then
|
yellowfive@161
|
441 for bagId, v in pairs(Amr.db.char.BankItems) do
|
yellowfive@161
|
442 if not usedItems[bagId] then
|
yellowfive@161
|
443 usedItems[bagId] = {}
|
yellowfive@161
|
444 end
|
yellowfive@161
|
445
|
yellowfive@161
|
446 for i, itemData in ipairs(v) do
|
yellowfive@161
|
447 if itemData and not usedItems[bagId][i] then
|
yellowfive@161
|
448 -- see if it matches
|
yellowfive@163
|
449 local diffs = Amr.CountItemDifferences(matchItem, itemData)
|
yellowfive@163
|
450 if diffs == 0 then
|
yellowfive@161
|
451 usedItems[bagId][i] = true
|
yellowfive@161
|
452 itemData.bagId = bagId
|
yellowfive@161
|
453 itemData.slotId = i
|
yellowfive@161
|
454 return itemData
|
yellowfive@163
|
455 elseif diffs < 10000 then
|
yellowfive@163
|
456 if itemData.azerite and #itemData.azerite > 0 then
|
yellowfive@163
|
457 threshold = 100
|
yellowfive@163
|
458 else
|
yellowfive@163
|
459 threshold = 10000
|
yellowfive@163
|
460 end
|
yellowfive@163
|
461 if diffs < threshold and diffs < bestMatchDiffs then
|
yellowfive@163
|
462 -- closest match we could find
|
yellowfive@163
|
463 bestMatchDiffs = diffs
|
yellowfive@163
|
464 itemData.bagId = bagId
|
yellowfive@163
|
465 itemData.slotId = i
|
yellowfive@163
|
466 bestMatch = itemData
|
yellowfive@163
|
467 end
|
yellowfive@161
|
468 end
|
yellowfive@161
|
469 end
|
yellowfive@161
|
470 end
|
yellowfive@161
|
471 end
|
yellowfive@161
|
472 end
|
yellowfive@161
|
473
|
yellowfive@163
|
474 -- if we couldn't get a perfect match, take the best match that might have some small differences like
|
yellowfive@163
|
475 -- an old school enchant or upgrade ID that didn't load
|
yellowfive@163
|
476 if bestMatch then
|
yellowfive@163
|
477 usedItems[bestMatch.bagId][bestMatch.slotId] = true
|
yellowfive@163
|
478 return bestMatch
|
yellowfive@163
|
479 else
|
yellowfive@163
|
480 return nil
|
yellowfive@163
|
481 end
|
yellowfive@161
|
482 end
|
yellowfive@161
|
483
|
yellowfive@161
|
484 local function renderItem(item, itemLink, scroll)
|
yellowfive@161
|
485
|
yellowfive@161
|
486 local panel = AceGUI:Create("AmrUiPanel")
|
yellowfive@161
|
487 scroll:AddChild(panel)
|
yellowfive@161
|
488 panel:SetLayout("None")
|
yellowfive@161
|
489 panel:SetTransparent()
|
yellowfive@161
|
490 panel:SetWidth(380)
|
yellowfive@161
|
491 panel:SetHeight(40)
|
yellowfive@161
|
492
|
yellowfive@161
|
493 -- ilvl label
|
yellowfive@161
|
494 local lblIlvl = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
495 panel:AddChild(lblIlvl)
|
yellowfive@161
|
496 lblIlvl:SetPoint("LEFT", panel.content, "LEFT", 0, 0)
|
yellowfive@161
|
497 lblIlvl:SetWidth(35)
|
yellowfive@161
|
498 lblIlvl:SetFont(Amr.CreateFont("Italic", 13, Amr.Colors.TextTan))
|
yellowfive@161
|
499
|
yellowfive@161
|
500 -- icon
|
yellowfive@161
|
501 local icon = AceGUI:Create("AmrUiIcon")
|
yellowfive@161
|
502 panel:AddChild(icon)
|
yellowfive@161
|
503 icon:SetBorderWidth(1)
|
yellowfive@161
|
504 icon:SetIconBorderColor(Amr.Colors.White)
|
yellowfive@161
|
505 icon:SetWidth(28)
|
yellowfive@161
|
506 icon:SetHeight(28)
|
yellowfive@161
|
507 icon:SetPoint("LEFT", lblIlvl.frame, "RIGHT", 0, 0)
|
yellowfive@161
|
508
|
yellowfive@161
|
509 -- item name/link label
|
yellowfive@161
|
510 local lblItem = AceGUI:Create("AmrUiTextButton")
|
yellowfive@161
|
511 panel:AddChild(lblItem)
|
yellowfive@161
|
512 lblItem:SetPoint("LEFT", icon.frame, "RIGHT", 0, 0)
|
yellowfive@161
|
513 lblItem:SetWordWrap(false)
|
yellowfive@161
|
514 lblItem:SetJustifyH("LEFT")
|
yellowfive@161
|
515 lblItem:SetWidth(300)
|
yellowfive@161
|
516 lblItem:SetHeight(28)
|
yellowfive@161
|
517 lblItem:SetFont(Amr.CreateFont("Regular", 13, Amr.Colors.White))
|
yellowfive@161
|
518 lblItem:SetHoverBackgroundColor(Amr.Colors.Black, 0.3)
|
yellowfive@161
|
519 lblItem:SetTextPadding(0, 0, 0, 5)
|
yellowfive@161
|
520 lblItem:SetCallback("PreClick", onItemPreClick)
|
yellowfive@161
|
521 lblItem:SetCallback("OnClick", onItemClick)
|
yellowfive@161
|
522 lblItem:SetUserData("itemData", item)
|
yellowfive@161
|
523
|
yellowfive@161
|
524 -- fill the name/ilvl labels, which may require asynchronous loading of item information
|
yellowfive@161
|
525 if itemLink then
|
yellowfive@161
|
526 local gameItem = Item:CreateFromItemLink(itemLink)
|
yellowfive@161
|
527 if gameItem then
|
yellowfive@161
|
528 local q = gameItem:GetItemQuality()
|
yellowfive@161
|
529 lblItem:SetFont(Amr.CreateFont("Regular", 13, Amr.Colors.Qualities[q] or Amr.Colors.White))
|
yellowfive@161
|
530 lblItem:SetHoverFont(Amr.CreateFont("Regular", 13, Amr.Colors.Qualities[q] or Amr.Colors.White))
|
yellowfive@161
|
531 lblItem:SetText(gameItem:GetItemName())
|
yellowfive@161
|
532 lblIlvl:SetText(gameItem:GetCurrentItemLevel())
|
yellowfive@161
|
533 icon:SetIconBorderColor(Amr.Colors.Qualities[q] or Amr.Colors.White)
|
yellowfive@161
|
534 icon:SetIcon(gameItem:GetItemIcon())
|
yellowfive@161
|
535 Amr:SetItemTooltip(lblItem, gameItem:GetItemLink(), "ANCHOR_BOTTOMRIGHT", 0, 30)
|
yellowfive@161
|
536 end
|
yellowfive@161
|
537 end
|
yellowfive@161
|
538
|
yellowfive@161
|
539 end
|
yellowfive@161
|
540
|
yellowfive@161
|
541 --
|
yellowfive@161
|
542 -- Just updates state without re-rendering the list of junk
|
yellowfive@161
|
543 --
|
yellowfive@161
|
544 function Amr:SetJunkUiState()
|
yellowfive@161
|
545
|
yellowfive@161
|
546 -- don't do anything if the window is not open
|
yellowfive@161
|
547 if not _frameJunk then return end
|
yellowfive@161
|
548
|
yellowfive@161
|
549 -- cache whether the player can disenchant whenever the ui is refreshed
|
yellowfive@161
|
550 _canDisenchant = canDisenchant()
|
yellowfive@161
|
551
|
yellowfive@161
|
552 -- update action label
|
yellowfive@161
|
553 if _isScrapOpen then
|
yellowfive@161
|
554 _lblAction:SetText(L.JunkScrap)
|
yellowfive@161
|
555 elseif _isMerchantOpen then
|
yellowfive@161
|
556 _lblAction:SetText(L.JunkVendor)
|
yellowfive@161
|
557 elseif _canDisenchant then
|
yellowfive@161
|
558 _lblAction:SetText(L.JunkDisenchant)
|
yellowfive@161
|
559 else
|
yellowfive@161
|
560 _lblAction:SetText(" ")
|
yellowfive@161
|
561 end
|
yellowfive@161
|
562
|
yellowfive@161
|
563 -- update bank button state
|
yellowfive@161
|
564 _btnBank:SetDisabled(not _isBankOpen)
|
yellowfive@161
|
565 end
|
yellowfive@161
|
566
|
yellowfive@161
|
567 --
|
yellowfive@161
|
568 -- Refresh the entire UI, including re-rendering the junk list
|
yellowfive@161
|
569 --
|
yellowfive@161
|
570 function Amr:RefreshJunkUi()
|
yellowfive@161
|
571
|
yellowfive@161
|
572 -- don't do anything if the window is not open
|
yellowfive@161
|
573 if not _frameJunk then return end
|
yellowfive@161
|
574
|
yellowfive@161
|
575 Amr:SetJunkUiState()
|
yellowfive@161
|
576
|
yellowfive@161
|
577 -- clear out any previous data
|
yellowfive@161
|
578 _panelContent:ReleaseChildren()
|
yellowfive@161
|
579
|
yellowfive@161
|
580 local data = Amr.db.char.JunkData
|
yellowfive@161
|
581
|
yellowfive@161
|
582 if not data or not data.Junk or #data.Junk <= 0 then
|
yellowfive@161
|
583 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
584 _panelContent:AddChild(lbl)
|
yellowfive@161
|
585 lbl:SetFont(Amr.CreateFont("Italic", 16, Amr.Colors.TextGray))
|
yellowfive@161
|
586 lbl:SetText(L.JunkEmpty)
|
yellowfive@161
|
587 lbl:SetPoint("TOPLEFT", _panelContent.content, "TOPLEFT", 0, -10)
|
yellowfive@161
|
588 _lblBank:SetVisible(false)
|
yellowfive@161
|
589 _btnBank:SetVisible(false)
|
yellowfive@161
|
590 else
|
yellowfive@161
|
591
|
yellowfive@161
|
592 _panelContent:SetLayout("Fill")
|
yellowfive@161
|
593
|
yellowfive@161
|
594 local scroll = AceGUI:Create("AmrUiScrollFrame")
|
yellowfive@161
|
595 scroll:SetLayout("List")
|
yellowfive@161
|
596 _panelContent:AddChild(scroll)
|
yellowfive@161
|
597
|
yellowfive@161
|
598 -- render items currently in the player's inventory
|
yellowfive@161
|
599 local usedItems = {}
|
yellowfive@161
|
600 local bankCount = 0
|
yellowfive@161
|
601 local missingCount = 0
|
yellowfive@161
|
602
|
yellowfive@161
|
603 -- if we have any "keep" items, those are exact duplicates of ones to be junked,
|
yellowfive@161
|
604 -- be sure to "reserve" those first
|
yellowfive@161
|
605 if data.Keep then
|
yellowfive@161
|
606 for uniqueId, item in pairs(data.Keep) do
|
yellowfive@161
|
607 -- check if an exact match is in the player's bank data or equipped
|
yellowfive@161
|
608 local matchItem = findMatchingNonBagItem(item, usedItems)
|
yellowfive@161
|
609
|
yellowfive@161
|
610 -- if not, find one in the player's bags
|
yellowfive@161
|
611 if not matchItem then
|
yellowfive@161
|
612 matchItem = findMatchingBagItem(item, usedItems)
|
yellowfive@161
|
613 end
|
yellowfive@161
|
614
|
yellowfive@161
|
615 if not matchItem then
|
yellowfive@161
|
616 -- abort, player's data must be out of sync
|
yellowfive@161
|
617 local lbl = AceGUI:Create("AmrUiLabel")
|
yellowfive@161
|
618 _panelContent:AddChild(lbl)
|
yellowfive@161
|
619 lbl:SetWidth(380)
|
yellowfive@161
|
620 lbl:SetFont(Amr.CreateFont("Italic", 13, Amr.Colors.TextGray))
|
yellowfive@161
|
621 lbl:SetText(L.JunkOutOfSync)
|
yellowfive@161
|
622 lbl:SetPoint("TOPLEFT", _panelContent.content, "TOPLEFT", 0, -10)
|
yellowfive@161
|
623
|
yellowfive@161
|
624 _lblBank:SetVisible(false)
|
yellowfive@161
|
625 _btnBank:SetVisible(false)
|
yellowfive@161
|
626
|
yellowfive@161
|
627 return
|
yellowfive@161
|
628 end
|
yellowfive@161
|
629 end
|
yellowfive@161
|
630 end
|
yellowfive@161
|
631
|
yellowfive@161
|
632 -- now render any junk items in the player's bags, and a count of how many are elsewhere (usually bank)
|
yellowfive@161
|
633 for i, item in ipairs(data.Junk) do
|
yellowfive@161
|
634 local matchItem = findMatchingBagItem(item, usedItems)
|
yellowfive@161
|
635 if matchItem then
|
yellowfive@161
|
636 local itemLink = Amr.CreateItemLink(matchItem)
|
yellowfive@161
|
637 renderItem(matchItem, itemLink, scroll)
|
yellowfive@161
|
638 else
|
yellowfive@161
|
639 -- see if it is in the bank or equipped
|
yellowfive@161
|
640 matchItem = findMatchingNonBagItem(item, usedItems)
|
yellowfive@161
|
641 if matchItem then
|
yellowfive@161
|
642 bankCount = bankCount + 1
|
yellowfive@161
|
643 else
|
yellowfive@161
|
644 missingCount = missingCount + 1
|
yellowfive@161
|
645 end
|
yellowfive@161
|
646 end
|
yellowfive@161
|
647 end
|
yellowfive@161
|
648
|
yellowfive@161
|
649 _lblBank:SetText(L.JunkBankText(bankCount))
|
yellowfive@161
|
650 _lblBank:SetVisible(bankCount > 0)
|
yellowfive@161
|
651 _btnBank:SetVisible(bankCount > 0)
|
yellowfive@161
|
652 end
|
yellowfive@161
|
653 end
|
yellowfive@161
|
654
|
yellowfive@161
|
655 Amr:AddEventHandler("SCRAPPING_MACHINE_SHOW", function()
|
yellowfive@161
|
656 _isScrapOpen = true
|
yellowfive@161
|
657 if Amr.db.profile.options.junkVendor and Amr.db.char.JunkData and Amr.db.char.JunkData.Junk and #Amr.db.char.JunkData.Junk > 0 then
|
yellowfive@161
|
658 Amr:ShowJunkWindow()
|
yellowfive@161
|
659 else
|
yellowfive@161
|
660 Amr:SetJunkUiState()
|
yellowfive@161
|
661 end
|
yellowfive@161
|
662 end)
|
yellowfive@161
|
663
|
yellowfive@161
|
664 Amr:AddEventHandler("SCRAPPING_MACHINE_CLOSE", function()
|
yellowfive@161
|
665 _isScrapOpen = false
|
yellowfive@161
|
666 if Amr.db.profile.options.junkVendor then
|
yellowfive@161
|
667 Amr:HideJunkWindow()
|
yellowfive@161
|
668 else
|
yellowfive@161
|
669 Amr:SetJunkUiState()
|
yellowfive@161
|
670 end
|
yellowfive@161
|
671 end)
|
yellowfive@161
|
672
|
yellowfive@161
|
673 Amr:AddEventHandler("MERCHANT_SHOW", function()
|
yellowfive@161
|
674 _isMerchantOpen = true
|
yellowfive@161
|
675 if Amr.db.profile.options.junkVendor and Amr.db.char.JunkData and Amr.db.char.JunkData.Junk and #Amr.db.char.JunkData.Junk > 0 then
|
yellowfive@161
|
676 Amr:ShowJunkWindow()
|
yellowfive@161
|
677 else
|
yellowfive@161
|
678 Amr:SetJunkUiState()
|
yellowfive@161
|
679 end
|
yellowfive@161
|
680 end)
|
yellowfive@161
|
681
|
yellowfive@161
|
682 Amr:AddEventHandler("MERCHANT_CLOSED", function()
|
yellowfive@161
|
683 _isMerchantOpen = false
|
yellowfive@161
|
684 if Amr.db.profile.options.junkVendor then
|
yellowfive@161
|
685 Amr:HideJunkWindow()
|
yellowfive@161
|
686 else
|
yellowfive@161
|
687 Amr:SetJunkUiState()
|
yellowfive@161
|
688 end
|
yellowfive@161
|
689 end)
|
yellowfive@161
|
690
|
yellowfive@161
|
691 Amr:AddEventHandler("BANKFRAME_OPENED", function()
|
yellowfive@161
|
692 _isBankOpen = true
|
yellowfive@161
|
693 Amr:SetJunkUiState()
|
yellowfive@161
|
694 end)
|
yellowfive@161
|
695
|
yellowfive@161
|
696 Amr:AddEventHandler("BANKFRAME_CLOSED", function()
|
yellowfive@161
|
697 _isBankOpen = false
|
yellowfive@161
|
698 Amr:SetJunkUiState()
|
yellowfive@161
|
699 end)
|