Mercurial > wow > askmrrobot
comparison AskMrRobot.lua @ 17:e77e01abce98
Warlords of Draenor pre-patch
author | Adam tegen <adam.tegen@gmail.com> |
---|---|
date | Mon, 13 Oct 2014 21:28:32 -0500 |
parents | bb0c8ce689d1 |
children | a400b906acca |
comparison
equal
deleted
inserted
replaced
16:9793e8b683d2 | 17:e77e01abce98 |
---|---|
1 local _, AskMrRobot = ... | 1 local _, AskMrRobot = ... |
2 local L = AskMrRobot.L; | 2 local L = AskMrRobot.L; |
3 | 3 |
4 AskMrRobot.eventListener = CreateFrame("FRAME"); -- Need a frame to respond to events | 4 AskMrRobot.eventListener = CreateFrame("FRAME") -- Need a frame to respond to events |
5 AskMrRobot.eventListener:RegisterEvent("ADDON_LOADED"); -- Fired when saved variables are loaded | 5 AskMrRobot.eventListener:RegisterEvent("ADDON_LOADED") -- Fired when saved variables are loaded |
6 AskMrRobot.eventListener:RegisterEvent("ITEM_PUSH"); | 6 AskMrRobot.eventListener:RegisterEvent("ITEM_PUSH") |
7 AskMrRobot.eventListener:RegisterEvent("DELETE_ITEM_CONFIRM"); | 7 AskMrRobot.eventListener:RegisterEvent("DELETE_ITEM_CONFIRM") |
8 AskMrRobot.eventListener:RegisterEvent("UNIT_INVENTORY_CHANGED"); | 8 AskMrRobot.eventListener:RegisterEvent("UNIT_INVENTORY_CHANGED") |
9 AskMrRobot.eventListener:RegisterEvent("BANKFRAME_OPENED"); | 9 AskMrRobot.eventListener:RegisterEvent("BANKFRAME_OPENED") |
10 AskMrRobot.eventListener:RegisterEvent("BANKFRAME_CLOSED"); | 10 --AskMrRobot.eventListener:RegisterEvent("BANKFRAME_CLOSED"); |
11 AskMrRobot.eventListener:RegisterEvent("PLAYERBANKSLOTS_CHANGED"); | 11 AskMrRobot.eventListener:RegisterEvent("PLAYERBANKSLOTS_CHANGED") |
12 AskMrRobot.eventListener:RegisterEvent("CHARACTER_POINTS_CHANGED"); | 12 AskMrRobot.eventListener:RegisterEvent("CHARACTER_POINTS_CHANGED") |
13 AskMrRobot.eventListener:RegisterEvent("CONFIRM_TALENT_WIPE"); | 13 AskMrRobot.eventListener:RegisterEvent("CONFIRM_TALENT_WIPE") |
14 AskMrRobot.eventListener:RegisterEvent("PLAYER_TALENT_UPDATE"); | 14 AskMrRobot.eventListener:RegisterEvent("PLAYER_TALENT_UPDATE") |
15 AskMrRobot.eventListener:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED"); | 15 AskMrRobot.eventListener:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED") |
16 AskMrRobot.eventListener:RegisterEvent("PLAYER_ENTERING_WORLD"); | 16 AskMrRobot.eventListener:RegisterEvent("PLAYER_ENTERING_WORLD") |
17 AskMrRobot.eventListener:RegisterEvent("PLAYER_LOGOUT"); -- Fired when about to log out | 17 --AskMrRobot.eventListener:RegisterEvent("PLAYER_LOGOUT") -- Fired when about to log out |
18 AskMrRobot.eventListener:RegisterEvent("PLAYER_LEVEL_UP"); | 18 --AskMrRobot.eventListener:RegisterEvent("PLAYER_LEVEL_UP") |
19 --AskMrRobot.eventListener:RegisterEvent("GET_ITEM_INFO_RECEIVED") | 19 --AskMrRobot.eventListener:RegisterEvent("GET_ITEM_INFO_RECEIVED") |
20 AskMrRobot.eventListener:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") | 20 AskMrRobot.eventListener:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") |
21 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_UPDATE") | 21 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_UPDATE") |
22 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_CLOSE") | 22 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_CLOSE") |
23 AskMrRobot.eventListener:RegisterEvent("BAG_UPDATE") | 23 AskMrRobot.eventListener:RegisterEvent("BAG_UPDATE") |
29 AskMrRobot.eventListener:RegisterEvent("PLAYER_DIFFICULTY_CHANGED") | 29 AskMrRobot.eventListener:RegisterEvent("PLAYER_DIFFICULTY_CHANGED") |
30 | 30 |
31 AskMrRobot.AddonName = ... | 31 AskMrRobot.AddonName = ... |
32 AskMrRobot.ChatPrefix = "_AMR" | 32 AskMrRobot.ChatPrefix = "_AMR" |
33 | 33 |
34 local amrLDB | 34 -- the main user interface window |
35 local icon | 35 AskMrRobot.mainWindow = nil |
36 local reforgequeue | 36 |
37 local reforgeFrame = nil | 37 local _amrLDB |
38 local LoggingCombat = _G.LoggingCombat | 38 local _minimapIcon |
39 | |
40 AskMrRobot.itemDiffs = { | |
41 items = {}, -- slotNum -> nil (no change) or current <item id>, optimized <item id> | |
42 enchants = {}, -- slotNum -> nil (no change) or current <enchant id>, optimized <enchant id> | |
43 gems = {}, -- slotNum -> nil (no change) or ? | |
44 reforges = {} -- slotNum -> nil (no change) or current <reforge id>, optimized <reforge id> | |
45 } | |
46 | |
47 AskMrRobot.instanceIds = { | |
48 HeartOfFear = 1009, | |
49 MogushanVaults = 1008, | |
50 SiegeOfOrgrimmar = 1136, | |
51 TerraceOfEndlessSpring = 996, | |
52 ThroneOfThunder = 1098 | |
53 } | |
54 | |
55 -- instances that we currently support logging for | |
56 AskMrRobot.supportedInstanceIds = { | |
57 [1136] = true | |
58 } | |
59 | |
60 -- returns true if currently in a supported instance | |
61 function AskMrRobot.IsSupportedInstance() | |
62 | |
63 local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo() | |
64 if AskMrRobot.supportedInstanceIds[tonumber(instanceMapID)] then | |
65 return true | |
66 else | |
67 return false | |
68 end | |
69 end | |
70 | |
71 -- upgrade id -> upgrade level | |
72 local upgradeTable = { | |
73 [0] = 0, | |
74 [1] = 1, -- 1/1 -> 8 | |
75 [373] = 1, -- 1/2 -> 4 | |
76 [374] = 2, -- 2/2 -> 8 | |
77 [375] = 1, -- 1/3 -> 4 | |
78 [376] = 2, -- 2/3 -> 4 | |
79 [377] = 3, -- 3/3 -> 4 | |
80 [378] = 1, -- 1/1 -> 7 | |
81 [379] = 1, -- 1/2 -> 4 | |
82 [380] = 2, -- 2/2 -> 4 | |
83 [445] = 0, -- 0/2 -> 0 | |
84 [446] = 1, -- 1/2 -> 4 | |
85 [447] = 2, -- 2/2 -> 8 | |
86 [451] = 0, -- 0/1 -> 0 | |
87 [452] = 1, -- 1/1 -> 8 | |
88 [453] = 0, -- 0/2 -> 0 | |
89 [454] = 1, -- 1/2 -> 4 | |
90 [455] = 2, -- 2/2 -> 8 | |
91 [456] = 0, -- 0/1 -> 0 | |
92 [457] = 1, -- 1/1 -> 8 | |
93 [458] = 0, -- 0/4 -> 0 | |
94 [459] = 1, -- 1/4 -> 4 | |
95 [460] = 2, -- 2/4 -> 8 | |
96 [461] = 3, -- 3/4 -> 12 | |
97 [462] = 4, -- 4/4 -> 16 | |
98 [465] = 0, -- 0/2 -> 0 | |
99 [466] = 1, -- 1/2 -> 4 | |
100 [467] = 2, -- 2/2 -> 8 | |
101 [468] = 0, -- 0/4 -> 0 | |
102 [469] = 1, -- 1/4 -> 4 | |
103 [470] = 2, -- 2/4 -> 8 | |
104 [471] = 3, -- 3/4 -> 12 | |
105 [472] = 4, -- 4/4 -> 16 | |
106 [476] = 0, -- ? -> 0 | |
107 [479] = 0, -- ? -> 0 | |
108 [491] = 0, -- ? -> 0 | |
109 [492] = 1, -- ? -> 0 | |
110 [493] = 2, -- ? -> 0 | |
111 [494] = 0, | |
112 [495] = 1, | |
113 [496] = 2, | |
114 [497] = 3, | |
115 [498] = 4, | |
116 [504] = 3, | |
117 [505] = 4, | |
118 [506] = 5, | |
119 [507] = 6 | |
120 } | |
121 | |
122 local professionIds = { | |
123 ["None"] = 0, | |
124 ["Mining"] = 1, | |
125 ["Skinning"] = 2, | |
126 ["Herbalism"] = 3, | |
127 ["Enchanting"] = 4, | |
128 ["Jewelcrafting"] = 5, | |
129 ["Engineering"] = 6, | |
130 ["Blacksmithing"] = 7, | |
131 ["Leatherworking"] = 8, | |
132 ["Inscription"] = 9, | |
133 ["Tailoring"] = 10, | |
134 ["Alchemy"] = 11, | |
135 ["Fishing"] = 12, | |
136 ["Cooking"] = 13, | |
137 ["First Aid"] = 14, | |
138 ["Archaeology"] = 15 | |
139 } | |
140 | |
141 local raceIds = { | |
142 ["None"] = 0, | |
143 ["BloodElf"] = 1, | |
144 ["Draenei"] = 2, | |
145 ["Dwarf"] = 3, | |
146 ["Gnome"] = 4, | |
147 ["Human"] = 5, | |
148 ["NightElf"] = 6, | |
149 ["Orc"] = 7, | |
150 ["Tauren"] = 8, | |
151 ["Troll"] = 9, | |
152 ["Scourge"] = 10, | |
153 ["Undead"] = 10, | |
154 ["Goblin"] = 11, | |
155 ["Worgen"] = 12, | |
156 ["Pandaren"] = 13 | |
157 } | |
158 | |
159 local factionIds = { | |
160 ["None"] = 0, | |
161 ["Alliance"] = 1, | |
162 ["Horde"] = 2 | |
163 } | |
164 | |
165 local function OnExport() | |
166 if (AmrOptions.exportToClient) then | |
167 AskMrRobot.SaveAll() | |
168 ReloadUI() | |
169 else | |
170 AskMrRobot_ReforgeFrame:Show() | |
171 AskMrRobot_ReforgeFrame:ShowTab("export") | |
172 end | |
173 end | |
174 | 39 |
175 function AskMrRobot.eventListener:OnEvent(event, ...) | 40 function AskMrRobot.eventListener:OnEvent(event, ...) |
176 if event == "ADDON_LOADED" then | 41 if event == "ADDON_LOADED" then |
177 local addon = select(1, ...) | 42 local addon = select(1, ...) |
178 if (addon == "AskMrRobot") then | 43 if (addon == "AskMrRobot") then |
179 print(L.AMR_ON_EVENT_LOADED.format(GetAddOnMetadata(AskMrRobot.AddonName, "Version"))) | 44 --print(L.AMR_ON_EVENT_LOADED:format(GetAddOnMetadata(AskMrRobot.AddonName, "Version"))) |
45 | |
46 AskMrRobot.InitializeSettings() | |
47 AskMrRobot.InitializeMinimap() | |
180 | 48 |
181 -- listen for messages from other AMR addons | 49 -- listen for messages from other AMR addons |
182 RegisterAddonMessagePrefix(AskMrRobot.ChatPrefix) | 50 RegisterAddonMessagePrefix(AskMrRobot.ChatPrefix) |
183 | 51 |
184 AmrRealmName = GetRealmName() | 52 AskMrRobot.mainWindow = AskMrRobot.AmrUI:new() |
185 AmrCharacterName = UnitName("player") | 53 end |
186 | 54 |
187 AskMrRobot.CombatLogTab.InitializeVariable() | 55 elseif event == "UNIT_INVENTORY_CHANGED" then |
188 | 56 AskMrRobot.ScanEquipped() |
189 if not AmrIconInfo then AmrIconInfo = {} end | 57 |
190 if not AmrBankItems then AmrBankItems = {} end | 58 elseif event == "ITEM_PUSH" or event == "DELETE_ITEM_CONFIRM" or event == "SOCKET_INFO_CLOSE" or event == "PLAYER_SPECIALIZATION_CHANGED" or event == "BAG_UPDATE" then |
191 if not AmrCurrencies then AmrCurrencies = {} end | 59 --if AskMrRobot_ReforgeFrame then |
192 if not AmrSpecializations then AmrSpecializations = {} end | 60 -- AskMrRobot_ReforgeFrame:OnUpdate() |
193 if not AmrOptions then AmrOptions = {} end | 61 --end |
194 if not AmrGlyphs then AmrGlyphs = {} end | |
195 if not AmrTalents then AmrTalents = {} end | |
196 if not AmrBankItemsAndCounts then AmrBankItemsAndCounts = {} end | |
197 if not AmrImportString then AmrImportString = "" end | |
198 if not AmrImportDate then AmrImportDate = "" end | |
199 | |
200 if not AmrSettings then AmrSettings = {} end | |
201 if not AmrSettings.Logins then AmrSettings.Logins = {} end | |
202 | |
203 if not AmrSendSettings then | |
204 AmrSendSettings = { | |
205 SendGems = true, | |
206 SendEnchants = true, | |
207 SendEnchantMaterials = true, | |
208 SendToType = "a friend", | |
209 SendTo = "" | |
210 } | |
211 end | |
212 | |
213 amrLDB = LibStub("LibDataBroker-1.1"):NewDataObject("AskMrRobot", { | |
214 type = "launcher", | |
215 text = "Ask Mr. Robot", | |
216 icon = "Interface\\AddOns\\AskMrRobot\\Media\\icon", | |
217 OnClick = function() | |
218 if IsControlKeyDown() then | |
219 AskMrRobot_ReforgeFrame.combatLogTab:LogWipe() | |
220 elseif IsModifiedClick("CHATLINK") then | |
221 OnExport() | |
222 else | |
223 AskMrRobot_ReforgeFrame:Toggle() | |
224 end | |
225 end, | |
226 OnTooltipShow = function(tt) | |
227 tt:AddLine("Ask Mr. Robot", 1, 1, 1); | |
228 tt:AddLine(" "); | |
229 tt:AddLine(L.AMR_ON_EVENT_TOOLTIP) | |
230 end | |
231 }); | |
232 | |
233 | |
234 AskMrRobot.AmrUpdateMinimap() | |
235 | |
236 AskMrRobot_ReforgeFrame = AskMrRobot.AmrUI:new() | |
237 | |
238 -- remember the import settings between sessions | |
239 AskMrRobot_ReforgeFrame.summaryTab.importDate = AmrImportDate or "" | |
240 AskMrRobot_ReforgeFrame.buttons[2]:Click() | |
241 | |
242 -- the previous import string is loaded when the UI is first shown, otherwise the game spams events and it lags | |
243 end | |
244 | |
245 elseif event == "ITEM_PUSH" or event == "DELETE_ITEM_CONFIRM" or event == "UNIT_INVENTORY_CHANGED" or event == "SOCKET_INFO_CLOSE" or event == "PLAYER_SPECIALIZATION_CHANGED" or event == "BAG_UPDATE" then | |
246 if AskMrRobot_ReforgeFrame then | |
247 AskMrRobot_ReforgeFrame:OnUpdate() | |
248 end | |
249 --AskMrRobot.SaveBags(); | 62 --AskMrRobot.SaveBags(); |
250 --AskMrRobot.SaveEquiped(); | 63 --AskMrRobot.SaveEquiped(); |
251 --AskMrRonot.GetCurrencies(); | 64 --AskMrRonot.GetCurrencies(); |
252 --AskMrRobot.GetGold(); | 65 --AskMrRobot.GetGold(); |
66 | |
253 elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then | 67 elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then |
254 --print("Scanning Bank: " .. event); | |
255 AskMrRobot.ScanBank(); | 68 AskMrRobot.ScanBank(); |
256 elseif event == "BANKFRAME_CLOSED" then | 69 |
257 --print("Stop Scanning Bank"); | |
258 --inBank = false; | |
259 elseif event == "CHARACTER_POINTS_CHANGED" or event == "CONFIRM_TALENT_WIPE" or event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED" then | 70 elseif event == "CHARACTER_POINTS_CHANGED" or event == "CONFIRM_TALENT_WIPE" or event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED" then |
260 --AskMrRobot.GetAmrSpecializations(); | 71 --AskMrRobot.GetAmrSpecializations(); |
261 if AskMrRobot_ReforgeFrame then | 72 --if AskMrRobot_ReforgeFrame then |
262 AskMrRobot_ReforgeFrame:OnUpdate() | 73 -- AskMrRobot_ReforgeFrame:OnUpdate() |
263 end | 74 --end |
264 elseif event == "PLAYER_LEVEL_UP" then | 75 |
265 --GetLevel(); | |
266 elseif event == "ITEM_UNLOCKED" then | 76 elseif event == "ITEM_UNLOCKED" then |
267 AskMrRobot.On_ITEM_UNLOCKED() | 77 --AskMrRobot.On_ITEM_UNLOCKED() |
268 elseif event == "PLAYER_LOGOUT" then | 78 |
269 -- doing nothing right now, but leaving this in case we need something here | 79 elseif event == "PLAYER_ENTERING_WORLD" then |
270 elseif event == "PLAYER_ENTERING_WORLD" then | 80 AskMrRobot.RecordLogin() |
271 | |
272 -- delete entries that are more than 10 days old to prevent the table from growing indefinitely | |
273 if AmrSettings.Logins and #AmrSettings.Logins > 0 then | |
274 local now = time() | |
275 local oldDuration = 60 * 60 * 24 * 10 | |
276 local entryTime | |
277 repeat | |
278 -- parse entry and get time | |
279 local parts = {} | |
280 for part in string.gmatch(AmrSettings.Logins[1], "([^;]+)") do | |
281 tinsert(parts, part) | |
282 end | |
283 entryTime = tonumber(parts[3]) | |
284 | |
285 -- entries are in order, remove first entry if it is old | |
286 if difftime(now, entryTime) > oldDuration then | |
287 tremove(AmrSettings.Logins, 1) | |
288 end | |
289 until #AmrSettings.Logins == 0 or difftime(now, entryTime) <= oldDuration | |
290 end | |
291 | |
292 -- record the time a player logs in, used to figure out which player logged which parts of their log file | |
293 local key = AmrRealmName .. ";" .. AmrCharacterName .. ";" | |
294 local loginData = key .. time() | |
295 if AmrSettings.Logins and #AmrSettings.Logins > 0 then | |
296 local last = AmrSettings.Logins[#AmrSettings.Logins] | |
297 if string.len(last) >= string.len(key) and string.sub(last, 1, string.len(key)) ~= key then | |
298 table.insert(AmrSettings.Logins, loginData) | |
299 end | |
300 else | |
301 table.insert(AmrSettings.Logins, loginData) | |
302 end | |
303 | 81 |
304 elseif event == "PLAYER_REGEN_DISABLED" then | 82 elseif event == "PLAYER_REGEN_DISABLED" then |
305 | |
306 -- send data about this character when a player enters combat in a supported zone | 83 -- send data about this character when a player enters combat in a supported zone |
307 if AskMrRobot.IsSupportedInstance() then | 84 if AskMrRobot.IsSupportedInstance() then |
308 local t = time() | 85 local t = time() |
309 AskMrRobot.SaveAll() | 86 AskMrRobot.SaveAll() |
310 AskMrRobot.ExportToAddonChat(t) | 87 AskMrRobot.ExportToAddonChat(t) |
311 AskMrRobot.ExportLoggingData(t) | 88 AskMrRobot.CombatLogTab.SaveExtras(t) |
312 end | 89 end |
313 | 90 |
314 elseif event == "CHAT_MSG_ADDON" then | 91 elseif event == "CHAT_MSG_ADDON" then |
315 local chatPrefix, message = select(1, ...) | 92 local chatPrefix, message = select(1, ...) |
316 local isLogging = AskMrRobot_ReforgeFrame.combatLogTab:IsLogging() | 93 local isLogging = AskMrRobot.CombatLogTab.IsLogging() |
317 if (isLogging and chatPrefix == AskMrRobot.ChatPrefix) then | 94 if (isLogging and chatPrefix == AskMrRobot.ChatPrefix) then |
318 AskMrRobot_ReforgeFrame.combatLogTab:ReadAddonMessage(message) | 95 AskMrRobot.mainWindow.combatLogTab:ReadAddonMessage(message) |
319 end | 96 end |
97 | |
320 elseif event == "UPDATE_INSTANCE_INFO" or event == "PLAYER_DIFFICULTY_CHANGED" then | 98 elseif event == "UPDATE_INSTANCE_INFO" or event == "PLAYER_DIFFICULTY_CHANGED" then |
321 AskMrRobot_ReforgeFrame.combatLogTab:UpdateAutoLogging() | 99 AskMrRobot.mainWindow.combatLogTab:UpdateAutoLogging() |
100 | |
322 end | 101 end |
323 | 102 |
324 end | 103 end |
325 | 104 |
326 AskMrRobot.eventListener:SetScript("OnEvent", AskMrRobot.eventListener.OnEvent); | 105 AskMrRobot.eventListener:SetScript("OnEvent", AskMrRobot.eventListener.OnEvent) |
327 | 106 |
328 local function parseItemLink(input) | |
329 local itemId, enchantId, gemEnchantId1, gemEnchantId2, gemEnchantId3, gemEnchantId4, suffixId, _, _, reforgeId, upgradeId = string.match(input, "^|.-|Hitem:(%d+):(%d+):(%d+):(%d+):(%d+):(%d+):(-?%d+):(-?%d+):(-?%d+):(%d+):(%d+)|"); | |
330 local item = {} | |
331 item.itemId = tonumber(itemId) | |
332 item.suffixId = tonumber(suffixId) | |
333 item.enchantId = tonumber(enchantId) | |
334 item.reforgeId = tonumber(reforgeId) | |
335 item.upgradeId = tonumber(upgradeId) | |
336 item.gemEnchantIds = { tonumber(gemEnchantId1), tonumber(gemEnchantId2), tonumber(gemEnchantId3), tonumber(gemEnchantId4) } | |
337 return item | |
338 end | |
339 | 107 |
340 SLASH_AMR1 = "/amr"; | 108 SLASH_AMR1 = "/amr"; |
341 function SlashCmdList.AMR(msg) | 109 function SlashCmdList.AMR(msg) |
342 | 110 |
343 if msg == 'toggle' then | 111 if msg == 'toggle' then |
344 AskMrRobot_ReforgeFrame:Toggle() | 112 AskMrRobot.mainWindow:Toggle() |
345 elseif msg == 'show' then | 113 elseif msg == 'show' then |
346 AskMrRobot_ReforgeFrame:Show() | 114 AskMrRobot.mainWindow:Show() |
347 elseif msg == 'hide' then | 115 elseif msg == 'hide' then |
348 AskMrRobot_ReforgeFrame:Hide() | 116 AskMrRobot.mainWindow:Hide() |
349 elseif msg == 'export' then | 117 elseif msg == 'export' then |
350 OnExport() | 118 AskMrRobot.mainWindow.exportTab:Show() |
351 elseif msg == 'wipe' then | 119 elseif msg == 'wipe' then |
352 AskMrRobot_ReforgeFrame.combatLogTab:LogWipe() | 120 AskMrRobot.mainWindow.combatLogTab:LogWipe() |
353 elseif msg == 'unwipe' then | 121 elseif msg == 'unwipe' then |
354 AskMrRobot_ReforgeFrame.combatLogTab:LogUnwipe() | 122 AskMrRobot.mainWindow.combatLogTab:LogUnwipe() |
355 else | 123 else |
356 print(L.AMR_SLASH_COMMAND_TEXT_1 .. L.AMR_SLASH_COMMAND_TEXT_2 .. L.AMR_SLASH_COMMAND_TEXT_3 .. L.AMR_SLASH_COMMAND_TEXT_4 .. L.AMR_SLASH_COMMAND_TEXT_5 .. L.AMR_SLASH_COMMAND_TEXT_6 .. L.AMR_SLASH_COMMAND_TEXT_7) | 124 print(L.AMR_SLASH_COMMAND_TEXT_1 .. L.AMR_SLASH_COMMAND_TEXT_2 .. L.AMR_SLASH_COMMAND_TEXT_3 .. L.AMR_SLASH_COMMAND_TEXT_4 .. L.AMR_SLASH_COMMAND_TEXT_5 .. L.AMR_SLASH_COMMAND_TEXT_6 .. L.AMR_SLASH_COMMAND_TEXT_7) |
357 end | 125 end |
358 end | 126 end |
359 | 127 |
128 -- initialize settings when the addon loads | |
129 function AskMrRobot.InitializeSettings() | |
130 | |
131 -- global settings | |
132 if not AmrSettings then AmrSettings = {} end | |
133 if not AmrSettings.Logins then AmrSettings.Logins = {} end | |
134 | |
135 -- per-character settings | |
136 if not AmrDb then AmrDb = {} end | |
137 | |
138 -- addon stuff | |
139 if not AmrDb.IconInfo then AmrDb.IconInfo = {} end | |
140 if not AmrDb.Options then AmrDb.Options = {} end | |
141 if not AmrDb.LastCharacterImport then AmrDb.LastCharacterImport = "" end | |
142 if not AmrDb.LastCharacterImportDate then AmrDb.LastCharacterImportDate = "" end | |
143 | |
144 if not AmrDb.SendSettings then | |
145 AmrDb.SendSettings = { | |
146 SendGems = true, | |
147 SendEnchants = true, | |
148 SendEnchantMaterials = true, | |
149 SendToType = "a friend", | |
150 SendTo = "" | |
151 } | |
152 end | |
153 | |
154 -- character stuff | |
155 AskMrRobot.ScanCharacter() | |
156 if not AmrDb.BankItems then AmrDb.BankItems = {} end | |
157 if not AmrDb.BagItems then AmrDb.BagItems = {} end | |
158 if not AmrDb.Currencies then AmrDb.Currencies = {} end | |
159 if not AmrDb.Reps then AmrDb.Reps = {} end | |
160 -- data saved for both specs | |
161 if not AmrDb.Specs then AmrDb.Specs = {} end | |
162 if not AmrDb.Glyphs then AmrDb.Glyphs = {} end | |
163 if not AmrDb.Talents then AmrDb.Talents = {} end | |
164 if not AmrDb.Equipped then AmrDb.Equipped = {} end | |
165 | |
166 -- combat log specific settings | |
167 AskMrRobot.CombatLogTab.InitializeVariable() | |
168 end | |
169 | |
170 -- record logins when the addon starts up, used to help figure out which character logged which parts of a log file | |
171 function AskMrRobot.RecordLogin() | |
172 | |
173 -- delete entries that are more than 10 days old to prevent the table from growing indefinitely | |
174 if AmrSettings.Logins and #AmrSettings.Logins > 0 then | |
175 local now = time() | |
176 local oldDuration = 60 * 60 * 24 * 10 | |
177 local entryTime | |
178 repeat | |
179 -- parse entry and get time | |
180 local parts = {} | |
181 for part in string.gmatch(AmrSettings.Logins[1], "([^;]+)") do | |
182 tinsert(parts, part) | |
183 end | |
184 entryTime = tonumber(parts[3]) | |
185 | |
186 -- entries are in order, remove first entry if it is old | |
187 if difftime(now, entryTime) > oldDuration then | |
188 tremove(AmrSettings.Logins, 1) | |
189 end | |
190 until #AmrSettings.Logins == 0 or difftime(now, entryTime) <= oldDuration | |
191 end | |
192 | |
193 -- record the time a player logs in, used to figure out which player logged which parts of their log file | |
194 local key = AmrDb.RealmName .. ";" .. AmrDb.CharacterName .. ";" | |
195 local loginData = key .. time() | |
196 if AmrSettings.Logins and #AmrSettings.Logins > 0 then | |
197 local last = AmrSettings.Logins[#AmrSettings.Logins] | |
198 if string.len(last) >= string.len(key) and string.sub(last, 1, string.len(key)) ~= key then | |
199 table.insert(AmrSettings.Logins, loginData) | |
200 end | |
201 else | |
202 table.insert(AmrSettings.Logins, loginData) | |
203 end | |
204 end | |
205 | |
206 function AskMrRobot.InitializeMinimap() | |
207 | |
208 -- minimap icon and data broker icon plugin thingy | |
209 _amrLDB = LibStub("LibDataBroker-1.1"):NewDataObject("AskMrRobot", { | |
210 type = "launcher", | |
211 text = "Ask Mr. Robot", | |
212 icon = "Interface\\AddOns\\AskMrRobot\\Media\\icon", | |
213 OnClick = function() | |
214 if IsControlKeyDown() then | |
215 AskMrRobot.mainWindow.combatLogTab:LogWipe() | |
216 elseif IsModifiedClick("CHATLINL") then | |
217 AskMrRobot.mainWindow.exportTab:Show() | |
218 else | |
219 AskMrRobot.mainWindow:Toggle() | |
220 end | |
221 end, | |
222 OnTooltipShow = function(tt) | |
223 tt:AddLine("Ask Mr. Robot", 1, 1, 1); | |
224 tt:AddLine(" "); | |
225 tt:AddLine(L.AMR_ON_EVENT_TOOLTIP) | |
226 end | |
227 }); | |
228 | |
229 AskMrRobot.AmrUpdateMinimap() | |
230 end | |
231 | |
232 function AskMrRobot.AmrUpdateMinimap() | |
233 if AmrDb.Options.hideMapIcon then | |
234 if _minimapIcon then | |
235 _minimapIcon:Hide("AskMrRobot") | |
236 end | |
237 else | |
238 if not _minimapIcon then | |
239 _minimapIcon = LibStub("LibDBIcon-1.0") | |
240 _minimapIcon:Register("AskMrRobot", _amrLDB, AmrDb.IconInfo) | |
241 end | |
242 | |
243 if AskMrRobot.CombatLogTab.IsLogging() then | |
244 _amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon_green' | |
245 else | |
246 _amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon' | |
247 end | |
248 | |
249 _minimapIcon:Show("AskMrRobot") | |
250 end | |
251 end | |
252 | |
253 | |
360 function AskMrRobot.SaveAll() | 254 function AskMrRobot.SaveAll() |
255 AskMrRobot.ScanCharacter() | |
361 AskMrRobot.ScanBank() | 256 AskMrRobot.ScanBank() |
362 AskMrRobot.SaveBags() | 257 AskMrRobot.ScanBags() |
363 AskMrRobot.SaveEquiped() | 258 AskMrRobot.ScanEquipped() |
364 AskMrRobot.GetCurrencies() | 259 AskMrRobot.GetCurrencies() |
365 AskMrRobot.GetGold() | 260 AskMrRobot.GetReputations() |
366 AskMrRobot.GetAmrSpecializations() | 261 AskMrRobot.GetSpecs() |
367 AskMrRobot.GetAmrProfessions() | 262 end |
368 AskMrRobot.GetRace() | 263 |
369 AskMrRobot.GetLevel() | 264 -- gets all basic character properties |
370 AskMrRobot.GetAmrGlyphs() | 265 function AskMrRobot.ScanCharacter() |
371 AskMrRobot.GetAmrTalents() | 266 AmrDb.RealmName = GetRealmName() |
372 --ReloadUI() | 267 AmrDb.CharacterName = UnitName("player") |
373 end | 268 AmrDb.Guild = GetGuildInfo("player") |
374 | 269 AmrDb.ActiveSpec = GetActiveSpecGroup() |
375 local function InitIcon() | 270 AmrDb.Level = UnitLevel("player"); |
376 icon = LibStub("LibDBIcon-1.0"); | 271 |
377 icon:Register("AskMrRobot", amrLDB, AmrIconInfo); | 272 local cls, clsEn = UnitClass("player") |
378 end | 273 AmrDb.Class = clsEn; |
379 | 274 |
380 function AskMrRobot.AmrUpdateMinimap() | 275 local race, raceEn = UnitRace("player") |
381 if AmrOptions.hideMapIcon then | 276 AmrDb.Race = raceEn; |
382 if icon then | 277 AmrDb.Faction = UnitFactionGroup("player") |
383 icon:Hide("AskMrRobot"); | 278 |
384 end | 279 AskMrRobot.GetAmrProfessions() |
385 else | |
386 if not icon then | |
387 InitIcon() | |
388 end | |
389 --if AskMrRobot_ReforgeFrame.combatLogTab:IsLogging() then | |
390 if AskMrRobot.CombatLogTab.IsLogging(nil) then | |
391 amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon_green' | |
392 else | |
393 amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon' | |
394 end | |
395 icon:Show("AskMrRobot"); | |
396 end | |
397 end | |
398 | |
399 local function getToolTipText(tip) | |
400 return EnumerateTooltipLines_helper(tip:GetRegions()) | |
401 end | |
402 | |
403 local bagItems = {} | |
404 local bagItemsWithCount = {} | |
405 | |
406 function AskMrRobot.ScanBag(bagId) | |
407 local numSlots = GetContainerNumSlots(bagId); | |
408 for slotId = 1, numSlots do | |
409 local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId); | |
410 if itemLink ~= nil then | |
411 local itemData = parseItemLink(itemLink) | |
412 if itemData.itemId ~= nil then | |
413 tinsert(bagItems, itemLink); | |
414 tinsert(bagItemsWithCount, {link = itemLink, count = itemCount}) | |
415 end | |
416 end | |
417 end | |
418 end | |
419 | |
420 local BACKPACK_CONTAINER = 0; | |
421 local BANK_CONTAINER = -1; | |
422 | |
423 function AskMrRobot.ScanEquiped() | |
424 local equipedItems = {}; | |
425 for slotNum = 1, #AskMrRobot.slotIds do | |
426 local slotId = AskMrRobot.slotIds[slotNum]; | |
427 local itemLink = GetInventoryItemLink("player", slotId); | |
428 if (itemLink ~= nil) then | |
429 equipedItems[slotId .. ""] = itemLink; | |
430 end | |
431 end | |
432 return equipedItems | |
433 end | |
434 | |
435 function AskMrRobot.SaveEquiped() | |
436 AmrEquipedItems = AskMrRobot.ScanEquiped(); | |
437 end | |
438 | |
439 function AskMrRobot.ScanBags() | |
440 bagItems = {} | |
441 bagItemsWithCount = {} | |
442 | |
443 AskMrRobot.ScanBag(BACKPACK_CONTAINER); -- backpack | |
444 | |
445 for bagId = 1, NUM_BAG_SLOTS do | |
446 AskMrRobot.ScanBag(bagId); | |
447 end | |
448 | |
449 | |
450 return bagItems, bagItemsWithCount | |
451 end | |
452 | |
453 function AskMrRobot.SaveBags() | |
454 AmrBagItems, _ = AskMrRobot.ScanBags() | |
455 end | |
456 | |
457 function AskMrRobot.GetGold() | |
458 AmrGold = GetMoney(); | |
459 end | |
460 | |
461 local lastBankBagId = nil; | |
462 local lastBankSlotId = nil; | |
463 local bankItems = {}; | |
464 local bankItemsAndCount = {}; | |
465 AmrBankItemsAndCounts = {}; | |
466 | |
467 local function ScanBankBag(bagId) | |
468 local numSlots = GetContainerNumSlots(bagId); | |
469 for slotId = 1, numSlots do | |
470 local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId); | |
471 if itemLink ~= nil then | |
472 local itemData = parseItemLink(itemLink) | |
473 if itemData.itemId ~= nil then | |
474 lastBankBagId = bagId; | |
475 lastBankSlotId = slotId; | |
476 tinsert(bankItems, itemLink); | |
477 tinsert(bankItemsAndCount, {link = itemLink, count = itemCount}) | |
478 end | |
479 end | |
480 end | |
481 end | |
482 | |
483 function AskMrRobot.ScanBank() | |
484 | |
485 bankItems = {}; | |
486 bankItemsAndCount = {} | |
487 | |
488 ScanBankBag(BANK_CONTAINER); | |
489 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do | |
490 ScanBankBag(bagId); | |
491 end | |
492 | |
493 -- see if the scan completed before the window closed | |
494 if lastBankBagId ~= nil then | |
495 local itemLink = GetContainerItemLink(lastBankBagId, lastBankSlotId); | |
496 if itemLink ~= nil then --still open | |
497 AmrBankItems = bankItems; | |
498 AmrBankItemsAndCounts = bankItemsAndCount | |
499 end | |
500 end | |
501 end | |
502 | |
503 local function GetCurrencyAmount(index) | |
504 local localized_label, amount, icon_file_name = GetCurrencyInfo(index); | |
505 return amount; | |
506 end | |
507 | |
508 function AskMrRobot.GetCurrencies() | |
509 local currencies = {}; | |
510 local currencyList = {61, 81, 241, 361, 384, 394, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 416, 515, 614, 615, 676, 679}; | |
511 | |
512 for i, currency in pairs(currencyList) do | |
513 local amount = GetCurrencyAmount(currency); | |
514 if amount ~= 0 then | |
515 currencies[currencyList[i]] = amount; | |
516 end | |
517 end | |
518 AmrCurrencies = currencies; | |
519 end | |
520 | |
521 local function GetAmrSpecialization(specGroup) | |
522 local spec = GetSpecialization(false, false, specGroup); | |
523 return spec and GetSpecializationInfo(spec); | |
524 end | |
525 | |
526 function AskMrRobot.GetAmrSpecializations() | |
527 | |
528 AmrSpecializations = {}; | |
529 | |
530 AmrActiveSpec = GetActiveSpecGroup(); | |
531 | |
532 for group = 1, 2 do | |
533 AmrSpecializations[group .. ""] = GetAmrSpecialization(group) | |
534 end | |
535 | |
536 -- Death Knight | |
537 -- 250 - Blood | |
538 -- 251 - Frost | |
539 -- 252 - Unholy | |
540 -- Druid | |
541 -- 102 - Balance | |
542 -- 103 - Feral Combat | |
543 -- 104 - Guardian | |
544 -- 105 - Restoration | |
545 -- Hunter | |
546 -- 253 - Beast Mastery | |
547 -- 254 - Marksmanship | |
548 -- 255 - Survival | |
549 -- Mage | |
550 -- 62 - Arcane | |
551 -- 63 - Fire | |
552 -- 64 - Frost | |
553 -- Monk | |
554 -- 268 - Brewmaster | |
555 -- 269 - Windwalker | |
556 -- 270 - Mistweaver | |
557 -- Paladin | |
558 -- 65 - Holy | |
559 -- 66 - Protection | |
560 -- 70 - Retribution | |
561 -- Priest | |
562 -- 256 Discipline | |
563 -- 257 Holy | |
564 -- 258 Shadow | |
565 -- Rogue | |
566 -- 259 - Assassination | |
567 -- 260 - Combat | |
568 -- 261 - Subtlety | |
569 -- Shaman | |
570 -- 262 - Elemental | |
571 -- 263 - Enhancement | |
572 -- 264 - Restoration | |
573 -- Warlock | |
574 -- 265 - Affliction | |
575 -- 266 - Demonology | |
576 -- 267 - Destruction | |
577 -- Warrior | |
578 -- 71 - Arms | |
579 -- 72 - Fury | |
580 -- 73 - Protection | |
581 end | 280 end |
582 | 281 |
583 function AskMrRobot.GetAmrProfessions() | 282 function AskMrRobot.GetAmrProfessions() |
584 | 283 |
585 local profMap = { | 284 local profMap = { |
599 [393] = "Skinning", | 298 [393] = "Skinning", |
600 [197] = "Tailoring" | 299 [197] = "Tailoring" |
601 } | 300 } |
602 | 301 |
603 local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions(); | 302 local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions(); |
604 AmrProfessions = {}; | 303 AmrDb.Professions = {}; |
605 if prof1 then | 304 if prof1 then |
606 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof1); | 305 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof1); |
607 if profMap[skillLine] ~= nil then | 306 if profMap[skillLine] ~= nil then |
608 AmrProfessions[profMap[skillLine]] = skillLevel; | 307 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
609 end | 308 end |
610 end | 309 end |
611 if prof2 then | 310 if prof2 then |
612 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof2); | 311 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof2); |
613 if profMap[skillLine] ~= nil then | 312 if profMap[skillLine] ~= nil then |
614 AmrProfessions[profMap[skillLine]] = skillLevel; | 313 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
615 end | 314 end |
616 end | 315 end |
617 if archaeology then | 316 if archaeology then |
618 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(archaeology); | 317 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(archaeology); |
619 if profMap[skillLine] ~= nil then | 318 if profMap[skillLine] ~= nil then |
620 AmrProfessions[profMap[skillLine]] = skillLevel; | 319 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
621 end | 320 end |
622 end | 321 end |
623 if fishing then | 322 if fishing then |
624 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(fishing); | 323 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(fishing); |
625 if profMap[skillLine] ~= nil then | 324 if profMap[skillLine] ~= nil then |
626 AmrProfessions[profMap[skillLine]] = skillLevel; | 325 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
627 end | 326 end |
628 end | 327 end |
629 if cooking then | 328 if cooking then |
630 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(cooking); | 329 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(cooking); |
631 if profMap[skillLine] ~= nil then | 330 if profMap[skillLine] ~= nil then |
632 AmrProfessions[profMap[skillLine]] = skillLevel; | 331 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
633 end | 332 end |
634 end | 333 end |
635 if firstAid then | 334 if firstAid then |
636 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(firstAid); | 335 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(firstAid); |
637 if profMap[skillLine] ~= nil then | 336 if profMap[skillLine] ~= nil then |
638 AmrProfessions[profMap[skillLine]] = skillLevel; | 337 AmrDb.Professions[profMap[skillLine]] = skillLevel; |
639 end | 338 end |
640 end | 339 end |
641 end | 340 end |
642 | 341 |
643 function AskMrRobot.GetRace() | 342 |
644 local race, raceEn = UnitRace("player"); | 343 -- use some local variables to deal with the fact that a user can close the bank before a scan completes |
645 AmrRace = raceEn; | 344 local _lastBankBagId = nil |
646 AmrFaction = UnitFactionGroup("player"); | 345 local _lastBankSlotId = nil |
647 end | 346 local BACKPACK_CONTAINER = 0 |
648 | 347 local BANK_CONTAINER = -1 |
649 function AskMrRobot.GetLevel() | 348 |
650 AmrLevel = UnitLevel("player"); | 349 local function scanBag(bagId, isBank, bagTable, bagItemsWithCount) |
651 end | 350 local numSlots = GetContainerNumSlots(bagId) |
652 | 351 for slotId = 1, numSlots do |
653 local SlotNames = { | 352 local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId) |
654 "HeadSlot", | 353 -- we skip any stackable item, as far as we know, there is no equippable gear that can be stacked |
655 "NeckSlot", | 354 if itemLink ~= nil then |
656 "ShoulderSlot", | 355 local itemData = AskMrRobot.parseItemLink(itemLink) |
657 "ShirtSlot", | 356 if itemData ~= nil then |
658 "ChestSlot", | 357 if itemCount == 1 then |
659 "WaistSlot", | 358 if isBank then |
660 "LegsSlot", | 359 _lastBankBagId = bagId |
661 "FeetSlot", | 360 _lastBankSlotId = slotId |
662 "WristSlot", | 361 end |
663 "HandsSlot", | 362 tinsert(bagTable, itemLink) |
664 "Finger0Slot", | 363 end |
665 "Finger1Slot", | 364 if bagItemsWithCount then |
666 "Trinket0Slot", | 365 if bagItemsWithCount[itemData.id] then |
667 "Trinket1Slot", | 366 bagItemsWithCount[itemData.id] = bagItemsWithCount[itemData.id] + itemCount |
668 "BackSlot", | 367 else |
669 "MainHandSlot", | 368 bagItemsWithCount[itemData.id] = itemCount |
670 "SecondaryHandSlot", | 369 end |
671 -- "RangedSlot", | 370 end |
672 "TabardSlot", | 371 end |
673 } | 372 end |
674 | 373 end |
675 local function GetAmrTalentsForSpec(spec) | 374 end |
375 | |
376 function AskMrRobot.ScanBank(bankItemsWithCount) | |
377 local bankItems = {} | |
378 local bankItemsAndCounts = {} | |
379 | |
380 scanBag(BANK_CONTAINER, true, bankItems, bankItemsAndCounts) | |
381 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do | |
382 scanBag(bagId, true, bankItems, bankItemsAndCounts) | |
383 end | |
384 | |
385 -- see if the scan completed before the window closed, otherwise we don't overwrite with partial data | |
386 if _lastBankBagId ~= nil then | |
387 local itemLink = GetContainerItemLink(_lastBankBagId, _lastBankSlotId) | |
388 if itemLink ~= nil then --still open | |
389 AmrDb.BankItems = bankItems | |
390 AmrDb.BankItemsAndCounts = bankItemsAndCounts | |
391 end | |
392 end | |
393 end | |
394 | |
395 function AskMrRobot.ScanBags(bagItemsWithCount) | |
396 local bagItems = {} | |
397 scanBag(BACKPACK_CONTAINER, false, bagItems, bagItemsWithCount) -- backpack | |
398 for bagId = 1, NUM_BAG_SLOTS do | |
399 scanBag(bagId, false, bagItems, bagItemsWithCount) | |
400 end | |
401 AmrDb.BagItems = bagItems | |
402 end | |
403 | |
404 function AskMrRobot.ScanEquipped() | |
405 local equippedItems = {}; | |
406 for slotNum = 1, #AskMrRobot.slotIds do | |
407 local slotId = AskMrRobot.slotIds[slotNum]; | |
408 local itemLink = GetInventoryItemLink("player", slotId); | |
409 if (itemLink ~= nil) then | |
410 equippedItems[slotId] = itemLink; | |
411 end | |
412 end | |
413 | |
414 -- store last-seen equipped gear for each spec | |
415 AmrDb.Equipped[GetActiveSpecGroup()] = equippedItems | |
416 end | |
417 | |
418 | |
419 local function getCurrencyAmount(index) | |
420 local localized_label, amount, icon_file_name = GetCurrencyInfo(index); | |
421 return amount; | |
422 end | |
423 | |
424 function AskMrRobot.GetCurrencies() | |
425 local currencies = {}; | |
426 currencies[-1] = GetMoney() | |
427 | |
428 local currencyList = {61, 81, 241, 361, 384, 394, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 416, 515, 614, 615, 676, 679} | |
429 for i, currency in pairs(currencyList) do | |
430 local amount = getCurrencyAmount(currency) | |
431 if amount ~= 0 then | |
432 currencies[currency] = amount | |
433 end | |
434 end | |
435 | |
436 AmrDb.Currencies = currencies | |
437 end | |
438 | |
439 | |
440 local function getRepStanding(factionId) | |
441 local name, description, standingId, _ = GetFactionInfoByID(factionId) | |
442 return standingId - 1; -- our rep enum correspond to what the armory returns, are 1 less than what the game returns | |
443 end | |
444 | |
445 function AskMrRobot.GetReputations() | |
446 local reps = {} | |
447 | |
448 local repList = {1375,1376,1270,1269,1341,1337,1387,1388,1435} | |
449 for i, repId in pairs(repList) do | |
450 local standing = getRepStanding(repId) | |
451 if standing >= 0 then | |
452 reps[repId] = standing | |
453 end | |
454 end | |
455 | |
456 AmrDb.Reps = reps; | |
457 end | |
458 | |
459 | |
460 local function getSpecId(specGroup) | |
461 local spec = GetSpecialization(false, false, specGroup); | |
462 return spec and GetSpecializationInfo(spec); | |
463 end | |
464 | |
465 local function getTalents(specGroup) | |
676 local talentInfo = {} | 466 local talentInfo = {} |
677 local maxTiers = 6 | 467 local maxTiers = 7 |
678 for talent = 1, GetNumTalents() do | 468 for tier = 1, maxTiers do |
679 local name, texture, tier, column, selected, available = GetTalentInfo(talent, false, spec) | 469 for col = 1, 3 do |
680 if tier > maxTiers then | 470 local id, name, texture, selected, available = GetTalentInfo(tier, col, specGroup) |
681 maxTiers = tier | 471 if selected then |
682 end | 472 talentInfo[tier] = col |
683 if selected then | 473 end |
684 talentInfo[tier] = column | 474 end |
685 end | |
686 end | 475 end |
687 | 476 |
688 local str = "" | 477 local str = "" |
689 for i = 1, maxTiers do | 478 for i = 1, maxTiers do |
690 if talentInfo[i] then | 479 if talentInfo[i] then |
695 end | 484 end |
696 | 485 |
697 return str | 486 return str |
698 end | 487 end |
699 | 488 |
700 function AskMrRobot.GetAmrTalents() | 489 local function getGlyphs(specGroup) |
701 AmrTalents = {} | |
702 for spec = 1, GetNumSpecGroups() do | |
703 AmrTalents[spec] = GetAmrTalentsForSpec(spec); | |
704 end | |
705 end | |
706 | |
707 local function GetAmrGlyphsForSpec(spec) | |
708 local glyphs = {} | 490 local glyphs = {} |
709 for i = 1, NUM_GLYPH_SLOTS do | 491 for i = 1, NUM_GLYPH_SLOTS do |
710 local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, spec) | 492 local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, specGroup) |
711 if (glyphID) then | 493 if (glyphID) then |
712 tinsert(glyphs, glyphSpellID) | 494 tinsert(glyphs, glyphSpellID) |
713 end | 495 end |
714 end | 496 end |
715 return glyphs; | 497 return glyphs; |
716 end | 498 end |
717 | 499 |
718 function AskMrRobot.GetAmrGlyphs() | 500 -- get specs, talents, and glyphs |
719 AmrGlyphs = {} | 501 function AskMrRobot.GetSpecs() |
720 for spec = 1, GetNumSpecGroups() do | 502 |
721 AmrGlyphs[spec] = GetAmrGlyphsForSpec(spec) | 503 AmrDb.Specs = {} |
722 end | 504 AmrDb.Talents = {} |
723 end | 505 AmrDb.Glyphs = {} |
724 | 506 |
725 --[[ | 507 for group = 1, GetNumSpecGroups() do |
726 local function ItemLinkToExportString(itemLink, slot) | 508 -- spec, convert game spec id to one of our spec ids |
727 local itemData = parseItemLink(itemLink) | 509 local specId = getSpecId(group) |
728 local ret = {} | 510 if specId then |
729 table.insert(ret, slot) | 511 AmrDb.Specs[group] = AskMrRobot.specIds[specId] |
730 table.insert(ret, itemData.itemId) | 512 else |
731 table.insert(ret, itemData.suffixId) | 513 AmrDb.Specs[group] = 0 |
732 table.insert(ret, itemData.upgradeId) | 514 end |
733 table.insert(ret, itemData.gemEnchantIds[1]) | 515 |
734 table.insert(ret, itemData.gemEnchantIds[2]) | 516 AmrDb.Talents[group] = getTalents(group) |
735 table.insert(ret, itemData.gemEnchantIds[3]) | 517 AmrDb.Glyphs[group] = getGlyphs(group) |
736 table.insert(ret, itemData.enchantId) | 518 end |
737 table.insert(ret, itemData.reforgeId) | 519 end |
738 return table.concat(ret, ":") | 520 |
739 end | 521 ---------------------------------------------------------------------------- |
740 ]] | 522 -- Export |
741 | 523 ---------------------------------------------------------------------------- |
742 local function toCompressedNumberList(list) | 524 |
525 function AskMrRobot.toCompressedNumberList(list) | |
743 -- ensure the values are numbers, sorted from lowest to highest | 526 -- ensure the values are numbers, sorted from lowest to highest |
744 local nums = {} | 527 local nums = {} |
745 for i, v in ipairs(list) do | 528 for i, v in ipairs(list) do |
746 table.insert(nums, tonumber(v)) | 529 table.insert(nums, tonumber(v)) |
747 end | 530 end |
756 end | 539 end |
757 | 540 |
758 return table.concat(ret, ",") | 541 return table.concat(ret, ",") |
759 end | 542 end |
760 | 543 |
761 -- create a more compact but less readable string | 544 -- appends a list of items to the export |
762 function AskMrRobot.ExportToCompressedString(includeInventory) | 545 local function appendItemsToExport(fields, itemObjects) |
546 | |
547 -- sort by item id so we can compress it more easily | |
548 table.sort(itemObjects, function(a, b) return a.id < b.id end) | |
549 | |
550 -- append to the export string | |
551 local prevItemId = 0 | |
552 local prevGemId = 0 | |
553 local prevEnchantId = 0 | |
554 local prevUpgradeId = 0 | |
555 local prevBonusId = 0 | |
556 for i, itemData in ipairs(itemObjects) do | |
557 local itemParts = {} | |
558 | |
559 table.insert(itemParts, itemData.id - prevItemId) | |
560 prevItemId = itemData.id | |
561 | |
562 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end | |
563 if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end | |
564 if itemData.upgradeId ~= 0 then | |
565 table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId)) | |
566 prevUpgradeId = itemData.upgradeId | |
567 end | |
568 if itemData.bonusIds then | |
569 for bIndex, bValue in ipairs(itemData.bonusIds) do | |
570 table.insert(itemParts, "b" .. (bValue - prevBonusId)) | |
571 prevBonusId = bValue | |
572 end | |
573 end | |
574 if itemData.gemIds[1] ~= 0 then | |
575 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId)) | |
576 prevGemId = itemData.gemIds[1] | |
577 end | |
578 if itemData.gemIds[2] ~= 0 then | |
579 table.insert(itemParts, "y" .. (itemData.gemIds[2] - prevGemId)) | |
580 prevGemId = itemData.gemIds[2] | |
581 end | |
582 if itemData.gemIds[3] ~= 0 then | |
583 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId)) | |
584 prevGemId = itemData.gemIds[3] | |
585 end | |
586 if itemData.enchantId ~= 0 then | |
587 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId)) | |
588 prevEnchantId = itemData.enchantId | |
589 end | |
590 | |
591 table.insert(fields, table.concat(itemParts, "")) | |
592 end | |
593 end | |
594 | |
595 -- create a compact string representing this player | |
596 -- if complete is true, exports everything (inventory, both specs) | |
597 -- otherwise only exports the player's active gear, spec, etc. | |
598 function AskMrRobot.ExportToCompressedString(complete) | |
763 local fields = {} | 599 local fields = {} |
764 | 600 |
765 -- compressed string uses a fixed order rather than inserting identifiers | 601 -- compressed string uses a fixed order rather than inserting identifiers |
766 table.insert(fields, GetAddOnMetadata(AskMrRobot.AddonName, "Version")) | 602 table.insert(fields, GetAddOnMetadata(AskMrRobot.AddonName, "Version")) |
767 table.insert(fields, AmrRealmName) | 603 table.insert(fields, AmrDb.RealmName) |
768 table.insert(fields, AmrCharacterName) | 604 table.insert(fields, AmrDb.CharacterName) |
769 | 605 |
770 -- guild name | 606 -- guild name |
771 local guildName = GetGuildInfo("player") | 607 local guildName = GetGuildInfo("player") |
772 if guildName == nil then | 608 if guildName == nil then |
773 table.insert(fields, "") | 609 table.insert(fields, "") |
774 else | 610 else |
775 table.insert(fields, guildName) | 611 table.insert(fields, guildName) |
776 end | 612 end |
777 | 613 |
778 -- race, default to pandaren if we can't read it for some reason | 614 -- race, default to pandaren if we can't read it for some reason |
779 local raceval = raceIds[AmrRace] | 615 local raceval = AskMrRobot.raceIds[AmrDb.Race] |
780 if raceval == nil then raceval = 13 end | 616 if raceval == nil then raceval = 13 end |
781 table.insert(fields, raceval) | 617 table.insert(fields, raceval) |
782 | 618 |
783 -- faction, default to alliance if we can't read it for some reason | 619 -- faction, default to alliance if we can't read it for some reason |
784 raceval = factionIds[AmrFaction] | 620 raceval = AskMrRobot.factionIds[AmrDb.Faction] |
785 if raceval == nil then raceval = 1 end | 621 if raceval == nil then raceval = 1 end |
786 table.insert(fields, raceval) | 622 table.insert(fields, raceval) |
787 | 623 |
788 table.insert(fields, AmrLevel) | 624 table.insert(fields, AmrDb.Level) |
789 | 625 |
790 local profs = {} | 626 local profs = {} |
791 local noprofs = true | 627 local noprofs = true |
792 if AmrProfessions then | 628 if AmrDb.Professions then |
793 for k, v in pairs(AmrProfessions) do | 629 for k, v in pairs(AmrDb.Professions) do |
794 local profval = professionIds[k] | 630 local profval = AskMrRobot.professionIds[k] |
795 if profval ~= nil then | 631 if profval ~= nil then |
796 noprofs = false | 632 noprofs = false |
797 table.insert(profs, profval .. ":" .. v) | 633 table.insert(profs, profval .. ":" .. v) |
798 end | 634 end |
799 end | 635 end |
803 table.insert(profs, "0:0") | 639 table.insert(profs, "0:0") |
804 end | 640 end |
805 | 641 |
806 table.insert(fields, table.concat(profs, ",")) | 642 table.insert(fields, table.concat(profs, ",")) |
807 | 643 |
808 if (AmrActiveSpec ~= nil) then | 644 -- export specs |
809 table.insert(fields, AmrActiveSpec) | 645 table.insert(fields, AmrDb.ActiveSpec) |
810 table.insert(fields, AmrSpecializations[AmrActiveSpec .. ""]) | 646 for spec = 1, 2 do |
811 table.insert(fields, AmrTalents[AmrActiveSpec]) | 647 if AmrDb.Specs[spec] and (complete or spec == AmrDb.ActiveSpec) then |
812 table.insert(fields, toCompressedNumberList(AmrGlyphs[AmrActiveSpec])) | 648 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block |
813 else | 649 table.insert(fields, AmrDb.Specs[spec]) |
814 table.insert(fields, "_") | 650 table.insert(fields, AmrDb.Talents[spec]) |
815 table.insert(fields, "_") | 651 table.insert(fields, AskMrRobot.toCompressedNumberList(AmrDb.Glyphs[spec])) |
816 table.insert(fields, "_") | 652 end |
817 table.insert(fields, "_") | 653 end |
818 end | 654 |
819 | 655 -- export equipped gear |
820 -- convert items to parsed objects, sorted by id | 656 if AmrDb.Equipped then |
821 local itemObjects = {} | 657 for spec = 1, 2 do |
822 if AmrEquipedItems then | 658 if AmrDb.Equipped[spec] and (complete or spec == AmrDb.ActiveSpec) then |
823 for k, v in pairs(AmrEquipedItems) do | 659 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block |
824 local itemData = parseItemLink(v) | 660 |
825 itemData.slot = k | 661 local itemObjects = {} |
826 table.insert(itemObjects, itemData) | 662 for k, v in pairs(AmrDb.Equipped[spec]) do |
827 end | 663 local itemData = AskMrRobot.parseItemLink(v) |
828 end | 664 itemData.slot = k |
829 | 665 table.insert(itemObjects, itemData) |
830 -- if desired, include bank/bag items too | 666 end |
831 if includeInventory then | 667 |
832 if AmrBagItems then | 668 appendItemsToExport(fields, itemObjects) |
833 for i, v in ipairs(AmrBagItems) do | 669 end |
834 local itemData = parseItemLink(v) | 670 end |
835 if itemData.itemId ~= nil then | 671 end |
672 | |
673 -- if doing a complete export, include reputations and bank/bag items too | |
674 if complete then | |
675 | |
676 -- export reputations | |
677 local reps = {} | |
678 local noreps = true | |
679 if AmrDb.Reps then | |
680 for k, v in pairs(AmrDb.Reps) do | |
681 noreps = false | |
682 table.insert(reps, k .. ":" .. v) | |
683 end | |
684 end | |
685 if noreps then | |
686 table.insert(reps, "_") | |
687 end | |
688 | |
689 table.insert(fields, ".r") | |
690 table.insert(fields, table.concat(reps, ",")) | |
691 | |
692 -- export bag and bank | |
693 local itemObjects = {} | |
694 if AmrDb.BagItems then | |
695 for i, v in ipairs(AmrDb.BagItems) do | |
696 local itemData = AskMrRobot.parseItemLink(v) | |
697 if itemData ~= nil then | |
836 table.insert(itemObjects, itemData) | 698 table.insert(itemObjects, itemData) |
837 end | 699 end |
838 end | 700 end |
839 end | 701 end |
840 if AmrBankItems then | 702 if AmrDb.BankItems then |
841 for i, v in ipairs(AmrBankItems) do | 703 for i, v in ipairs(AmrDb.BankItems) do |
842 local itemData = parseItemLink(v) | 704 local itemData = AskMrRobot.parseItemLink(v) |
843 if itemData.itemId ~= nil then | 705 if itemData ~= nil then |
844 table.insert(itemObjects, itemData) | 706 table.insert(itemObjects, itemData) |
845 end | 707 end |
846 end | 708 end |
847 end | 709 end |
848 end | 710 |
849 | 711 table.insert(fields, ".inv") |
850 -- sort by item id so we can compress it more easily | 712 appendItemsToExport(fields, itemObjects) |
851 table.sort(itemObjects, function(a, b) return a.itemId < b.itemId end) | |
852 | |
853 -- append to the export string | |
854 local prevItemId = 0 | |
855 local prevGemId = 0 | |
856 local prevEnchantId = 0 | |
857 for i, itemData in ipairs(itemObjects) do | |
858 | |
859 local itemParts = {} | |
860 | |
861 table.insert(itemParts, itemData.itemId - prevItemId) | |
862 prevItemId = itemData.itemId | |
863 | |
864 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end | |
865 if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end | |
866 if upgradeTable[itemData.upgradeId] ~= 0 then table.insert(itemParts, "u" .. upgradeTable[itemData.upgradeId]) end | |
867 if itemData.gemEnchantIds[1] ~= 0 then | |
868 table.insert(itemParts, "a" .. (itemData.gemEnchantIds[1] - prevGemId)) | |
869 prevGemId = itemData.gemEnchantIds[1] | |
870 end | |
871 if itemData.gemEnchantIds[2] ~= 0 then | |
872 table.insert(itemParts, "b" .. (itemData.gemEnchantIds[2] - prevGemId)) | |
873 prevGemId = itemData.gemEnchantIds[2] | |
874 end | |
875 if itemData.gemEnchantIds[3] ~= 0 then | |
876 table.insert(itemParts, "c" .. (itemData.gemEnchantIds[3] - prevGemId)) | |
877 prevGemId = itemData.gemEnchantIds[3] | |
878 end | |
879 if itemData.enchantId ~= 0 then | |
880 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId)) | |
881 prevEnchantId = itemData.enchantId | |
882 end | |
883 if itemData.reforgeId ~= 0 then table.insert(itemParts, "r" .. (itemData.reforgeId - 113)) end | |
884 | |
885 table.insert(fields, table.concat(itemParts, "")) | |
886 end | 713 end |
887 | 714 |
888 return "$" .. table.concat(fields, ";") .. "$" | 715 return "$" .. table.concat(fields, ";") .. "$" |
889 end | |
890 | |
891 local function GetPlayerExtraData(data, index) | |
892 | |
893 local unitId = "raid" .. index | |
894 | |
895 local guid = UnitGUID(unitId) | |
896 if guid == nil then | |
897 return nil | |
898 end | |
899 | |
900 local fields = {} | |
901 | |
902 local buffs = {} | |
903 for i=1,40 do | |
904 local _,_,_,count,_,_,_,_,_,_,spellId = UnitAura(unitId, i, "HELPFUL") | |
905 table.insert(buffs, spellId) | |
906 end | |
907 if #buffs == 0 then | |
908 table.insert(fields, "_") | |
909 else | |
910 table.insert(fields, toCompressedNumberList(buffs)) | |
911 end | |
912 | |
913 local petGuid = UnitGUID("raidpet" .. index) | |
914 if petGuid then | |
915 table.insert(fields, guid .. "," .. petGuid) | |
916 else | |
917 table.insert(fields, '_') | |
918 end | |
919 | |
920 local name = GetRaidRosterInfo(index) | |
921 local realm = GetRealmName() | |
922 local splitPos = string.find(name, "-") | |
923 if splitPos ~= nil then | |
924 realm = string.sub(name, splitPos + 1) | |
925 name = string.sub(name, 1, splitPos - 1) | |
926 end | |
927 | |
928 data[realm .. ":" .. name] = table.concat(fields, ";") | |
929 end | |
930 | |
931 function AskMrRobot.ExportLoggingData(timestamp) | |
932 | |
933 local isLogging = AskMrRobot_ReforgeFrame.combatLogTab:IsLogging() | |
934 if not isLogging then | |
935 return | |
936 end | |
937 | |
938 -- we only get extra information for people if in a raid | |
939 if not IsInRaid() then | |
940 return | |
941 end | |
942 | |
943 local data = {} | |
944 for i = 1,40 do | |
945 GetPlayerExtraData(data, i) | |
946 end | |
947 | |
948 AskMrRobot.CombatLogTab.SaveExtras(data, timestamp) | |
949 end | 716 end |
950 | 717 |
951 function AskMrRobot.ExportToAddonChat(timestamp) | 718 function AskMrRobot.ExportToAddonChat(timestamp) |
952 local msg = AskMrRobot.ExportToCompressedString(false) | 719 local msg = AskMrRobot.ExportToCompressedString(false) |
953 local msgPrefix = timestamp .. "\n" .. AmrRealmName .. "\n" .. AmrCharacterName .. "\n" | 720 local msgPrefix = timestamp .. "\n" .. AmrRealmName .. "\n" .. AmrCharacterName .. "\n" |
971 SendAddonMessage(AskMrRobot.ChatPrefix, msgPrefix .. "done", "RAID") | 738 SendAddonMessage(AskMrRobot.ChatPrefix, msgPrefix .. "done", "RAID") |
972 end | 739 end |
973 | 740 |
974 -- Create an export string that can be copied to the website | 741 -- Create an export string that can be copied to the website |
975 function AskMrRobot.ExportToString() | 742 function AskMrRobot.ExportToString() |
976 | |
977 --[[ | |
978 local fields = {} | |
979 | |
980 fields["realm"] = AmrRealmName | |
981 fields["name"] = AmrCharacterName | |
982 fields["race"] = AmrRace | |
983 fields["faction"] = AmrFaction | |
984 fields["level"] = AmrLevel | |
985 | |
986 local profs = {} | |
987 for k, v in pairs(AmrProfessions) do | |
988 table.insert(profs, k .. ":" .. v) | |
989 end | |
990 fields["professions"] = table.concat(profs, ",") | |
991 | |
992 if (AmrActiveSpec ~= nil) then | |
993 fields["activespec"] = AmrActiveSpec | |
994 fields["spec"] = AmrSpecializations[AmrActiveSpec .. ""] | |
995 fields["talents"] = AmrTalents[AmrActiveSpec] | |
996 fields["glyphs"] = table.concat(AmrGlyphs[AmrActiveSpec], ",") | |
997 end | |
998 | |
999 local items = {} | |
1000 for k, v in pairs(AmrEquipedItems) do | |
1001 table.insert(items, ItemLinkToExportString(v, k)) | |
1002 end | |
1003 for i, v in ipairs(AmrBagItems) do | |
1004 table.insert(items, ItemLinkToExportString(v, "-1")) | |
1005 end | |
1006 for i, v in ipairs(AmrBankItems) do | |
1007 table.insert(items, ItemLinkToExportString(v, "-1")) | |
1008 end | |
1009 fields["items"] = table.concat(items, "_") | |
1010 | |
1011 local fieldList = {} | |
1012 for k, v in pairs(fields) do | |
1013 table.insert(fieldList, k .. "=" .. v) | |
1014 end | |
1015 ]] | |
1016 | |
1017 --return table.concat(fieldList, ";") | |
1018 | |
1019 return AskMrRobot.ExportToCompressedString(true) | 743 return AskMrRobot.ExportToCompressedString(true) |
1020 --return AskMrRobot.ExportToAddonChat(time()) | 744 end |
1021 end | 745 |
1022 | 746 |
1023 local function parseGlyphs(input) | 747 ---------------------------------------------------------------------------- |
1024 local glyphs = {} | 748 -- Import |
1025 for glyph in string.gmatch(input, "([^,]+)") do | 749 ---------------------------------------------------------------------------- |
1026 tinsert(glyphs, glyph) | 750 |
1027 end | 751 -- imports will give us extra information about items, gems, and enchants |
1028 table.sort(glyphs) | 752 AskMrRobot.ExtraItemData = {} -- keyed by item id |
1029 return glyphs | 753 AskMrRobot.ExtraGemData = {} -- keyed by gem enchant id |
1030 end | 754 AskMrRobot.ExtraEnchantData = {} -- keyed by enchant id |
1031 | 755 |
1032 local function parseProfessions(input) | 756 -- the data that was last imported |
1033 local professions = {} | 757 AskMrRobot.ImportData = nil -- keyed by slot id |
1034 for prof, v in string.gmatch(input, "([^:,]+):([^,]+)") do | 758 |
1035 professions[prof] = tonumber(v); | 759 local MIN_IMPORT_VERSION = 2 |
1036 end | 760 |
1037 return professions; | 761 -- |
1038 end | 762 -- Import a character, returning nil on success, otherwise an error message, import result stored in AskMrRobot.ImportData |
1039 | 763 -- |
1040 local gemColorMapping = { | 764 function AskMrRobot.ImportCharacter(data) |
1041 y = 'Yellow', | 765 |
1042 b = 'Blue', | 766 -- make sure all data is up to date before importing |
1043 r = 'Red', | 767 AskMrRobot.SaveAll() |
1044 h = 'Hydraulic', | 768 |
1045 p = 'Prismatic', | 769 if data == nil or string.len(data) == 0 then |
1046 m = 'Meta', | 770 return L.AMR_IMPORT_ERROR_EMPTY |
1047 c = 'Cogwheel' | 771 end |
1048 } | 772 |
1049 | 773 local data1 = { strsplit("$", data) } |
1050 local function parseAmrItem(input) | 774 if #data1 ~= 3 then |
1051 local slot, itemId, suffixList, upgradeId, gemColorString, gemEnchantIdString, gemIdString, enchantId, reforgeId = string.match(input, "^(%d+):(%d+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):(%d+):(%d+)"); | 775 return L.AMR_IMPORT_ERROR_FORMAT |
1052 -- parse the gem enchant ids out of their comma seperated list | 776 end |
1053 local gems = {} | 777 |
1054 for gemEnchantId in string.gmatch(gemEnchantIdString, '(%d+)') do | 778 local parts = { strsplit(";", data1[2]) } |
1055 tinsert(gems, {enchantId = tonumber(gemEnchantId), id = 0}) | 779 |
1056 end | 780 -- require a minimum version |
1057 -- make sure we have 4 gem ids | 781 local ver = tonumber(parts[1]) |
1058 for i = #gems + 1, 4 do | 782 if ver < MIN_IMPORT_VERSION then |
1059 tinsert(gems, {enchantId = 0, id = 0}) | 783 return L.AMR_IMPORT_ERROR_VERSION |
1060 end | 784 end |
1061 -- parse the gem ids out of their comma seperated list | 785 |
1062 local gemIds = {} | 786 -- require realm/name match |
1063 i = 1 | 787 local realm = parts[2] |
1064 for gemId in string.gmatch(gemIdString, '(%d+)') do | 788 local name = parts[3] |
1065 gems[i].id = tonumber(gemId) | 789 if realm ~= AmrDb.RealmName or name ~= AmrDb.CharacterName then |
1066 i = i + 1 | 790 local badPers = name .. " (" .. realm .. ")" |
1067 end | 791 local goodPers = AmrDb.CharacterName .. " (" .. AmrDb.RealmName .. ")" |
1068 i = 1 | 792 return L.AMR_IMPORT_ERROR_CHAR:format(badPers, goodPers) |
1069 for gemColor in string.gmatch(gemColorString, '([^,])') do | 793 end |
1070 gems[i].color = gemColorMapping[gemColor] | 794 |
1071 i = i + 1 | 795 -- require race match |
1072 end | 796 local race = tonumber(parts[5]) |
1073 | 797 if race ~= AskMrRobot.raceIds[AmrDb.Race] then |
1074 -- parse the possible suffixes out of their comma seperated list and put them in a set (number -> bool) | 798 return L.AMR_IMPORT_ERROR_RACE |
1075 local suffixes = {} | 799 end |
1076 for suffixId in string.gmatch(suffixList, '(%-?%d+)') do | 800 |
1077 suffixes[tonumber(suffixId)] = true | 801 -- require faction match |
1078 end | 802 local faction = tonumber(parts[6]) |
1079 | 803 if faction ~= AskMrRobot.factionIds[AmrDb.Faction] then |
1080 local item = { | 804 return L.AMR_IMPORT_ERROR_FACTION |
1081 itemId = tonumber(itemId), | 805 end |
1082 suffixes = suffixes, | 806 |
1083 upgradeId = tonumber(upgradeId), | 807 -- require level match |
1084 gems = gems, | 808 local level = tonumber(parts[7]) |
1085 enchantId = tonumber(enchantId), | 809 if level ~= AmrDb.Level then |
1086 reforgeId = tonumber(reforgeId) | 810 return L.AMR_IMPORT_ERROR_LEVEL |
1087 } | 811 end |
1088 return slot, item | 812 |
1089 end | 813 -- require spec match |
1090 | 814 local spec = tonumber(parts[11]) |
1091 | 815 if spec ~= AmrDb.Specs[AmrDb.ActiveSpec] then |
1092 function AskMrRobot.parseAmr(input) | 816 print(AmrDb.ActiveSpec) |
1093 local parsedInput = {} | 817 print(spec) |
1094 parsedInput.items = {} | 818 print(AmrDb.Specs[AmrDb.ActiveSpec]) |
1095 for k, v in string.gmatch(input, "([^=;]+)=([^;]*)") do | 819 local _, specName = GetSpecializationInfoByID(AskMrRobot.gameSpecIds[spec]) |
1096 if (k == 'item') then | 820 return L.AMR_IMPORT_ERROR_SPEC:format(specName) |
1097 local slot, item = parseAmrItem(v); | 821 end |
1098 parsedInput.items[AskMrRobot.slotIdToSlotNum[tonumber(slot) + 1]] = item; | 822 |
1099 elseif (k == 'glyphs') then | 823 -- require talent match |
1100 parsedInput.glyphs = parseGlyphs(v) | 824 local talents = parts[12] |
1101 elseif (k == 'professions') then | 825 if talents ~= AmrDb.Talents[AmrDb.ActiveSpec] then |
1102 parsedInput.professions = parseProfessions(v) | 826 return L.AMR_IMPORT_ERROR_TALENT |
1103 else | 827 end |
1104 parsedInput[k]=v | 828 |
1105 end | 829 -- require glyph match |
1106 end | 830 -- TODO: re-enable this check when glyphs are more consistent |
1107 return parsedInput | 831 --local glyphs = parts[13] |
1108 end | 832 --if glyphs ~= AskMrRobot.toCompressedNumberList(AmrDb.Glyphs[AmrDb.ActiveSpec]) then |
1109 | 833 -- return L.AMR_IMPORT_ERROR_GLYPH |
1110 function AskMrRobot.validateRealm(realm) | 834 --end |
1111 return realm == GetRealmName(); | 835 |
1112 end | 836 -- if we make it this far, the data is valid, so read item information |
1113 | 837 local importData = {} |
1114 function AskMrRobot.validateCharacterName(characterName) | 838 |
1115 return UnitName("player") == characterName | 839 local itemInfo = {} |
1116 end | 840 local gemInfo = {} |
1117 | 841 local enchantInfo = {} |
1118 function AskMrRobot.validateRace(race) | 842 |
1119 local _, raceEn = UnitRace("player") | 843 local prevItemId = 0 |
1120 return raceEn == race or (raceEn == "Scourge" and race == "Undead") | 844 local prevGemId = 0 |
1121 end | 845 local prevEnchantId = 0 |
1122 | 846 local prevUpgradeId = 0 |
1123 function AskMrRobot.validateFaction(faction) | 847 local prevBonusId = 0 |
1124 return faction == UnitFactionGroup("player") | 848 local digits = { |
1125 end | 849 ["-"] = true, |
1126 | 850 ["0"] = true, |
1127 function AskMrRobot.validateSpec(spec) | 851 ["1"] = true, |
1128 if spec == 'nil' then | 852 ["2"] = true, |
1129 spec = nil | 853 ["3"] = true, |
1130 end | 854 ["4"] = true, |
1131 local currentSpec = GetAmrSpecialization(GetActiveSpecGroup()) | 855 ["5"] = true, |
1132 return (not currentSpec and not spec) or tostring(currentSpec) == spec | 856 ["6"] = true, |
1133 end | 857 ["7"] = true, |
1134 | 858 ["8"] = true, |
1135 function AskMrRobot.validateTalents(talents) | 859 ["9"] = true, |
1136 if talents == nil then | 860 } |
1137 talents = '' | 861 for i = 15, #parts do |
1138 end | 862 local itemString = parts[i] |
1139 return talents == GetAmrTalentsForSpec(GetActiveSpecGroup()) | 863 if itemString ~= "" and itemString ~= "_" then |
1140 end | 864 local tokens = {} |
1141 | 865 local bonusIds = {} |
1142 function AskMrRobot.validateGlyphs(glyphs) | 866 local hasBonuses = false |
1143 if (glyphs == nil) then | 867 local token = "" |
1144 glyphs = {}; | 868 local prop = "i" |
1145 end | 869 local tokenComplete = false |
1146 local currentGlyphs = GetAmrGlyphsForSpec(GetActiveSpecGroup()) | 870 for j = 1, string.len(itemString) do |
1147 table.sort(glyphs, function(a,b) return tostring(a) < tostring(b) end) | 871 local c = string.sub(itemString, j, j) |
1148 table.sort(currentGlyphs, function(a,b) return tostring(a) < tostring(b) end) | 872 if digits[c] == nil then |
1149 | 873 tokenComplete = true |
1150 if #glyphs ~= #currentGlyphs then | 874 else |
1151 return false | 875 token = token .. c |
1152 end | 876 end |
1153 for i = 1, #glyphs do | 877 |
1154 if tostring(glyphs[i]) ~= tostring(currentGlyphs[i]) then | 878 if tokenComplete or j == string.len(itemString) then |
1155 return false | 879 local val = tonumber(token) |
1156 end | 880 if prop == "i" then |
1157 end | 881 val = val + prevItemId |
1158 | 882 prevItemId = val |
1159 return true | 883 elseif prop == "u" then |
1160 end | 884 val = val + prevUpgradeId |
1161 | 885 prevUpgradeId = val |
1162 local function getPrimaryProfessions() | 886 elseif prop == "b" then |
1163 local profs = {} | 887 val = val + prevBonusId |
1164 local prof1, prof2 = GetProfessions() | 888 prevBonusId = val |
1165 local profMap = { | 889 elseif prop == "x" or prop == "y" or prop == "z" then |
1166 [794] = "Archaeology", | 890 val = val + prevGemId |
1167 [171] = "Alchemy", | 891 prevGemId = val |
1168 [164] = "Blacksmithing", | 892 elseif prop == "e" then |
1169 [185] = "Cooking", | 893 val = val + prevEnchantId |
1170 [333] = "Enchanting", | 894 prevEnchantId = val |
1171 [202] = "Engineering", | 895 end |
1172 [129] = "First Aid", | 896 |
1173 [356] = "Fishing", | 897 if prop == "b" then |
1174 [182] = "Herbalism", | 898 table.insert(bonusIds, val) |
1175 [773] = "Inscription", | 899 hasBonuses = true |
1176 [755] = "Jewelcrafting", | 900 else |
1177 [165] = "Leatherworking", | 901 tokens[prop] = val |
1178 [186] = "Mining", | 902 end |
1179 [393] = "Skinning", | 903 |
1180 [197] = "Tailoring" | 904 token = "" |
1181 } | 905 tokenComplete = false |
1182 | 906 |
1183 if prof1 then | 907 -- we have moved on to the next token |
1184 local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof1); | 908 prop = c |
1185 if profMap[skillLine] ~= nil then | 909 end |
1186 profs[profMap[skillLine]] = skillLevel | 910 end |
1187 end | 911 |
1188 end | 912 local obj = {} |
1189 if prof2 then | 913 importData[tonumber(tokens["s"])] = obj |
1190 local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof2); | 914 |
1191 if profMap[skillLine] ~= nil then | 915 obj.id = tokens["i"] |
1192 profs[profMap[skillLine]] = skillLevel | 916 obj.suffixId = tokens["f"] or 0 |
1193 end | 917 obj.upgradeId = tokens["u"] or 0 |
1194 end | 918 obj.enchantId = tokens["e"] or 0 |
1195 return profs; | 919 |
1196 end | 920 obj.gemIds = {} |
1197 | 921 table.insert(obj.gemIds, tokens["x"] or 0) |
1198 local professionThresholds = { | 922 table.insert(obj.gemIds, tokens["y"] or 0) |
1199 Leatherworking = 575, | 923 table.insert(obj.gemIds, tokens["z"] or 0) |
1200 Inscription = 600, | 924 table.insert(obj.gemIds, 0) |
1201 Alchemy = 50, | 925 |
1202 Enchanting = 550, | 926 if hasBonuses then |
1203 Jewelcrafting = 550, | 927 obj.bonusIds = bonusIds |
1204 Blacksmithing = 550, | 928 end |
1205 Tailoring = 550 | 929 |
1206 } | 930 local itemObj = {} |
1207 | 931 itemObj.id = obj.id |
1208 function AskMrRobot.validateProfessions(professions) | 932 itemInfo[obj.id] = itemObj |
1209 local currentProfessions = getPrimaryProfessions() | 933 |
1210 if #currentProfessions ~= #professions then | 934 -- look for any socket color information, add to our extra data |
1211 return false | 935 if tokens["c"] then |
1212 end | 936 itemObj.socketColors = {} |
1213 for k, v in pairs(professions) do | 937 for j = 1, string.len(tokens["c"]) do |
1214 if currentProfessions[k] then | 938 table.insert(itemObj.socketColors, tonumber(string.sub(tokens["c"], j, j))) |
1215 local threshold = professionThresholds[k] | 939 end |
1216 if not threshold then | 940 end |
1217 threshold = 1 | 941 |
1218 end | 942 -- look for item ID duplicate info, deals with old SoO items |
1219 -- compare the desired profession against the threshold | 943 if tokens["d"] then |
1220 local desired = v >= threshold | 944 itemObj.duplicateId = tonumber(tokens["d"]) |
1221 -- compare the current profession against the threshold | 945 end |
1222 local has = currentProfessions[k] and currentProfessions[k] >= threshold | 946 |
1223 -- if the current value is on the other side of the threshold | 947 end |
1224 -- then we don't match | 948 end |
1225 if desired ~= has then | 949 |
1226 return false | 950 -- now read any extra display information |
1227 end | 951 parts = { strsplit("@", data1[3]) } |
1228 else | 952 for i = 1, #parts do |
1229 return false | 953 local infoParts = { strsplit("\\", parts[i]) } |
1230 end | 954 |
1231 end | 955 if infoParts[1] == "g" then |
1232 return true | 956 |
1233 end | 957 local gemObj = {} |
1234 | 958 gemObj.enchantId = tonumber(infoParts[2]) |
1235 function AskMrRobot.populateItemDiffs(amrItem, itemLink, slotNum) | 959 gemObj.id = tonumber(infoParts[3]) |
1236 AskMrRobot.itemDiffs.items[slotNum] = nil | 960 |
1237 AskMrRobot.itemDiffs.gems[slotNum] = nil | 961 local identicalGems = infoParts[4] |
1238 AskMrRobot.itemDiffs.enchants[slotNum] = nil | 962 if string.len(identicalGems) > 0 then |
1239 AskMrRobot.itemDiffs.reforges[slotNum] = nil | 963 gemObj.identicalGroup = {} |
1240 | 964 identicalGems = { strsplit(",", identicalGems) } |
1241 local needsUpgrade = false | 965 for j = 1, #identicalGems do |
1242 local aSuffix = 0 | 966 gemObj.identicalGroup[tonumber(identicalGems[j])] = true |
1243 if amrItem then | 967 end |
1244 for k,v in pairs(amrItem.suffixes) do | 968 end |
1245 aSuffix = k | 969 |
1246 end | 970 gemObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.AMR_STAT_SHORT_STRINGS[s] end) |
1247 end | 971 if infoParts[6] == nil or string.len(infoParts[6]) == 0 then |
1248 | 972 gemObj.identicalItemGroup = {[gemObj.id]=true} |
1249 if itemLink == nil then | 973 else |
1250 if amrItem ~= nil then | 974 local identicalIds = { strsplit(',', infoParts[6]) } |
1251 AskMrRobot.itemDiffs.items[slotNum] = { | 975 gemObj.identicalItemGroup = {} |
1252 current = nil, | 976 for j = 1, #identicalIds do |
1253 optimized = { itemId = amrItem.itemId, upgradeId = amrItem.upgradeId, suffixId = aSuffix }, | 977 gemObj.identicalItemGroup[tonumber(identicalIds[j])] = true |
1254 needsUpgrade = false | 978 end |
1255 } | 979 end |
1256 end | 980 |
1257 return | 981 gemInfo[gemObj.enchantId] = gemObj |
1258 end | 982 |
1259 local item = parseItemLink(itemLink) | 983 elseif infoParts[1] == "e" then |
1260 local isItemBad = false | 984 |
1261 | 985 local enchObj = {} |
1262 if amrItem == nil or item.itemId ~= amrItem.itemId then | 986 enchObj.id = tonumber(infoParts[2]) |
1263 isItemBad = true | 987 enchObj.itemId = tonumber(infoParts[3]) |
1264 else | 988 enchObj.spellId = tonumber(infoParts[4]) |
1265 if item.suffixId == 0 then | 989 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.AMR_STAT_SHORT_STRINGS[s] end) |
1266 if #amrItem.suffixes > 0 then | 990 |
1267 isItemBad = true | 991 local mats = infoParts[6] |
1268 end | 992 if string.len(mats) > 0 then |
1269 else | 993 enchObj.materials = {} |
1270 if not amrItem.suffixes[item.suffixId] then | 994 mats = { strsplit(",", mats) } |
1271 isItemBad = true | 995 for j = 1, #mats do |
1272 end | 996 local kv = { strsplit("=", mats[j]) } |
1273 end | 997 enchObj.materials[tonumber(kv[1])] = tonumber(kv[2]) |
1274 if not isItemBad and upgradeTable[item.upgradeId] ~= upgradeTable[amrItem.upgradeId] then | 998 end |
1275 isItemBad = true | 999 end |
1276 needsUpgrade = true | 1000 |
1277 end | 1001 enchantInfo[enchObj.id] = enchObj |
1278 end | 1002 |
1279 | 1003 end |
1280 if isItemBad then | 1004 end |
1281 AskMrRobot.itemDiffs.items[slotNum] = { | 1005 |
1282 current = item.itemId, | 1006 -- we have succeeded, record the result |
1283 optimized = { itemId = amrItem and amrItem.itemId or 0, upgradeId = amrItem and amrItem.upgradeId or 0, suffixId = aSuffix }, | 1007 AskMrRobot.ImportData = importData |
1284 needsUpgrade = needsUpgrade | 1008 AskMrRobot.ExtraItemData = itemInfo |
1285 } | 1009 AskMrRobot.ExtraGemData = gemInfo |
1286 return | 1010 AskMrRobot.ExtraEnchantData = enchantInfo |
1287 end | 1011 |
1288 | 1012 AmrDb.LastCharacterImport = data |
1289 local badGemCount, gemInfo = AskMrRobot.MatchesGems(itemLink, item.gemEnchantIds, amrItem.gems) | 1013 AmrDb.LastCharacterImportDate = date() |
1290 if badGemCount > 0 then | 1014 end |
1291 AskMrRobot.itemDiffs.gems[slotNum] = gemInfo | |
1292 end | |
1293 | |
1294 if item.enchantId ~= amrItem.enchantId then | |
1295 AskMrRobot.itemDiffs.enchants[slotNum] = { | |
1296 current = item.enchantId, | |
1297 optimized = amrItem.enchantId | |
1298 } | |
1299 end | |
1300 | |
1301 if item.reforgeId ~= amrItem.reforgeId then | |
1302 AskMrRobot.itemDiffs.reforges[slotNum] = { | |
1303 current = item.reforgeId, | |
1304 optimized = amrItem.reforgeId | |
1305 } | |
1306 end | |
1307 end | |
1308 | |
1309 --[[ | |
1310 function AskMrRobot.StartLogging() | |
1311 if not LoggingCombat() then | |
1312 LoggingCombat(1) | |
1313 print("Started Combat Logging") | |
1314 end | |
1315 end | |
1316 | |
1317 function AskMrRobot.FinishLogging() | |
1318 if LoggingCombat() then | |
1319 LoggingCombat(0) | |
1320 print("Finished Combat Logging") | |
1321 end | |
1322 end | |
1323 | |
1324 -- local difficultyLookup = { | |
1325 -- DUNGEON_DIFFICULTY1, | |
1326 -- DUNGEON_DIFFICULTY2, | |
1327 -- RAID_DIFFICULTY_10PLAYER, | |
1328 -- RAID_DIFFICULTY_25PLAYER, | |
1329 -- RAID_DIFFICULTY_10PLAYER_HEROIC, | |
1330 -- RAID_DIFFICULTY_25PLAYER_HEROIC, | |
1331 -- RAID_FINDER, | |
1332 -- CHALLENGE_MODE, | |
1333 -- RAID_DIFFICULTY_40PLAYER, | |
1334 -- nil, | |
1335 -- nil, -- Norm scen | |
1336 -- nil, -- heroic scen | |
1337 -- nil, | |
1338 -- PLAYER_DIFFICULTY4 | |
1339 -- } | |
1340 | |
1341 --http://wowpedia.org/InstanceMapID | |
1342 local instanceMaps = { | |
1343 HeartOfFear = 1009, | |
1344 MogushanVaults = 1008, | |
1345 SiegeOfOrgrimmar = 1136, | |
1346 TerraceOfEndlessSpring = 996, | |
1347 ThroneOfThunder = 1098 | |
1348 } | |
1349 | |
1350 function AskMrRobot.UpdateLogging() | |
1351 | |
1352 -- get the info about the instance | |
1353 --local zone, zonetype, difficultyIndex, difficultyName, maxPlayers, dynamicDifficulty, isDynamic, instanceMapID = GetInstanceInfo() | |
1354 local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo() | |
1355 --local difficulty = difficultyIndex | |
1356 -- Unless Blizzard fixes scenarios to not return nil, let's hardcode this into returning "scenario" -Znuff | |
1357 --if zonetype == nil and difficultyIndex == 1 then | |
1358 --zonetype = "scenario" | |
1359 --end | |
1360 | |
1361 -- if nothing has changed, then bail | |
1362 --if (not zone) and difficulty == 0 then return end | |
1363 if zone == AskMrRobot.lastzone and difficultyIndex == AskMrRobot.lastdiff then | |
1364 -- do nothing if the zone hasn't ACTUALLY changed | |
1365 -- otherwise we may override the user's manual enable/disable | |
1366 return | |
1367 end | |
1368 | |
1369 AskMrRobot.lastzone = zone | |
1370 AskMrRobot.lastdiff = difficultyIndex | |
1371 | |
1372 if AmrOptions.autoLog[tonumber(instanceMapID)] then | |
1373 if instanceMapID == instanceMaps.SiegeOfOrgrimmar then | |
1374 AskMrRobot.StartLogging() | |
1375 else | |
1376 AskMrRobot.FinishLogging() | |
1377 end | |
1378 end | |
1379 end | |
1380 ]] |