adam@0
|
1 local _, AskMrRobot = ...
|
yellowfive@11
|
2 local L = AskMrRobot.L;
|
adam@0
|
3
|
adam@17
|
4 AskMrRobot.eventListener = CreateFrame("FRAME") -- Need a frame to respond to events
|
adam@17
|
5 AskMrRobot.eventListener:RegisterEvent("ADDON_LOADED") -- Fired when saved variables are loaded
|
adam@17
|
6 AskMrRobot.eventListener:RegisterEvent("ITEM_PUSH")
|
adam@17
|
7 AskMrRobot.eventListener:RegisterEvent("DELETE_ITEM_CONFIRM")
|
adam@17
|
8 AskMrRobot.eventListener:RegisterEvent("UNIT_INVENTORY_CHANGED")
|
adam@17
|
9 AskMrRobot.eventListener:RegisterEvent("BANKFRAME_OPENED")
|
adam@17
|
10 --AskMrRobot.eventListener:RegisterEvent("BANKFRAME_CLOSED");
|
adam@17
|
11 AskMrRobot.eventListener:RegisterEvent("PLAYERBANKSLOTS_CHANGED")
|
adam@17
|
12 AskMrRobot.eventListener:RegisterEvent("CHARACTER_POINTS_CHANGED")
|
adam@17
|
13 AskMrRobot.eventListener:RegisterEvent("CONFIRM_TALENT_WIPE")
|
adam@17
|
14 AskMrRobot.eventListener:RegisterEvent("PLAYER_TALENT_UPDATE")
|
adam@17
|
15 AskMrRobot.eventListener:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED")
|
adam@17
|
16 AskMrRobot.eventListener:RegisterEvent("PLAYER_ENTERING_WORLD")
|
adam@17
|
17 --AskMrRobot.eventListener:RegisterEvent("PLAYER_LOGOUT") -- Fired when about to log out
|
adam@17
|
18 --AskMrRobot.eventListener:RegisterEvent("PLAYER_LEVEL_UP")
|
adam@0
|
19 --AskMrRobot.eventListener:RegisterEvent("GET_ITEM_INFO_RECEIVED")
|
adam@0
|
20 AskMrRobot.eventListener:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
|
adam@0
|
21 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_UPDATE")
|
adam@0
|
22 AskMrRobot.eventListener:RegisterEvent("SOCKET_INFO_CLOSE")
|
adam@0
|
23 AskMrRobot.eventListener:RegisterEvent("BAG_UPDATE")
|
adam@0
|
24 AskMrRobot.eventListener:RegisterEvent("ITEM_UNLOCKED")
|
yellowfive@11
|
25 AskMrRobot.eventListener:RegisterEvent("PLAYER_REGEN_DISABLED")
|
yellowfive@11
|
26 --AskMrRobot.eventListener:RegisterEvent("ENCOUNTER_START")
|
adam@0
|
27 AskMrRobot.eventListener:RegisterEvent("CHAT_MSG_ADDON")
|
adam@0
|
28 AskMrRobot.eventListener:RegisterEvent("UPDATE_INSTANCE_INFO")
|
adam@0
|
29 AskMrRobot.eventListener:RegisterEvent("PLAYER_DIFFICULTY_CHANGED")
|
adam@21
|
30 AskMrRobot.eventListener:RegisterEvent("VOID_STORAGE_OPEN")
|
adam@21
|
31 AskMrRobot.eventListener:RegisterEvent("VOID_STORAGE_CONTENTS_UPDATE")
|
adam@21
|
32 AskMrRobot.eventListener:RegisterEvent("PLAYER_DIFFICULTY_CHANGED")
|
adam@21
|
33 AskMrRobot.eventListener:RegisterEvent("VOID_STORAGE_UPDATE")
|
adam@0
|
34
|
adam@0
|
35 AskMrRobot.AddonName = ...
|
adam@0
|
36 AskMrRobot.ChatPrefix = "_AMR"
|
adam@0
|
37
|
yellowfive@31
|
38 -- flag to turn on debugging behavior
|
yellowfive@31
|
39 AskMrRobot.debug = false
|
yellowfive@31
|
40
|
adam@17
|
41 -- the main user interface window
|
adam@17
|
42 AskMrRobot.mainWindow = nil
|
adam@0
|
43
|
adam@17
|
44 local _amrLDB
|
adam@17
|
45 local _minimapIcon
|
adam@0
|
46
|
yellowfive@33
|
47 function ensureMainWindow()
|
yellowfive@33
|
48 if AskMrRobot.mainWindow == nil then
|
yellowfive@33
|
49 AskMrRobot.mainWindow = AskMrRobot.AmrUI:new()
|
yellowfive@33
|
50 end
|
yellowfive@33
|
51 end
|
yellowfive@33
|
52
|
adam@0
|
53 function AskMrRobot.eventListener:OnEvent(event, ...)
|
adam@0
|
54 if event == "ADDON_LOADED" then
|
adam@0
|
55 local addon = select(1, ...)
|
adam@0
|
56 if (addon == "AskMrRobot") then
|
yellowfive@33
|
57 -- create main window if not created yet
|
yellowfive@33
|
58 ensureMainWindow()
|
yellowfive@33
|
59
|
adam@17
|
60 AskMrRobot.InitializeSettings()
|
adam@17
|
61 AskMrRobot.InitializeMinimap()
|
adam@0
|
62
|
adam@0
|
63 -- listen for messages from other AMR addons
|
yellowfive@33
|
64 RegisterAddonMessagePrefix(AskMrRobot.ChatPrefix)
|
adam@0
|
65 end
|
adam@17
|
66
|
adam@17
|
67 elseif event == "UNIT_INVENTORY_CHANGED" then
|
adam@17
|
68 AskMrRobot.ScanEquipped()
|
adam@0
|
69
|
adam@17
|
70 elseif event == "ITEM_PUSH" or event == "DELETE_ITEM_CONFIRM" or event == "SOCKET_INFO_CLOSE" or event == "PLAYER_SPECIALIZATION_CHANGED" or event == "BAG_UPDATE" then
|
adam@17
|
71 --if AskMrRobot_ReforgeFrame then
|
adam@17
|
72 -- AskMrRobot_ReforgeFrame:OnUpdate()
|
adam@17
|
73 --end
|
adam@0
|
74 --AskMrRobot.SaveBags();
|
adam@0
|
75 --AskMrRobot.SaveEquiped();
|
adam@0
|
76 --AskMrRonot.GetCurrencies();
|
adam@0
|
77 --AskMrRobot.GetGold();
|
adam@17
|
78
|
adam@0
|
79 elseif event == "BANKFRAME_OPENED" or event == "PLAYERBANKSLOTS_CHANGED" then
|
adam@0
|
80 AskMrRobot.ScanBank();
|
adam@21
|
81 elseif event == "VOID_STORAGE_OPEN" or event == "VOID_STORAGE_CONTENTS_UPDATE" or event == "VOID_STORAGE_DEPOSIT_UPDATE" or event == "VOID_STORAGE_UPDATE" then
|
adam@21
|
82 AskMrRobot.ScanVoidStorage();
|
adam@0
|
83 elseif event == "CHARACTER_POINTS_CHANGED" or event == "CONFIRM_TALENT_WIPE" or event == "PLAYER_TALENT_UPDATE" or event == "ACTIVE_TALENT_GROUP_CHANGED" then
|
adam@0
|
84 --AskMrRobot.GetAmrSpecializations();
|
adam@17
|
85 --if AskMrRobot_ReforgeFrame then
|
adam@17
|
86 -- AskMrRobot_ReforgeFrame:OnUpdate()
|
adam@17
|
87 --end
|
adam@17
|
88
|
adam@0
|
89 elseif event == "ITEM_UNLOCKED" then
|
adam@17
|
90 --AskMrRobot.On_ITEM_UNLOCKED()
|
yellowfive@11
|
91
|
adam@17
|
92 elseif event == "PLAYER_ENTERING_WORLD" then
|
adam@17
|
93 AskMrRobot.RecordLogin()
|
yellowfive@11
|
94
|
yellowfive@11
|
95 elseif event == "PLAYER_REGEN_DISABLED" then
|
yellowfive@11
|
96 -- send data about this character when a player enters combat in a supported zone
|
yellowfive@11
|
97 if AskMrRobot.IsSupportedInstance() then
|
yellowfive@11
|
98 local t = time()
|
yellowfive@11
|
99 AskMrRobot.SaveAll()
|
yellowfive@11
|
100 AskMrRobot.ExportToAddonChat(t)
|
adam@17
|
101 AskMrRobot.CombatLogTab.SaveExtras(t)
|
yellowfive@11
|
102 end
|
yellowfive@11
|
103
|
adam@0
|
104 elseif event == "CHAT_MSG_ADDON" then
|
adam@0
|
105 local chatPrefix, message = select(1, ...)
|
adam@17
|
106 local isLogging = AskMrRobot.CombatLogTab.IsLogging()
|
adam@0
|
107 if (isLogging and chatPrefix == AskMrRobot.ChatPrefix) then
|
yellowfive@33
|
108 -- create main window if not created yet
|
yellowfive@33
|
109 ensureMainWindow()
|
yellowfive@33
|
110
|
adam@17
|
111 AskMrRobot.mainWindow.combatLogTab:ReadAddonMessage(message)
|
adam@0
|
112 end
|
adam@17
|
113
|
adam@0
|
114 elseif event == "UPDATE_INSTANCE_INFO" or event == "PLAYER_DIFFICULTY_CHANGED" then
|
yellowfive@33
|
115 -- create main window if not created yet
|
yellowfive@33
|
116 ensureMainWindow()
|
yellowfive@33
|
117
|
yellowfive@33
|
118 AskMrRobot.mainWindow.combatLogTab:UpdateAutoLogging()
|
adam@0
|
119 end
|
adam@0
|
120
|
adam@0
|
121 end
|
adam@0
|
122
|
adam@17
|
123 AskMrRobot.eventListener:SetScript("OnEvent", AskMrRobot.eventListener.OnEvent)
|
adam@0
|
124
|
adam@0
|
125
|
adam@0
|
126 SLASH_AMR1 = "/amr";
|
adam@0
|
127 function SlashCmdList.AMR(msg)
|
adam@0
|
128
|
adam@0
|
129 if msg == 'toggle' then
|
adam@17
|
130 AskMrRobot.mainWindow:Toggle()
|
adam@0
|
131 elseif msg == 'show' then
|
adam@17
|
132 AskMrRobot.mainWindow:Show()
|
adam@0
|
133 elseif msg == 'hide' then
|
adam@17
|
134 AskMrRobot.mainWindow:Hide()
|
adam@0
|
135 elseif msg == 'export' then
|
adam@17
|
136 AskMrRobot.mainWindow.exportTab:Show()
|
yellowfive@11
|
137 elseif msg == 'wipe' then
|
adam@17
|
138 AskMrRobot.mainWindow.combatLogTab:LogWipe()
|
yellowfive@11
|
139 elseif msg == 'unwipe' then
|
adam@17
|
140 AskMrRobot.mainWindow.combatLogTab:LogUnwipe()
|
adam@0
|
141 else
|
yellowfive@11
|
142 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)
|
adam@0
|
143 end
|
adam@0
|
144 end
|
adam@0
|
145
|
adam@17
|
146 -- initialize settings when the addon loads
|
adam@17
|
147 function AskMrRobot.InitializeSettings()
|
adam@17
|
148
|
adam@17
|
149 -- global settings
|
adam@17
|
150 if not AmrSettings then AmrSettings = {} end
|
adam@17
|
151 if not AmrSettings.Logins then AmrSettings.Logins = {} end
|
adam@17
|
152
|
adam@17
|
153 -- per-character settings
|
adam@17
|
154 if not AmrDb then AmrDb = {} end
|
adam@17
|
155
|
adam@17
|
156 -- addon stuff
|
adam@17
|
157 if not AmrDb.IconInfo then AmrDb.IconInfo = {} end
|
adam@17
|
158 if not AmrDb.Options then AmrDb.Options = {} end
|
adam@17
|
159 if not AmrDb.LastCharacterImport then AmrDb.LastCharacterImport = "" end
|
adam@17
|
160 if not AmrDb.LastCharacterImportDate then AmrDb.LastCharacterImportDate = "" end
|
adam@17
|
161
|
adam@17
|
162 if not AmrDb.SendSettings then
|
adam@17
|
163 AmrDb.SendSettings = {
|
adam@17
|
164 SendGems = true,
|
adam@17
|
165 SendEnchants = true,
|
adam@17
|
166 SendEnchantMaterials = true,
|
adam@17
|
167 SendToType = "a friend",
|
adam@17
|
168 SendTo = ""
|
adam@17
|
169 }
|
adam@17
|
170 end
|
adam@17
|
171
|
adam@17
|
172 -- character stuff
|
adam@17
|
173 AskMrRobot.ScanCharacter()
|
adam@17
|
174 if not AmrDb.BankItems then AmrDb.BankItems = {} end
|
adam@17
|
175 if not AmrDb.BagItems then AmrDb.BagItems = {} end
|
adam@17
|
176 if not AmrDb.Currencies then AmrDb.Currencies = {} end
|
adam@17
|
177 if not AmrDb.Reps then AmrDb.Reps = {} end
|
adam@17
|
178 -- data saved for both specs
|
adam@17
|
179 if not AmrDb.Specs then AmrDb.Specs = {} end
|
adam@17
|
180 if not AmrDb.Glyphs then AmrDb.Glyphs = {} end
|
adam@17
|
181 if not AmrDb.Talents then AmrDb.Talents = {} end
|
adam@17
|
182 if not AmrDb.Equipped then AmrDb.Equipped = {} end
|
adam@17
|
183
|
adam@17
|
184 -- combat log specific settings
|
adam@17
|
185 AskMrRobot.CombatLogTab.InitializeVariable()
|
adam@0
|
186 end
|
adam@0
|
187
|
adam@17
|
188 -- record logins when the addon starts up, used to help figure out which character logged which parts of a log file
|
adam@17
|
189 function AskMrRobot.RecordLogin()
|
adam@17
|
190
|
adam@17
|
191 -- delete entries that are more than 10 days old to prevent the table from growing indefinitely
|
adam@17
|
192 if AmrSettings.Logins and #AmrSettings.Logins > 0 then
|
adam@17
|
193 local now = time()
|
adam@17
|
194 local oldDuration = 60 * 60 * 24 * 10
|
adam@17
|
195 local entryTime
|
adam@17
|
196 repeat
|
adam@17
|
197 -- parse entry and get time
|
adam@17
|
198 local parts = {}
|
adam@17
|
199 for part in string.gmatch(AmrSettings.Logins[1], "([^;]+)") do
|
adam@17
|
200 tinsert(parts, part)
|
adam@17
|
201 end
|
adam@17
|
202 entryTime = tonumber(parts[3])
|
adam@17
|
203
|
adam@17
|
204 -- entries are in order, remove first entry if it is old
|
adam@17
|
205 if difftime(now, entryTime) > oldDuration then
|
adam@17
|
206 tremove(AmrSettings.Logins, 1)
|
adam@17
|
207 end
|
adam@17
|
208 until #AmrSettings.Logins == 0 or difftime(now, entryTime) <= oldDuration
|
adam@17
|
209 end
|
adam@17
|
210
|
adam@17
|
211 -- record the time a player logs in, used to figure out which player logged which parts of their log file
|
adam@17
|
212 local key = AmrDb.RealmName .. ";" .. AmrDb.CharacterName .. ";"
|
adam@17
|
213 local loginData = key .. time()
|
adam@17
|
214 if AmrSettings.Logins and #AmrSettings.Logins > 0 then
|
adam@17
|
215 local last = AmrSettings.Logins[#AmrSettings.Logins]
|
adam@17
|
216 if string.len(last) >= string.len(key) and string.sub(last, 1, string.len(key)) ~= key then
|
adam@17
|
217 table.insert(AmrSettings.Logins, loginData)
|
adam@17
|
218 end
|
adam@17
|
219 else
|
adam@17
|
220 table.insert(AmrSettings.Logins, loginData)
|
adam@17
|
221 end
|
adam@17
|
222 end
|
adam@17
|
223
|
adam@17
|
224 function AskMrRobot.InitializeMinimap()
|
adam@17
|
225
|
adam@17
|
226 -- minimap icon and data broker icon plugin thingy
|
adam@17
|
227 _amrLDB = LibStub("LibDataBroker-1.1"):NewDataObject("AskMrRobot", {
|
adam@17
|
228 type = "launcher",
|
adam@17
|
229 text = "Ask Mr. Robot",
|
adam@17
|
230 icon = "Interface\\AddOns\\AskMrRobot\\Media\\icon",
|
adam@17
|
231 OnClick = function()
|
adam@17
|
232 if IsControlKeyDown() then
|
adam@17
|
233 AskMrRobot.mainWindow.combatLogTab:LogWipe()
|
adam@17
|
234 elseif IsModifiedClick("CHATLINL") then
|
adam@17
|
235 AskMrRobot.mainWindow.exportTab:Show()
|
adam@17
|
236 else
|
adam@17
|
237 AskMrRobot.mainWindow:Toggle()
|
adam@17
|
238 end
|
adam@17
|
239 end,
|
adam@17
|
240 OnTooltipShow = function(tt)
|
adam@17
|
241 tt:AddLine("Ask Mr. Robot", 1, 1, 1);
|
adam@17
|
242 tt:AddLine(" ");
|
adam@17
|
243 tt:AddLine(L.AMR_ON_EVENT_TOOLTIP)
|
adam@17
|
244 end
|
adam@17
|
245 });
|
adam@17
|
246
|
adam@17
|
247 AskMrRobot.AmrUpdateMinimap()
|
adam@0
|
248 end
|
adam@0
|
249
|
yellowfive@11
|
250 function AskMrRobot.AmrUpdateMinimap()
|
adam@17
|
251 if AmrDb.Options.hideMapIcon then
|
adam@17
|
252 if _minimapIcon then
|
adam@17
|
253 _minimapIcon:Hide("AskMrRobot")
|
adam@0
|
254 end
|
adam@0
|
255 else
|
adam@17
|
256 if not _minimapIcon then
|
adam@17
|
257 _minimapIcon = LibStub("LibDBIcon-1.0")
|
adam@17
|
258 _minimapIcon:Register("AskMrRobot", _amrLDB, AmrDb.IconInfo)
|
adam@0
|
259 end
|
adam@17
|
260
|
adam@17
|
261 if AskMrRobot.CombatLogTab.IsLogging() then
|
adam@17
|
262 _amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon_green'
|
yellowfive@11
|
263 else
|
adam@17
|
264 _amrLDB.icon = 'Interface\\AddOns\\AskMrRobot\\Media\\icon'
|
yellowfive@11
|
265 end
|
adam@17
|
266
|
adam@17
|
267 _minimapIcon:Show("AskMrRobot")
|
adam@0
|
268 end
|
adam@0
|
269 end
|
adam@0
|
270
|
adam@17
|
271
|
adam@17
|
272 function AskMrRobot.SaveAll()
|
adam@17
|
273 AskMrRobot.ScanCharacter()
|
adam@17
|
274 AskMrRobot.ScanBags()
|
adam@17
|
275 AskMrRobot.ScanEquipped()
|
adam@17
|
276 AskMrRobot.GetCurrencies()
|
adam@17
|
277 AskMrRobot.GetReputations()
|
adam@17
|
278 AskMrRobot.GetSpecs()
|
adam@0
|
279 end
|
adam@0
|
280
|
adam@17
|
281 -- gets all basic character properties
|
adam@17
|
282 function AskMrRobot.ScanCharacter()
|
adam@17
|
283 AmrDb.RealmName = GetRealmName()
|
adam@17
|
284 AmrDb.CharacterName = UnitName("player")
|
adam@17
|
285 AmrDb.Guild = GetGuildInfo("player")
|
adam@17
|
286 AmrDb.ActiveSpec = GetActiveSpecGroup()
|
adam@17
|
287 AmrDb.Level = UnitLevel("player");
|
adam@17
|
288
|
adam@17
|
289 local cls, clsEn = UnitClass("player")
|
adam@17
|
290 AmrDb.Class = clsEn;
|
adam@17
|
291
|
adam@17
|
292 local race, raceEn = UnitRace("player")
|
adam@17
|
293 AmrDb.Race = raceEn;
|
adam@17
|
294 AmrDb.Faction = UnitFactionGroup("player")
|
adam@17
|
295
|
adam@17
|
296 AskMrRobot.GetAmrProfessions()
|
adam@0
|
297 end
|
adam@0
|
298
|
adam@0
|
299 function AskMrRobot.GetAmrProfessions()
|
adam@0
|
300
|
adam@0
|
301 local profMap = {
|
adam@0
|
302 [794] = "Archaeology",
|
adam@0
|
303 [171] = "Alchemy",
|
adam@0
|
304 [164] = "Blacksmithing",
|
adam@0
|
305 [185] = "Cooking",
|
adam@0
|
306 [333] = "Enchanting",
|
adam@0
|
307 [202] = "Engineering",
|
adam@0
|
308 [129] = "First Aid",
|
adam@0
|
309 [356] = "Fishing",
|
adam@0
|
310 [182] = "Herbalism",
|
adam@0
|
311 [773] = "Inscription",
|
adam@0
|
312 [755] = "Jewelcrafting",
|
adam@0
|
313 [165] = "Leatherworking",
|
adam@0
|
314 [186] = "Mining",
|
adam@0
|
315 [393] = "Skinning",
|
adam@0
|
316 [197] = "Tailoring"
|
adam@0
|
317 }
|
adam@0
|
318
|
adam@0
|
319 local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions();
|
adam@17
|
320 AmrDb.Professions = {};
|
adam@0
|
321 if prof1 then
|
adam@0
|
322 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof1);
|
adam@0
|
323 if profMap[skillLine] ~= nil then
|
adam@17
|
324 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
325 end
|
adam@0
|
326 end
|
adam@0
|
327 if prof2 then
|
adam@0
|
328 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof2);
|
adam@0
|
329 if profMap[skillLine] ~= nil then
|
adam@17
|
330 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
331 end
|
adam@0
|
332 end
|
adam@0
|
333 if archaeology then
|
adam@0
|
334 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(archaeology);
|
adam@0
|
335 if profMap[skillLine] ~= nil then
|
adam@17
|
336 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
337 end
|
adam@0
|
338 end
|
adam@0
|
339 if fishing then
|
adam@0
|
340 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(fishing);
|
adam@0
|
341 if profMap[skillLine] ~= nil then
|
adam@17
|
342 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
343 end
|
adam@0
|
344 end
|
adam@0
|
345 if cooking then
|
adam@0
|
346 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(cooking);
|
adam@0
|
347 if profMap[skillLine] ~= nil then
|
adam@17
|
348 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
349 end
|
adam@0
|
350 end
|
adam@0
|
351 if firstAid then
|
adam@0
|
352 local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(firstAid);
|
adam@0
|
353 if profMap[skillLine] ~= nil then
|
adam@17
|
354 AmrDb.Professions[profMap[skillLine]] = skillLevel;
|
adam@0
|
355 end
|
adam@0
|
356 end
|
adam@0
|
357 end
|
adam@0
|
358
|
adam@17
|
359
|
adam@17
|
360 -- use some local variables to deal with the fact that a user can close the bank before a scan completes
|
adam@17
|
361 local _lastBankBagId = nil
|
adam@17
|
362 local _lastBankSlotId = nil
|
adam@17
|
363 local BACKPACK_CONTAINER = 0
|
adam@17
|
364 local BANK_CONTAINER = -1
|
adam@17
|
365
|
adam@17
|
366 local function scanBag(bagId, isBank, bagTable, bagItemsWithCount)
|
adam@17
|
367 local numSlots = GetContainerNumSlots(bagId)
|
adam@17
|
368 for slotId = 1, numSlots do
|
adam@17
|
369 local _, itemCount, _, _, _, _, itemLink = GetContainerItemInfo(bagId, slotId)
|
adam@17
|
370 -- we skip any stackable item, as far as we know, there is no equippable gear that can be stacked
|
adam@17
|
371 if itemLink ~= nil then
|
adam@17
|
372 local itemData = AskMrRobot.parseItemLink(itemLink)
|
adam@17
|
373 if itemData ~= nil then
|
adam@17
|
374 if itemCount == 1 then
|
adam@17
|
375 if isBank then
|
adam@17
|
376 _lastBankBagId = bagId
|
adam@17
|
377 _lastBankSlotId = slotId
|
adam@17
|
378 end
|
adam@17
|
379 tinsert(bagTable, itemLink)
|
adam@17
|
380 end
|
adam@17
|
381 if bagItemsWithCount then
|
adam@17
|
382 if bagItemsWithCount[itemData.id] then
|
adam@17
|
383 bagItemsWithCount[itemData.id] = bagItemsWithCount[itemData.id] + itemCount
|
adam@17
|
384 else
|
adam@17
|
385 bagItemsWithCount[itemData.id] = itemCount
|
adam@17
|
386 end
|
adam@17
|
387 end
|
adam@17
|
388 end
|
adam@17
|
389 end
|
adam@17
|
390 end
|
adam@17
|
391 end
|
adam@17
|
392
|
adam@21
|
393 function AskMrRobot.ScanBank()
|
adam@21
|
394 --REAGENTBANK_CONTAINER (-3)
|
adam@17
|
395 local bankItems = {}
|
adam@17
|
396 local bankItemsAndCounts = {}
|
adam@17
|
397
|
adam@17
|
398 scanBag(BANK_CONTAINER, true, bankItems, bankItemsAndCounts)
|
adam@21
|
399 scanBag(REAGENTBANK_CONTAINER, true, bankItems, bankItemsAndCounts)
|
adam@17
|
400 for bagId = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do
|
adam@17
|
401 scanBag(bagId, true, bankItems, bankItemsAndCounts)
|
adam@17
|
402 end
|
adam@17
|
403
|
adam@17
|
404 -- see if the scan completed before the window closed, otherwise we don't overwrite with partial data
|
adam@17
|
405 if _lastBankBagId ~= nil then
|
adam@17
|
406 local itemLink = GetContainerItemLink(_lastBankBagId, _lastBankSlotId)
|
adam@17
|
407 if itemLink ~= nil then --still open
|
adam@17
|
408 AmrDb.BankItems = bankItems
|
adam@17
|
409 AmrDb.BankItemsAndCounts = bankItemsAndCounts
|
adam@17
|
410 end
|
adam@17
|
411 end
|
adam@0
|
412 end
|
adam@0
|
413
|
adam@21
|
414 function AskMrRobot.ScanVoidStorage()
|
adam@21
|
415 if IsVoidStorageReady() then
|
adam@21
|
416 local voidItems = {}
|
adam@21
|
417 local VOID_STORAGE_MAX = 80
|
adam@21
|
418 local VOID_STORAGE_PAGES = 2
|
adam@21
|
419 local i
|
adam@21
|
420 for page = 1,VOID_STORAGE_PAGES do
|
adam@21
|
421 for i = 1,VOID_STORAGE_MAX do
|
adam@21
|
422 local itemId = GetVoidItemInfo(page, i)
|
adam@21
|
423 if itemId then
|
adam@21
|
424 local itemLink = GetVoidItemHyperlinkString(page, i);
|
adam@21
|
425 if itemLink then
|
adam@21
|
426 tinsert(voidItems, itemLink)
|
adam@21
|
427 end
|
adam@21
|
428 end
|
adam@21
|
429 end
|
adam@21
|
430 end
|
adam@21
|
431 AmrDb.VoidItems = voidItems
|
adam@21
|
432 end
|
adam@21
|
433 end
|
adam@21
|
434
|
adam@17
|
435 function AskMrRobot.ScanBags(bagItemsWithCount)
|
adam@17
|
436 local bagItems = {}
|
adam@17
|
437 scanBag(BACKPACK_CONTAINER, false, bagItems, bagItemsWithCount) -- backpack
|
adam@17
|
438 for bagId = 1, NUM_BAG_SLOTS do
|
adam@17
|
439 scanBag(bagId, false, bagItems, bagItemsWithCount)
|
adam@17
|
440 end
|
adam@17
|
441 AmrDb.BagItems = bagItems
|
adam@0
|
442 end
|
adam@0
|
443
|
adam@17
|
444 function AskMrRobot.ScanEquipped()
|
adam@17
|
445 local equippedItems = {};
|
adam@17
|
446 for slotNum = 1, #AskMrRobot.slotIds do
|
adam@17
|
447 local slotId = AskMrRobot.slotIds[slotNum];
|
adam@17
|
448 local itemLink = GetInventoryItemLink("player", slotId);
|
adam@17
|
449 if (itemLink ~= nil) then
|
adam@17
|
450 equippedItems[slotId] = itemLink;
|
adam@17
|
451 end
|
adam@17
|
452 end
|
adam@17
|
453
|
adam@17
|
454 -- store last-seen equipped gear for each spec
|
adam@17
|
455 AmrDb.Equipped[GetActiveSpecGroup()] = equippedItems
|
adam@17
|
456 end
|
adam@0
|
457
|
adam@17
|
458
|
adam@17
|
459 local function getCurrencyAmount(index)
|
adam@17
|
460 local localized_label, amount, icon_file_name = GetCurrencyInfo(index);
|
adam@17
|
461 return amount;
|
adam@17
|
462 end
|
adam@17
|
463
|
adam@17
|
464 function AskMrRobot.GetCurrencies()
|
adam@17
|
465 local currencies = {};
|
adam@17
|
466 currencies[-1] = GetMoney()
|
adam@17
|
467
|
yellowfive@31
|
468 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, 823}
|
adam@17
|
469 for i, currency in pairs(currencyList) do
|
adam@17
|
470 local amount = getCurrencyAmount(currency)
|
adam@17
|
471 if amount ~= 0 then
|
adam@17
|
472 currencies[currency] = amount
|
adam@17
|
473 end
|
adam@17
|
474 end
|
adam@17
|
475
|
adam@17
|
476 AmrDb.Currencies = currencies
|
adam@17
|
477 end
|
adam@17
|
478
|
adam@17
|
479
|
adam@17
|
480 local function getRepStanding(factionId)
|
adam@17
|
481 local name, description, standingId, _ = GetFactionInfoByID(factionId)
|
adam@17
|
482 return standingId - 1; -- our rep enum correspond to what the armory returns, are 1 less than what the game returns
|
adam@17
|
483 end
|
adam@17
|
484
|
adam@17
|
485 function AskMrRobot.GetReputations()
|
adam@17
|
486 local reps = {}
|
adam@17
|
487
|
adam@17
|
488 local repList = {1375,1376,1270,1269,1341,1337,1387,1388,1435}
|
adam@17
|
489 for i, repId in pairs(repList) do
|
adam@17
|
490 local standing = getRepStanding(repId)
|
adam@17
|
491 if standing >= 0 then
|
adam@17
|
492 reps[repId] = standing
|
adam@17
|
493 end
|
adam@17
|
494 end
|
adam@17
|
495
|
adam@17
|
496 AmrDb.Reps = reps;
|
adam@17
|
497 end
|
adam@17
|
498
|
adam@17
|
499
|
adam@17
|
500 local function getSpecId(specGroup)
|
adam@17
|
501 local spec = GetSpecialization(false, false, specGroup);
|
adam@17
|
502 return spec and GetSpecializationInfo(spec);
|
adam@17
|
503 end
|
adam@17
|
504
|
adam@17
|
505 local function getTalents(specGroup)
|
adam@0
|
506 local talentInfo = {}
|
adam@17
|
507 local maxTiers = 7
|
adam@17
|
508 for tier = 1, maxTiers do
|
adam@17
|
509 for col = 1, 3 do
|
adam@17
|
510 local id, name, texture, selected, available = GetTalentInfo(tier, col, specGroup)
|
adam@17
|
511 if selected then
|
adam@17
|
512 talentInfo[tier] = col
|
adam@17
|
513 end
|
adam@17
|
514 end
|
adam@0
|
515 end
|
adam@0
|
516
|
adam@0
|
517 local str = ""
|
adam@0
|
518 for i = 1, maxTiers do
|
adam@0
|
519 if talentInfo[i] then
|
adam@0
|
520 str = str .. talentInfo[i]
|
adam@0
|
521 else
|
adam@0
|
522 str = str .. '0'
|
adam@0
|
523 end
|
adam@0
|
524 end
|
adam@0
|
525
|
adam@0
|
526 return str
|
adam@0
|
527 end
|
adam@0
|
528
|
adam@17
|
529 local function getGlyphs(specGroup)
|
adam@0
|
530 local glyphs = {}
|
adam@0
|
531 for i = 1, NUM_GLYPH_SLOTS do
|
adam@17
|
532 local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, specGroup)
|
adam@0
|
533 if (glyphID) then
|
adam@0
|
534 tinsert(glyphs, glyphSpellID)
|
adam@0
|
535 end
|
adam@0
|
536 end
|
adam@0
|
537 return glyphs;
|
adam@0
|
538 end
|
adam@0
|
539
|
adam@17
|
540 -- get specs, talents, and glyphs
|
adam@17
|
541 function AskMrRobot.GetSpecs()
|
adam@17
|
542
|
adam@17
|
543 AmrDb.Specs = {}
|
adam@17
|
544 AmrDb.Talents = {}
|
adam@17
|
545 AmrDb.Glyphs = {}
|
adam@17
|
546
|
adam@17
|
547 for group = 1, GetNumSpecGroups() do
|
adam@17
|
548 -- spec, convert game spec id to one of our spec ids
|
adam@17
|
549 local specId = getSpecId(group)
|
adam@17
|
550 if specId then
|
adam@17
|
551 AmrDb.Specs[group] = AskMrRobot.specIds[specId]
|
adam@17
|
552 else
|
adam@17
|
553 AmrDb.Specs[group] = 0
|
adam@17
|
554 end
|
adam@17
|
555
|
adam@17
|
556 AmrDb.Talents[group] = getTalents(group)
|
adam@17
|
557 AmrDb.Glyphs[group] = getGlyphs(group)
|
adam@0
|
558 end
|
adam@0
|
559 end
|
adam@0
|
560
|
adam@17
|
561 ----------------------------------------------------------------------------
|
adam@17
|
562 -- Export
|
adam@17
|
563 ----------------------------------------------------------------------------
|
adam@0
|
564
|
adam@17
|
565 function AskMrRobot.toCompressedNumberList(list)
|
adam@0
|
566 -- ensure the values are numbers, sorted from lowest to highest
|
adam@0
|
567 local nums = {}
|
adam@0
|
568 for i, v in ipairs(list) do
|
adam@0
|
569 table.insert(nums, tonumber(v))
|
adam@0
|
570 end
|
adam@0
|
571 table.sort(nums)
|
adam@0
|
572
|
adam@0
|
573 local ret = {}
|
adam@0
|
574 local prev = 0
|
adam@0
|
575 for i, v in ipairs(nums) do
|
adam@0
|
576 local diff = v - prev
|
adam@0
|
577 table.insert(ret, diff)
|
adam@0
|
578 prev = v
|
adam@0
|
579 end
|
adam@0
|
580
|
adam@0
|
581 return table.concat(ret, ",")
|
adam@0
|
582 end
|
adam@0
|
583
|
adam@17
|
584 -- appends a list of items to the export
|
adam@17
|
585 local function appendItemsToExport(fields, itemObjects)
|
adam@17
|
586
|
adam@17
|
587 -- sort by item id so we can compress it more easily
|
adam@17
|
588 table.sort(itemObjects, function(a, b) return a.id < b.id end)
|
adam@17
|
589
|
adam@17
|
590 -- append to the export string
|
adam@17
|
591 local prevItemId = 0
|
adam@17
|
592 local prevGemId = 0
|
adam@17
|
593 local prevEnchantId = 0
|
adam@17
|
594 local prevUpgradeId = 0
|
adam@17
|
595 local prevBonusId = 0
|
adam@17
|
596 for i, itemData in ipairs(itemObjects) do
|
adam@17
|
597 local itemParts = {}
|
adam@17
|
598
|
adam@17
|
599 table.insert(itemParts, itemData.id - prevItemId)
|
adam@17
|
600 prevItemId = itemData.id
|
adam@17
|
601
|
adam@17
|
602 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end
|
adam@17
|
603 if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end
|
adam@17
|
604 if itemData.upgradeId ~= 0 then
|
adam@17
|
605 table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId))
|
adam@17
|
606 prevUpgradeId = itemData.upgradeId
|
adam@17
|
607 end
|
adam@17
|
608 if itemData.bonusIds then
|
adam@17
|
609 for bIndex, bValue in ipairs(itemData.bonusIds) do
|
adam@17
|
610 table.insert(itemParts, "b" .. (bValue - prevBonusId))
|
adam@17
|
611 prevBonusId = bValue
|
adam@17
|
612 end
|
adam@17
|
613 end
|
adam@17
|
614 if itemData.gemIds[1] ~= 0 then
|
adam@17
|
615 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId))
|
adam@17
|
616 prevGemId = itemData.gemIds[1]
|
adam@17
|
617 end
|
adam@17
|
618 if itemData.gemIds[2] ~= 0 then
|
adam@17
|
619 table.insert(itemParts, "y" .. (itemData.gemIds[2] - prevGemId))
|
adam@17
|
620 prevGemId = itemData.gemIds[2]
|
adam@17
|
621 end
|
adam@17
|
622 if itemData.gemIds[3] ~= 0 then
|
adam@17
|
623 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId))
|
adam@17
|
624 prevGemId = itemData.gemIds[3]
|
adam@17
|
625 end
|
adam@17
|
626 if itemData.enchantId ~= 0 then
|
adam@17
|
627 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId))
|
adam@17
|
628 prevEnchantId = itemData.enchantId
|
adam@17
|
629 end
|
adam@17
|
630
|
adam@17
|
631 table.insert(fields, table.concat(itemParts, ""))
|
adam@17
|
632 end
|
adam@17
|
633 end
|
adam@17
|
634
|
adam@17
|
635 -- create a compact string representing this player
|
adam@17
|
636 -- if complete is true, exports everything (inventory, both specs)
|
adam@17
|
637 -- otherwise only exports the player's active gear, spec, etc.
|
adam@17
|
638 function AskMrRobot.ExportToCompressedString(complete)
|
adam@0
|
639 local fields = {}
|
adam@0
|
640
|
adam@0
|
641 -- compressed string uses a fixed order rather than inserting identifiers
|
adam@0
|
642 table.insert(fields, GetAddOnMetadata(AskMrRobot.AddonName, "Version"))
|
adam@17
|
643 table.insert(fields, AmrDb.RealmName)
|
adam@17
|
644 table.insert(fields, AmrDb.CharacterName)
|
adam@0
|
645
|
adam@0
|
646 -- guild name
|
adam@0
|
647 local guildName = GetGuildInfo("player")
|
adam@0
|
648 if guildName == nil then
|
adam@0
|
649 table.insert(fields, "")
|
adam@0
|
650 else
|
adam@0
|
651 table.insert(fields, guildName)
|
adam@0
|
652 end
|
adam@0
|
653
|
adam@0
|
654 -- race, default to pandaren if we can't read it for some reason
|
adam@17
|
655 local raceval = AskMrRobot.raceIds[AmrDb.Race]
|
adam@0
|
656 if raceval == nil then raceval = 13 end
|
adam@0
|
657 table.insert(fields, raceval)
|
adam@0
|
658
|
adam@0
|
659 -- faction, default to alliance if we can't read it for some reason
|
adam@17
|
660 raceval = AskMrRobot.factionIds[AmrDb.Faction]
|
adam@0
|
661 if raceval == nil then raceval = 1 end
|
adam@0
|
662 table.insert(fields, raceval)
|
adam@0
|
663
|
adam@17
|
664 table.insert(fields, AmrDb.Level)
|
adam@0
|
665
|
adam@0
|
666 local profs = {}
|
adam@0
|
667 local noprofs = true
|
adam@17
|
668 if AmrDb.Professions then
|
adam@17
|
669 for k, v in pairs(AmrDb.Professions) do
|
adam@17
|
670 local profval = AskMrRobot.professionIds[k]
|
yellowfive@11
|
671 if profval ~= nil then
|
yellowfive@11
|
672 noprofs = false
|
yellowfive@11
|
673 table.insert(profs, profval .. ":" .. v)
|
yellowfive@11
|
674 end
|
yellowfive@11
|
675 end
|
yellowfive@11
|
676 end
|
adam@0
|
677
|
adam@0
|
678 if noprofs then
|
adam@0
|
679 table.insert(profs, "0:0")
|
adam@0
|
680 end
|
adam@0
|
681
|
adam@0
|
682 table.insert(fields, table.concat(profs, ","))
|
adam@0
|
683
|
adam@17
|
684 -- export specs
|
adam@17
|
685 table.insert(fields, AmrDb.ActiveSpec)
|
adam@17
|
686 for spec = 1, 2 do
|
adam@17
|
687 if AmrDb.Specs[spec] and (complete or spec == AmrDb.ActiveSpec) then
|
adam@17
|
688 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block
|
adam@17
|
689 table.insert(fields, AmrDb.Specs[spec])
|
adam@17
|
690 table.insert(fields, AmrDb.Talents[spec])
|
adam@17
|
691 table.insert(fields, AskMrRobot.toCompressedNumberList(AmrDb.Glyphs[spec]))
|
adam@17
|
692 end
|
adam@0
|
693 end
|
adam@0
|
694
|
adam@17
|
695 -- export equipped gear
|
adam@17
|
696 if AmrDb.Equipped then
|
adam@17
|
697 for spec = 1, 2 do
|
adam@17
|
698 if AmrDb.Equipped[spec] and (complete or spec == AmrDb.ActiveSpec) then
|
adam@17
|
699 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block
|
adam@17
|
700
|
adam@17
|
701 local itemObjects = {}
|
adam@17
|
702 for k, v in pairs(AmrDb.Equipped[spec]) do
|
adam@17
|
703 local itemData = AskMrRobot.parseItemLink(v)
|
adam@17
|
704 itemData.slot = k
|
adam@17
|
705 table.insert(itemObjects, itemData)
|
adam@17
|
706 end
|
adam@17
|
707
|
adam@17
|
708 appendItemsToExport(fields, itemObjects)
|
adam@17
|
709 end
|
adam@17
|
710 end
|
yellowfive@11
|
711 end
|
adam@0
|
712
|
adam@17
|
713 -- if doing a complete export, include reputations and bank/bag items too
|
adam@17
|
714 if complete then
|
adam@17
|
715
|
adam@17
|
716 -- export reputations
|
adam@17
|
717 local reps = {}
|
adam@17
|
718 local noreps = true
|
adam@17
|
719 if AmrDb.Reps then
|
adam@17
|
720 for k, v in pairs(AmrDb.Reps) do
|
adam@17
|
721 noreps = false
|
adam@17
|
722 table.insert(reps, k .. ":" .. v)
|
adam@17
|
723 end
|
adam@17
|
724 end
|
adam@17
|
725 if noreps then
|
adam@17
|
726 table.insert(reps, "_")
|
adam@17
|
727 end
|
adam@17
|
728
|
adam@17
|
729 table.insert(fields, ".r")
|
adam@17
|
730 table.insert(fields, table.concat(reps, ","))
|
adam@17
|
731
|
adam@17
|
732 -- export bag and bank
|
adam@17
|
733 local itemObjects = {}
|
adam@17
|
734 if AmrDb.BagItems then
|
adam@17
|
735 for i, v in ipairs(AmrDb.BagItems) do
|
adam@21
|
736 local _,_,_,_,_,_,_,stackCount = GetItemInfo(v)
|
adam@21
|
737 if stackCount == 1 then
|
adam@21
|
738 local itemData = AskMrRobot.parseItemLink(v)
|
adam@21
|
739 if itemData ~= nil then
|
adam@21
|
740 table.insert(itemObjects, itemData)
|
adam@21
|
741 end
|
adam@21
|
742 end
|
yellowfive@11
|
743 end
|
yellowfive@11
|
744 end
|
adam@17
|
745 if AmrDb.BankItems then
|
adam@17
|
746 for i, v in ipairs(AmrDb.BankItems) do
|
adam@21
|
747 local _,_,_,_,_,_,_,stackCount = GetItemInfo(v)
|
adam@21
|
748 if stackCount == 1 then
|
adam@21
|
749 local itemData = AskMrRobot.parseItemLink(v)
|
adam@21
|
750 if itemData ~= nil then
|
adam@21
|
751 table.insert(itemObjects, itemData)
|
adam@21
|
752 end
|
yellowfive@11
|
753 end
|
yellowfive@11
|
754 end
|
yellowfive@11
|
755 end
|
adam@21
|
756 if AmrDb.VoidItems then
|
adam@21
|
757 for i, v in ipairs(AmrDb.VoidItems) do
|
adam@21
|
758 local _,_,_,_,_,_,_,stackCount = GetItemInfo(v)
|
adam@21
|
759 if stackCount == 1 then
|
adam@21
|
760 local itemData = AskMrRobot.parseItemLink(v)
|
adam@21
|
761 if itemData ~= nil then
|
adam@21
|
762 table.insert(itemObjects, itemData)
|
adam@21
|
763 end
|
adam@21
|
764 end
|
adam@21
|
765 end
|
adam@21
|
766 end
|
adam@0
|
767
|
adam@17
|
768 table.insert(fields, ".inv")
|
adam@17
|
769 appendItemsToExport(fields, itemObjects)
|
adam@0
|
770 end
|
yellowfive@11
|
771
|
adam@0
|
772 return "$" .. table.concat(fields, ";") .. "$"
|
adam@0
|
773 end
|
adam@0
|
774
|
adam@0
|
775 function AskMrRobot.ExportToAddonChat(timestamp)
|
yellowfive@11
|
776 local msg = AskMrRobot.ExportToCompressedString(false)
|
yellowfive@29
|
777 local msgPrefix = timestamp .. "\n" .. AmrDb.RealmName .. "\n" .. AmrDb.CharacterName .. "\n"
|
adam@0
|
778
|
adam@0
|
779 -- break the data into 250 character chunks (to deal with the short limit on addon message size)
|
adam@0
|
780 local chunks = {}
|
adam@0
|
781 local i = 1
|
yellowfive@11
|
782 local length = string.len(msg)
|
adam@0
|
783 local chunkLen = 249 - string.len(msgPrefix)
|
adam@0
|
784 while (i <= length) do
|
adam@0
|
785 local endpos = math.min(i + chunkLen, length)
|
yellowfive@11
|
786 table.insert(chunks, msgPrefix .. string.sub(msg, i, endpos))
|
adam@0
|
787 i = endpos + 1
|
adam@0
|
788 end
|
adam@0
|
789
|
adam@0
|
790 for i, v in ipairs(chunks) do
|
adam@0
|
791 SendAddonMessage(AskMrRobot.ChatPrefix, v, "RAID")
|
adam@0
|
792 end
|
adam@0
|
793
|
adam@0
|
794 -- send a completion message
|
adam@0
|
795 SendAddonMessage(AskMrRobot.ChatPrefix, msgPrefix .. "done", "RAID")
|
adam@0
|
796 end
|
adam@0
|
797
|
adam@0
|
798 -- Create an export string that can be copied to the website
|
adam@0
|
799 function AskMrRobot.ExportToString()
|
adam@17
|
800 return AskMrRobot.ExportToCompressedString(true)
|
adam@17
|
801 end
|
adam@0
|
802
|
adam@17
|
803
|
adam@17
|
804 ----------------------------------------------------------------------------
|
adam@17
|
805 -- Import
|
adam@17
|
806 ----------------------------------------------------------------------------
|
adam@17
|
807
|
adam@17
|
808 -- imports will give us extra information about items, gems, and enchants
|
adam@17
|
809 AskMrRobot.ExtraItemData = {} -- keyed by item id
|
adam@17
|
810 AskMrRobot.ExtraGemData = {} -- keyed by gem enchant id
|
adam@17
|
811 AskMrRobot.ExtraEnchantData = {} -- keyed by enchant id
|
adam@17
|
812
|
adam@17
|
813 -- the data that was last imported
|
adam@17
|
814 AskMrRobot.ImportData = nil -- keyed by slot id
|
adam@17
|
815
|
adam@17
|
816 local MIN_IMPORT_VERSION = 2
|
adam@17
|
817
|
adam@17
|
818 --
|
adam@17
|
819 -- Import a character, returning nil on success, otherwise an error message, import result stored in AskMrRobot.ImportData
|
adam@17
|
820 --
|
yellowfive@31
|
821 function AskMrRobot.ImportCharacter(data, isTest)
|
adam@17
|
822
|
adam@17
|
823 -- make sure all data is up to date before importing
|
adam@17
|
824 AskMrRobot.SaveAll()
|
adam@0
|
825
|
adam@17
|
826 if data == nil or string.len(data) == 0 then
|
adam@17
|
827 return L.AMR_IMPORT_ERROR_EMPTY
|
adam@0
|
828 end
|
adam@0
|
829
|
adam@17
|
830 local data1 = { strsplit("$", data) }
|
adam@17
|
831 if #data1 ~= 3 then
|
adam@17
|
832 return L.AMR_IMPORT_ERROR_FORMAT
|
adam@0
|
833 end
|
adam@17
|
834
|
adam@17
|
835 local parts = { strsplit(";", data1[2]) }
|
adam@17
|
836
|
adam@17
|
837 -- require a minimum version
|
adam@17
|
838 local ver = tonumber(parts[1])
|
adam@17
|
839 if ver < MIN_IMPORT_VERSION then
|
adam@17
|
840 return L.AMR_IMPORT_ERROR_VERSION
|
adam@0
|
841 end
|
adam@17
|
842
|
adam@17
|
843 -- require realm/name match
|
yellowfive@31
|
844 if not isTest then
|
yellowfive@31
|
845 local realm = parts[2]
|
yellowfive@31
|
846 local name = parts[3]
|
yellowfive@31
|
847 if name ~= AmrDb.CharacterName then
|
yellowfive@31
|
848 local badPers = name .. " (" .. realm .. ")"
|
yellowfive@31
|
849 local goodPers = AmrDb.CharacterName .. " (" .. AmrDb.RealmName .. ")"
|
yellowfive@31
|
850 return L.AMR_IMPORT_ERROR_CHAR:format(badPers, goodPers)
|
yellowfive@31
|
851 end
|
yellowfive@31
|
852
|
yellowfive@31
|
853 -- require race match
|
yellowfive@31
|
854 local race = tonumber(parts[5])
|
yellowfive@31
|
855 if race ~= AskMrRobot.raceIds[AmrDb.Race] then
|
yellowfive@31
|
856 return L.AMR_IMPORT_ERROR_RACE
|
yellowfive@31
|
857 end
|
yellowfive@31
|
858
|
yellowfive@31
|
859 -- require faction match
|
yellowfive@31
|
860 local faction = tonumber(parts[6])
|
yellowfive@31
|
861 if faction ~= AskMrRobot.factionIds[AmrDb.Faction] then
|
yellowfive@31
|
862 return L.AMR_IMPORT_ERROR_FACTION
|
yellowfive@31
|
863 end
|
yellowfive@31
|
864
|
yellowfive@31
|
865 -- require level match
|
yellowfive@31
|
866 local level = tonumber(parts[7])
|
yellowfive@31
|
867 if level ~= AmrDb.Level then
|
yellowfive@31
|
868 return L.AMR_IMPORT_ERROR_LEVEL
|
yellowfive@31
|
869 end
|
yellowfive@31
|
870
|
yellowfive@31
|
871 -- require spec match
|
yellowfive@31
|
872 local spec = tonumber(parts[11])
|
yellowfive@31
|
873 if spec ~= AmrDb.Specs[AmrDb.ActiveSpec] then
|
yellowfive@31
|
874 print(AmrDb.ActiveSpec)
|
yellowfive@31
|
875 print(spec)
|
yellowfive@31
|
876 print(AmrDb.Specs[AmrDb.ActiveSpec])
|
yellowfive@31
|
877 local _, specName = GetSpecializationInfoByID(AskMrRobot.gameSpecIds[spec])
|
yellowfive@31
|
878 return L.AMR_IMPORT_ERROR_SPEC:format(specName)
|
yellowfive@31
|
879 end
|
yellowfive@31
|
880
|
yellowfive@31
|
881 -- require talent match
|
yellowfive@31
|
882 local talents = parts[12]
|
yellowfive@31
|
883 if talents ~= AmrDb.Talents[AmrDb.ActiveSpec] then
|
yellowfive@31
|
884 return L.AMR_IMPORT_ERROR_TALENT
|
yellowfive@31
|
885 end
|
yellowfive@31
|
886
|
yellowfive@31
|
887 -- require glyph match
|
yellowfive@31
|
888 -- TODO: re-enable this check when glyphs are more consistent
|
yellowfive@31
|
889 --local glyphs = parts[13]
|
yellowfive@31
|
890 --if glyphs ~= AskMrRobot.toCompressedNumberList(AmrDb.Glyphs[AmrDb.ActiveSpec]) then
|
yellowfive@31
|
891 -- return L.AMR_IMPORT_ERROR_GLYPH
|
yellowfive@31
|
892 --end
|
adam@0
|
893 end
|
adam@0
|
894
|
adam@17
|
895
|
adam@17
|
896 -- if we make it this far, the data is valid, so read item information
|
adam@17
|
897 local importData = {}
|
adam@17
|
898
|
adam@17
|
899 local itemInfo = {}
|
adam@17
|
900 local gemInfo = {}
|
adam@17
|
901 local enchantInfo = {}
|
adam@17
|
902
|
adam@17
|
903 local prevItemId = 0
|
adam@17
|
904 local prevGemId = 0
|
adam@17
|
905 local prevEnchantId = 0
|
adam@17
|
906 local prevUpgradeId = 0
|
adam@17
|
907 local prevBonusId = 0
|
adam@17
|
908 local digits = {
|
adam@17
|
909 ["-"] = true,
|
adam@17
|
910 ["0"] = true,
|
adam@17
|
911 ["1"] = true,
|
adam@17
|
912 ["2"] = true,
|
adam@17
|
913 ["3"] = true,
|
adam@17
|
914 ["4"] = true,
|
adam@17
|
915 ["5"] = true,
|
adam@17
|
916 ["6"] = true,
|
adam@17
|
917 ["7"] = true,
|
adam@17
|
918 ["8"] = true,
|
adam@17
|
919 ["9"] = true,
|
adam@17
|
920 }
|
adam@17
|
921 for i = 15, #parts do
|
adam@17
|
922 local itemString = parts[i]
|
adam@17
|
923 if itemString ~= "" and itemString ~= "_" then
|
adam@17
|
924 local tokens = {}
|
adam@17
|
925 local bonusIds = {}
|
adam@17
|
926 local hasBonuses = false
|
adam@17
|
927 local token = ""
|
adam@17
|
928 local prop = "i"
|
adam@17
|
929 local tokenComplete = false
|
adam@17
|
930 for j = 1, string.len(itemString) do
|
adam@17
|
931 local c = string.sub(itemString, j, j)
|
adam@17
|
932 if digits[c] == nil then
|
adam@17
|
933 tokenComplete = true
|
adam@17
|
934 else
|
adam@17
|
935 token = token .. c
|
adam@17
|
936 end
|
adam@17
|
937
|
adam@17
|
938 if tokenComplete or j == string.len(itemString) then
|
adam@17
|
939 local val = tonumber(token)
|
adam@17
|
940 if prop == "i" then
|
adam@17
|
941 val = val + prevItemId
|
adam@17
|
942 prevItemId = val
|
adam@17
|
943 elseif prop == "u" then
|
adam@17
|
944 val = val + prevUpgradeId
|
adam@17
|
945 prevUpgradeId = val
|
adam@17
|
946 elseif prop == "b" then
|
adam@17
|
947 val = val + prevBonusId
|
adam@17
|
948 prevBonusId = val
|
adam@17
|
949 elseif prop == "x" or prop == "y" or prop == "z" then
|
adam@17
|
950 val = val + prevGemId
|
adam@17
|
951 prevGemId = val
|
adam@17
|
952 elseif prop == "e" then
|
adam@17
|
953 val = val + prevEnchantId
|
adam@17
|
954 prevEnchantId = val
|
adam@17
|
955 end
|
adam@17
|
956
|
adam@17
|
957 if prop == "b" then
|
adam@17
|
958 table.insert(bonusIds, val)
|
adam@17
|
959 hasBonuses = true
|
adam@17
|
960 else
|
adam@17
|
961 tokens[prop] = val
|
adam@17
|
962 end
|
adam@17
|
963
|
adam@17
|
964 token = ""
|
adam@17
|
965 tokenComplete = false
|
adam@17
|
966
|
adam@17
|
967 -- we have moved on to the next token
|
adam@17
|
968 prop = c
|
adam@17
|
969 end
|
adam@17
|
970 end
|
adam@17
|
971
|
adam@17
|
972 local obj = {}
|
adam@17
|
973 importData[tonumber(tokens["s"])] = obj
|
adam@17
|
974
|
adam@17
|
975 obj.id = tokens["i"]
|
adam@17
|
976 obj.suffixId = tokens["f"] or 0
|
adam@17
|
977 obj.upgradeId = tokens["u"] or 0
|
adam@17
|
978 obj.enchantId = tokens["e"] or 0
|
adam@17
|
979
|
adam@17
|
980 obj.gemIds = {}
|
adam@17
|
981 table.insert(obj.gemIds, tokens["x"] or 0)
|
adam@17
|
982 table.insert(obj.gemIds, tokens["y"] or 0)
|
adam@17
|
983 table.insert(obj.gemIds, tokens["z"] or 0)
|
adam@17
|
984 table.insert(obj.gemIds, 0)
|
adam@17
|
985
|
adam@17
|
986 if hasBonuses then
|
adam@17
|
987 obj.bonusIds = bonusIds
|
adam@17
|
988 end
|
adam@17
|
989
|
adam@17
|
990 local itemObj = {}
|
adam@17
|
991 itemObj.id = obj.id
|
adam@17
|
992 itemInfo[obj.id] = itemObj
|
adam@17
|
993
|
adam@17
|
994 -- look for any socket color information, add to our extra data
|
adam@17
|
995 if tokens["c"] then
|
adam@17
|
996 itemObj.socketColors = {}
|
adam@17
|
997 for j = 1, string.len(tokens["c"]) do
|
adam@17
|
998 table.insert(itemObj.socketColors, tonumber(string.sub(tokens["c"], j, j)))
|
yellowfive@33
|
999 end
|
adam@17
|
1000 end
|
adam@17
|
1001
|
adam@17
|
1002 -- look for item ID duplicate info, deals with old SoO items
|
adam@17
|
1003 if tokens["d"] then
|
adam@17
|
1004 itemObj.duplicateId = tonumber(tokens["d"])
|
yellowfive@33
|
1005 itemInfo[itemObj.duplicateId] = itemObj
|
adam@17
|
1006 end
|
adam@17
|
1007
|
adam@17
|
1008 end
|
adam@17
|
1009 end
|
adam@17
|
1010
|
adam@17
|
1011 -- now read any extra display information
|
adam@17
|
1012 parts = { strsplit("@", data1[3]) }
|
adam@17
|
1013 for i = 1, #parts do
|
adam@17
|
1014 local infoParts = { strsplit("\\", parts[i]) }
|
adam@17
|
1015
|
adam@17
|
1016 if infoParts[1] == "g" then
|
adam@17
|
1017
|
adam@17
|
1018 local gemObj = {}
|
adam@17
|
1019 gemObj.enchantId = tonumber(infoParts[2])
|
adam@17
|
1020 gemObj.id = tonumber(infoParts[3])
|
adam@17
|
1021
|
adam@17
|
1022 local identicalGems = infoParts[4]
|
adam@17
|
1023 if string.len(identicalGems) > 0 then
|
adam@17
|
1024 gemObj.identicalGroup = {}
|
adam@17
|
1025 identicalGems = { strsplit(",", identicalGems) }
|
adam@17
|
1026 for j = 1, #identicalGems do
|
adam@17
|
1027 gemObj.identicalGroup[tonumber(identicalGems[j])] = true
|
adam@17
|
1028 end
|
adam@17
|
1029 end
|
adam@17
|
1030
|
adam@17
|
1031 gemObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.AMR_STAT_SHORT_STRINGS[s] end)
|
adam@17
|
1032 if infoParts[6] == nil or string.len(infoParts[6]) == 0 then
|
adam@17
|
1033 gemObj.identicalItemGroup = {[gemObj.id]=true}
|
adam@17
|
1034 else
|
adam@17
|
1035 local identicalIds = { strsplit(',', infoParts[6]) }
|
adam@17
|
1036 gemObj.identicalItemGroup = {}
|
adam@17
|
1037 for j = 1, #identicalIds do
|
adam@17
|
1038 gemObj.identicalItemGroup[tonumber(identicalIds[j])] = true
|
adam@17
|
1039 end
|
adam@17
|
1040 end
|
adam@17
|
1041
|
adam@17
|
1042 gemInfo[gemObj.enchantId] = gemObj
|
adam@17
|
1043
|
adam@17
|
1044 elseif infoParts[1] == "e" then
|
adam@17
|
1045
|
adam@17
|
1046 local enchObj = {}
|
adam@17
|
1047 enchObj.id = tonumber(infoParts[2])
|
adam@17
|
1048 enchObj.itemId = tonumber(infoParts[3])
|
adam@17
|
1049 enchObj.spellId = tonumber(infoParts[4])
|
adam@17
|
1050 enchObj.text = string.gsub(infoParts[5], "_(%a+)_", function(s) return L.AMR_STAT_SHORT_STRINGS[s] end)
|
adam@17
|
1051
|
adam@17
|
1052 local mats = infoParts[6]
|
adam@17
|
1053 if string.len(mats) > 0 then
|
adam@17
|
1054 enchObj.materials = {}
|
adam@17
|
1055 mats = { strsplit(",", mats) }
|
adam@17
|
1056 for j = 1, #mats do
|
adam@17
|
1057 local kv = { strsplit("=", mats[j]) }
|
adam@17
|
1058 enchObj.materials[tonumber(kv[1])] = tonumber(kv[2])
|
adam@17
|
1059 end
|
adam@17
|
1060 end
|
adam@17
|
1061
|
adam@17
|
1062 enchantInfo[enchObj.id] = enchObj
|
adam@17
|
1063
|
adam@17
|
1064 end
|
adam@17
|
1065 end
|
adam@17
|
1066
|
yellowfive@31
|
1067 if isTest then
|
yellowfive@33
|
1068
|
yellowfive@31
|
1069 -- print result for debugging
|
yellowfive@33
|
1070 --for k,v in pairs(importData) do
|
yellowfive@33
|
1071 -- local blah = AskMrRobot.createItemLink(v)
|
yellowfive@33
|
1072 -- local name, link = GetItemInfo(blah)
|
yellowfive@33
|
1073 -- if link == nil then
|
yellowfive@33
|
1074 -- print(blah)
|
yellowfive@33
|
1075 -- print("bad item: " .. v.id)
|
yellowfive@33
|
1076 -- end
|
yellowfive@33
|
1077 --end
|
yellowfive@33
|
1078
|
yellowfive@31
|
1079
|
yellowfive@31
|
1080 else
|
yellowfive@31
|
1081 -- we have succeeded, record the result
|
yellowfive@31
|
1082 AskMrRobot.ImportData = importData
|
yellowfive@31
|
1083 AskMrRobot.ExtraItemData = itemInfo
|
yellowfive@31
|
1084 AskMrRobot.ExtraGemData = gemInfo
|
yellowfive@31
|
1085 AskMrRobot.ExtraEnchantData = enchantInfo
|
yellowfive@31
|
1086
|
yellowfive@31
|
1087 AmrDb.LastCharacterImport = data
|
yellowfive@31
|
1088 AmrDb.LastCharacterImportDate = date()
|
yellowfive@31
|
1089 end
|
adam@0
|
1090 end
|