Mercurial > wow > inventory
comparison Modules/Alerts.lua @ 176:26c750a10b14
Renamed Inventorium debug channel to IMDebug (so it?s easier to recognize only IM changes, not from other addons), write /im d to register this new channel.
Implemented stock alerts.
Added ?don?t alert at characters? option which allows you to track groups at characters without being bothered about low stock.
You can change the speed of the stock alert at the extra config tab.
author | Zerotorescue |
---|---|
date | Sun, 30 Jan 2011 15:39:18 +0100 |
parents | |
children | 679d3664849d |
comparison
equal
deleted
inserted
replaced
175:7aa0850952ef | 176:26c750a10b14 |
---|---|
1 local addon = select(2, ...); | |
2 local mod = addon:NewModule("Alerts", "AceEvent-3.0", "AceTimer-3.0"); | |
3 | |
4 local queue, cache = {}, {}; | |
5 | |
6 function mod:OnEnable() | |
7 addon:Debug("Alerts:OnEnable"); | |
8 | |
9 -- Register our alert slash command | |
10 -- /im alert | |
11 addon:RegisterSlash(function(this) | |
12 mod:Scan(true); | |
13 end, { "a", "alert" }, "|Hfunction:InventoriumCommandHandler:alert|h|cff00fff7/im alert|r|h (or /im a) - Rescan the items within all tracked groups and show item alerts for those items missing."); | |
14 | |
15 self:RegisterEvent("PLAYER_LOGIN", function() | |
16 mod:Scan(false); | |
17 end); | |
18 | |
19 --[[if addon.db.profile.defaults.scanInterval["00Login"] then | |
20 self:RegisterEvent("PLAYER_LOGIN", "Scan"); | |
21 end | |
22 | |
23 if addon.db.profile.defaults.scanInterval["01Repeat5"] then | |
24 self:ScheduleTimer("Scan", 5 * 60); | |
25 elseif addon.db.profile.defaults.scanInterval["01Repeat10"] then | |
26 self:ScheduleTimer("Scan", 10 * 60); | |
27 elseif addon.db.profile.defaults.scanInterval["01Repeat15"] then | |
28 self:ScheduleTimer("Scan", 15 * 60); | |
29 elseif addon.db.profile.defaults.scanInterval["01Repeat30"] then | |
30 self:ScheduleTimer("Scan", 30 * 60); | |
31 elseif addon.db.profile.defaults.scanInterval["01Repeat60"] then | |
32 self:ScheduleTimer("Scan", 60 * 60); | |
33 elseif addon.db.profile.defaults.scanInterval["01Repeat120"] then | |
34 self:ScheduleTimer("Scan", 120 * 60); | |
35 end]] | |
36 end | |
37 | |
38 local scanTypes = { | |
39 Local = "local", | |
40 Global = "global", | |
41 }; | |
42 | |
43 function mod:Scan(verbal) | |
44 addon:Debug("Alerts:Scan"); | |
45 | |
46 if verbal then | |
47 addon:Print("Scanning items, the results will be presented to you in a moment. Please be patient."); | |
48 end | |
49 | |
50 local playerName = UnitName("player"); | |
51 | |
52 table.wipe(queue); | |
53 table.wipe(cache); | |
54 | |
55 -- Go through all groups | |
56 for groupName, values in pairs(addon.db.profile.groups) do | |
57 -- Settings | |
58 local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); | |
59 local dontAlertAt = addon:GetOptionByKey(groupName, "dontAlertAtCharacters"); | |
60 | |
61 local alertBelowLocalMinimum = addon:GetOptionByKey(groupName, "alertBelowLocalMinimum"); | |
62 local minLocalStock = alertBelowLocalMinimum and addon:GetOptionByKey(groupName, "minLocalStock"); | |
63 | |
64 local alertBelowGlobalMinimum = addon:GetOptionByKey(groupName, "alertBelowGlobalMinimum"); | |
65 local minGlobalStock = alertBelowGlobalMinimum and addon:GetOptionByKey(groupName, "minGlobalStock"); | |
66 | |
67 local isTracked = (trackAt and trackAt[playerName] and (not dontAlertAt or not dontAlertAt[playerName])); -- Is this character interested in this data and does it want alerts? | |
68 | |
69 if values.items and isTracked and (alertBelowLocalMinimum or alertBelowGlobalMinimum) then | |
70 addon:Debug("Scanning |cff00ff00%s|r", groupName); | |
71 | |
72 local groupSettings = { | |
73 ["name"] = groupName, | |
74 ["minLocalStock"] = minLocalStock, | |
75 ["minGlobalStock"] = minGlobalStock, | |
76 }; | |
77 | |
78 for itemId, _ in pairs(values.items) do | |
79 if alertBelowLocalMinimum then | |
80 self:QeueueScan(groupSettings, itemId, scanTypes.Local); | |
81 end | |
82 | |
83 if alertBelowGlobalMinimum then | |
84 self:QeueueScan(groupSettings, itemId, scanTypes.Global); | |
85 end | |
86 end | |
87 end | |
88 end | |
89 | |
90 if self:HasQueue() then | |
91 addon:Debug("Alerts:HasQueue, processing"); | |
92 --addon:Debug(queue); | |
93 | |
94 self:ProcessScan(verbal); | |
95 end | |
96 end | |
97 | |
98 function mod:QeueueScan(groupSettings, itemId, scanType) | |
99 table.insert(queue, { | |
100 ["group"] = groupSettings, | |
101 ["itemId"] = itemId, | |
102 ["type"] = scanType, | |
103 }); | |
104 end | |
105 | |
106 function mod:HasQueue() | |
107 return (#queue > 0); | |
108 end | |
109 | |
110 function mod:ProcessScan(verbal) | |
111 local thisItem = table.remove(queue, 1); | |
112 | |
113 if not thisItem then | |
114 self:ScanFinished(); | |
115 return; | |
116 end | |
117 | |
118 if thisItem.type == scanTypes.Global then | |
119 local globalCount = addon:GetItemCount(thisItem.itemId, thisItem.group.name); | |
120 | |
121 if not cache[thisItem.itemId] then | |
122 cache[thisItem.itemId] = { | |
123 ["itemId"] = thisItem.itemId, -- needed later for displaying | |
124 ["group"] = thisItem.group, | |
125 ["globalCount"] = globalCount, | |
126 }; | |
127 else | |
128 cache[thisItem.itemId].globalCount = globalCount; | |
129 end | |
130 elseif thisItem.type == scanTypes.Local then | |
131 local localCount = addon:GetLocalItemCount(thisItem.itemId, thisItem.group.name); | |
132 | |
133 if not cache[thisItem.itemId] then | |
134 cache[thisItem.itemId] = { | |
135 ["itemId"] = thisItem.itemId, -- needed later for displaying | |
136 ["group"] = thisItem.group, | |
137 ["localCount"] = localCount, | |
138 }; | |
139 else | |
140 cache[thisItem.itemId].globalCount = localCount; | |
141 end | |
142 end | |
143 | |
144 local nextScanDelay = (tonumber(addon.db.profile.defaults.scanInterval) or .1); | |
145 | |
146 if nextScanDelay == 0 then | |
147 mod:ProcessScan(verbal); | |
148 else | |
149 self:ScheduleTimer(function() | |
150 mod:ProcessScan(verbal); | |
151 end, nextScanDelay); -- scan next item in nextScanDelay seconds | |
152 end | |
153 end | |
154 | |
155 local function OnProceed() | |
156 InventoriumCommandHandler("summary"); | |
157 | |
158 if InventoriumItemMover then | |
159 InventoriumItemMover:Hide(); | |
160 end | |
161 end | |
162 | |
163 local function OnCancel() | |
164 if InventoriumItemMover then | |
165 InventoriumItemMover:Hide(); | |
166 end | |
167 end | |
168 | |
169 local function UseScanST() | |
170 if not InventoriumItemMover then | |
171 addon:CreateMoverFrame(); | |
172 end | |
173 | |
174 local frame = InventoriumItemMover; -- both for speed as code-consistency | |
175 | |
176 -- Scrolling table with a list of items to be moved | |
177 local scrollTableWidth = ( frame.frmMeasureDummy:GetWidth() - 30 ); -- adjust width by the scrollbar size | |
178 local headers = { | |
179 { | |
180 ["name"] = "Item", | |
181 ["width"] = (scrollTableWidth * .6), | |
182 ["defaultsort"] = "asc", | |
183 ["comparesort"] = function(this, aRow, bRow, column) | |
184 local aName, _, aRarity = GetItemInfo(this:GetRow(aRow).rowData.itemId); | |
185 local bName, _, bRarity = GetItemInfo(this:GetRow(bRow).rowData.itemId); | |
186 local template = "%d%s"; | |
187 aName = template:format((10 - (aRarity or 10)), (aName or ""):lower()); | |
188 bName = template:format((10 - (bRarity or 10)), (bName or ""):lower()); | |
189 | |
190 if this.cols[column].sort == "dsc" then | |
191 return aName > bName; | |
192 else | |
193 return aName < bName; | |
194 end | |
195 end, | |
196 ["sort"] = "asc", -- when the data is set, use this column so sort the default data | |
197 ["tooltipTitle"] = "Item", | |
198 ["tooltip"] = "Click to sort the list by item quality then item name.", | |
199 }, | |
200 { | |
201 ["name"] = "Local", | |
202 ["width"] = (scrollTableWidth * .2), | |
203 ["align"] = "RIGHT", | |
204 ["defaultsort"] = "dsc", | |
205 ["sortnext"] = 1, | |
206 ["comparesort"] = function(this, aRow, bRow, column) | |
207 local aAvailablePercent = (this:GetRow(aRow).rowData.localCount / this:GetRow(aRow).rowData.group.minLocalStock); | |
208 local bAvailablePercent = (this:GetRow(bRow).rowData.localCount / this:GetRow(bRow).rowData.group.minLocalStock); | |
209 | |
210 if this.cols[column].sort == "dsc" then | |
211 return aAvailablePercent > bAvailablePercent; | |
212 else | |
213 return aAvailablePercent < bAvailablePercent; | |
214 end | |
215 end, | |
216 ["tooltipTitle"] = "Local Stock", | |
217 ["tooltip"] = "Click to sort the list by the local stock percentage.", | |
218 }, | |
219 { | |
220 ["name"] = "Global", | |
221 ["width"] = (scrollTableWidth * .2), | |
222 ["align"] = "RIGHT", | |
223 ["defaultsort"] = "dsc", | |
224 ["sortnext"] = 1, | |
225 ["comparesort"] = function(this, aRow, bRow, column) | |
226 local aAvailablePercent = (this:GetRow(aRow).rowData.globalCount / this:GetRow(aRow).rowData.group.minGlobalStock); | |
227 local bAvailablePercent = (this:GetRow(bRow).rowData.globalCount / this:GetRow(bRow).rowData.group.minGlobalStock); | |
228 | |
229 if this.cols[column].sort == "dsc" then | |
230 return aAvailablePercent > bAvailablePercent; | |
231 else | |
232 return aAvailablePercent < bAvailablePercent; | |
233 end | |
234 end, | |
235 ["tooltipTitle"] = "Global Stock", | |
236 ["tooltip"] = "Click to sort the list by the global stock percentage.", | |
237 }, | |
238 }; | |
239 | |
240 local proceedButton = { | |
241 text = "Show in summary", | |
242 tooltipTitle = "Show in Summary", | |
243 tooltip = "Show the summary giving a more detailed list of missing items.", | |
244 onClick = OnProceed, | |
245 }; | |
246 local cancelButton = { | |
247 text = "Cancel", | |
248 tooltipTitle = "Cancel", | |
249 tooltip = "Close the window.", | |
250 onClick = OnCancel, | |
251 }; | |
252 | |
253 addon:SetMoverFrameSettings("Inventorium Stock Alert", "You have elected to receive an alert when the following items are under your minimum stock requirement:", proceedButton, cancelButton, headers); | |
254 end | |
255 | |
256 function mod:ScanFinished() | |
257 table.wipe(queue); | |
258 | |
259 --addon:Debug(cache); | |
260 | |
261 -- This table is never copied, just referenced. It is the same for every row. | |
262 local missingRow = { | |
263 { | |
264 ["value"] = function(data, cols, realrow, column, table) | |
265 return IdToItemLink(data[realrow].rowData.itemId); | |
266 end, | |
267 }, -- item | |
268 { | |
269 ["value"] = function(data, cols, realrow, column, table) | |
270 return addon:DisplayItemCount(data[realrow].rowData.localCount or -4, data[realrow].rowData.group.minLocalStock); | |
271 end, | |
272 }, -- local | |
273 { | |
274 ["value"] = function(data, cols, realrow, column, table) | |
275 return addon:DisplayItemCount(data[realrow].rowData.globalCount or -4, data[realrow].rowData.group.minGlobalStock); | |
276 end, | |
277 }, -- global | |
278 }; | |
279 | |
280 -- Store the list with rows in this | |
281 local missingList = {}; | |
282 | |
283 for itemId, info in pairs(cache) do | |
284 if (info.globalCount and info.globalCount < info.group.minGlobalStock) or (info.localCount and info.localCount < info.group.minLocalStock) then | |
285 -- Not enough global or not enough local | |
286 | |
287 tinsert(missingList, { | |
288 ["rowData"] = info, -- this is not a key usually found in a row item and ignored by the library | |
289 ["cols"] = missingRow, | |
290 }); | |
291 end | |
292 end | |
293 | |
294 table.wipe(cache); -- no longer needed, all missing items are now stored in the missingList | |
295 | |
296 if #missingList > 0 then | |
297 UseScanST(); | |
298 | |
299 addon:SetMoverFrameData(missingList); | |
300 | |
301 if verbal then | |
302 addon:Print("Presenting the data..."); | |
303 end | |
304 elseif verbal then | |
305 addon:Print("No items that you elected to be alerted about are below the selected stock thresholds."); | |
306 end | |
307 end |