annotate AskMrRobot.lua @ 33:4ba69d2ee252 v9

fixed bug with gem changes not appearing sometimes, mainWindow crash on startup, lua error for unknown item tooltips
author yellowfive
date Sat, 18 Oct 2014 18:13:55 -0700
parents 44c285acfff0
children d964099e4783
rev   line source
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