annotate AskMrRobot.lua @ 13:bb0c8ce689d1 v1.2.15.0

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