yellowfive@57: -- AskMrRobot-Serializer will serialize and communicate character data between users. yellowfive@57: -- This is used primarily to associate character information to logs uploaded to askmrrobot.com. yellowfive@57: yellowfive@85: local MAJOR, MINOR = "AskMrRobot-Serializer", 40 yellowfive@57: local Amr, oldminor = LibStub:NewLibrary(MAJOR, MINOR) yellowfive@57: yellowfive@57: if not Amr then return end -- already loaded by something else yellowfive@57: yellowfive@57: -- event and comm used for player snapshotting on entering combat yellowfive@57: LibStub("AceEvent-3.0"):Embed(Amr) yellowfive@57: LibStub("AceComm-3.0"):Embed(Amr) yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: -- Constants yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: yellowfive@57: -- prefix used for communicating gear snapshots created by the AMR serializer yellowfive@57: Amr.ChatPrefix = "_AMRS" yellowfive@57: yellowfive@57: -- map of region ids to AMR region names yellowfive@57: Amr.RegionNames = { yellowfive@57: [1] = "US", yellowfive@57: [2] = "KR", yellowfive@57: [3] = "EU", yellowfive@57: [4] = "TW", yellowfive@57: [5] = "CN" yellowfive@57: } yellowfive@57: yellowfive@57: -- map of the skillLine returned by profession API to the AMR profession name yellowfive@57: Amr.ProfessionSkillLineToName = { yellowfive@57: [794] = "Archaeology", yellowfive@57: [171] = "Alchemy", yellowfive@57: [164] = "Blacksmithing", yellowfive@57: [185] = "Cooking", yellowfive@57: [333] = "Enchanting", yellowfive@57: [202] = "Engineering", yellowfive@57: [129] = "First Aid", yellowfive@57: [356] = "Fishing", yellowfive@57: [182] = "Herbalism", yellowfive@57: [773] = "Inscription", yellowfive@57: [755] = "Jewelcrafting", yellowfive@57: [165] = "Leatherworking", yellowfive@57: [186] = "Mining", yellowfive@57: [393] = "Skinning", yellowfive@57: [197] = "Tailoring" yellowfive@57: } yellowfive@57: yellowfive@57: -- all slot IDs that we care about, ordered in AMR standard display order yellowfive@57: Amr.SlotIds = { 16, 17, 1, 2, 3, 15, 5, 9, 10, 6, 7, 8, 11, 12, 13, 14 } yellowfive@57: yellowfive@57: Amr.SpecIds = { yellowfive@57: [250] = 1, -- DeathKnightBlood yellowfive@57: [251] = 2, -- DeathKnightFrost yellowfive@57: [252] = 3, -- DeathKnightUnholy yellowfive@81: [577] = 4, -- DemonHunterHavoc yellowfive@81: [581] = 5, -- DemonHunterVengeance yellowfive@81: [102] = 6, -- DruidBalance yellowfive@81: [103] = 7, -- DruidFeral yellowfive@81: [104] = 8, -- DruidGuardian yellowfive@81: [105] = 9, -- DruidRestoration yellowfive@81: [253] = 10, -- HunterBeastMastery yellowfive@81: [254] = 11, -- HunterMarksmanship yellowfive@81: [255] = 12, -- HunterSurvival yellowfive@81: [62] = 13, -- MageArcane yellowfive@81: [63] = 14, -- MageFire yellowfive@81: [64] = 15, -- MageFrost yellowfive@81: [268] = 16, -- MonkBrewmaster yellowfive@81: [270] = 17, -- MonkMistweaver yellowfive@81: [269] = 18, -- MonkWindwalker yellowfive@81: [65] = 19, -- PaladinHoly yellowfive@81: [66] = 20, -- PaladinProtection yellowfive@81: [70] = 21, -- PaladinRetribution yellowfive@81: [256] = 22, -- PriestDiscipline yellowfive@81: [257] = 23, -- PriestHoly yellowfive@81: [258] = 24, -- PriestShadow yellowfive@81: [259] = 25, -- RogueAssassination yellowfive@81: [260] = 26, -- RogueOutlaw yellowfive@81: [261] = 27, -- RogueSubtlety yellowfive@81: [262] = 28, -- ShamanElemental yellowfive@81: [263] = 29, -- ShamanEnhancement yellowfive@81: [264] = 30, -- ShamanRestoration yellowfive@81: [265] = 31, -- WarlockAffliction yellowfive@81: [266] = 32, -- WarlockDemonology yellowfive@81: [267] = 33, -- WarlockDestruction yellowfive@81: [71] = 34, -- WarriorArms yellowfive@81: [72] = 35, -- WarriorFury yellowfive@81: [73] = 36 -- WarriorProtection yellowfive@57: } yellowfive@57: yellowfive@57: Amr.ClassIds = { yellowfive@57: ["NONE"] = 0, yellowfive@57: ["DEATHKNIGHT"] = 1, yellowfive@81: ["DEMONHUNTER"] = 2, yellowfive@81: ["DRUID"] = 3, yellowfive@81: ["HUNTER"] = 4, yellowfive@81: ["MAGE"] = 5, yellowfive@81: ["MONK"] = 6, yellowfive@81: ["PALADIN"] = 7, yellowfive@81: ["PRIEST"] = 8, yellowfive@81: ["ROGUE"] = 9, yellowfive@81: ["SHAMAN"] = 10, yellowfive@81: ["WARLOCK"] = 11, yellowfive@81: ["WARRIOR"] = 12, yellowfive@57: } yellowfive@57: yellowfive@57: Amr.ProfessionIds = { yellowfive@57: ["None"] = 0, yellowfive@57: ["Mining"] = 1, yellowfive@57: ["Skinning"] = 2, yellowfive@57: ["Herbalism"] = 3, yellowfive@57: ["Enchanting"] = 4, yellowfive@57: ["Jewelcrafting"] = 5, yellowfive@57: ["Engineering"] = 6, yellowfive@57: ["Blacksmithing"] = 7, yellowfive@57: ["Leatherworking"] = 8, yellowfive@57: ["Inscription"] = 9, yellowfive@57: ["Tailoring"] = 10, yellowfive@57: ["Alchemy"] = 11, yellowfive@57: ["Fishing"] = 12, yellowfive@57: ["Cooking"] = 13, yellowfive@57: ["First Aid"] = 14, yellowfive@57: ["Archaeology"] = 15 yellowfive@57: } yellowfive@57: yellowfive@57: Amr.RaceIds = { yellowfive@57: ["None"] = 0, yellowfive@57: ["BloodElf"] = 1, yellowfive@57: ["Draenei"] = 2, yellowfive@57: ["Dwarf"] = 3, yellowfive@57: ["Gnome"] = 4, yellowfive@57: ["Human"] = 5, yellowfive@57: ["NightElf"] = 6, yellowfive@57: ["Orc"] = 7, yellowfive@57: ["Tauren"] = 8, yellowfive@57: ["Troll"] = 9, yellowfive@57: ["Scourge"] = 10, yellowfive@57: ["Undead"] = 10, yellowfive@57: ["Goblin"] = 11, yellowfive@57: ["Worgen"] = 12, yellowfive@57: ["Pandaren"] = 13 yellowfive@57: } yellowfive@57: yellowfive@57: Amr.FactionIds = { yellowfive@57: ["None"] = 0, yellowfive@57: ["Alliance"] = 1, yellowfive@57: ["Horde"] = 2 yellowfive@57: } yellowfive@57: yellowfive@57: Amr.InstanceIds = { yellowfive@57: Auchindoun = 1182, yellowfive@57: BloodmaulSlagMines = 1175, yellowfive@57: GrimrailDepot = 1208, yellowfive@57: IronDocks = 1195, yellowfive@57: ShadowmoonBurialGrounds = 1176, yellowfive@57: Skyreach = 1209, yellowfive@57: TheEverbloom = 1279, yellowfive@57: UpperBlackrockSpire = 1358, yellowfive@57: Highmaul = 1228, yellowfive@61: BlackrockFoundry = 1205, yellowfive@61: HellfireCitadel = 1448 yellowfive@57: } yellowfive@57: yellowfive@57: -- instances that AskMrRobot currently supports logging for yellowfive@57: Amr.SupportedInstanceIds = { yellowfive@57: --[1182] = true, yellowfive@57: --[1175] = true, yellowfive@57: --[1208] = true, yellowfive@57: --[1195] = true, yellowfive@57: --[1176] = true, yellowfive@57: --[1209] = true, yellowfive@57: --[1279] = true, yellowfive@57: --[1358] = true, yellowfive@57: [1228] = true, yellowfive@61: [1205] = true, yellowfive@61: [1448] = true yellowfive@57: } yellowfive@57: yellowfive@57: -- IDs of set tokens that we would care about in a player's inventory yellowfive@57: Amr.SetTokenIds = { yellowfive@63: [127970] = true, yellowfive@63: [127969] = true, yellowfive@63: [127968] = true, yellowfive@63: [127967] = true, yellowfive@63: [127966] = true, yellowfive@63: [127965] = true, yellowfive@63: [127964] = true, yellowfive@63: [127963] = true, yellowfive@63: [127962] = true, yellowfive@63: [127961] = true, yellowfive@63: [127960] = true, yellowfive@63: [127959] = true, yellowfive@63: [127958] = true, yellowfive@63: [127957] = true, yellowfive@63: [127956] = true, yellowfive@63: [127955] = true, yellowfive@63: [127954] = true, yellowfive@63: [127953] = true, yellowfive@57: [120285] = true, yellowfive@57: [120284] = true, yellowfive@57: [120283] = true, yellowfive@57: [120282] = true, yellowfive@57: [120281] = true, yellowfive@57: [120280] = true, yellowfive@57: [120279] = true, yellowfive@57: [120278] = true, yellowfive@57: [120277] = true, yellowfive@57: [120256] = true, yellowfive@57: [120255] = true, yellowfive@57: [120254] = true, yellowfive@57: [120253] = true, yellowfive@57: [120252] = true, yellowfive@57: [120251] = true, yellowfive@57: [120250] = true, yellowfive@57: [120249] = true, yellowfive@57: [120248] = true, yellowfive@57: [120247] = true, yellowfive@57: [120246] = true, yellowfive@57: [120245] = true, yellowfive@57: [120244] = true, yellowfive@57: [120243] = true, yellowfive@57: [120242] = true, yellowfive@57: [120241] = true, yellowfive@57: [120240] = true, yellowfive@57: [120239] = true, yellowfive@57: [120238] = true, yellowfive@57: [120237] = true, yellowfive@57: [120236] = true, yellowfive@57: [120235] = true, yellowfive@57: [120234] = true, yellowfive@57: [120233] = true, yellowfive@57: [120232] = true, yellowfive@57: [120231] = true, yellowfive@57: [120230] = true, yellowfive@57: [120229] = true, yellowfive@57: [120228] = true, yellowfive@57: [120227] = true, yellowfive@57: [120226] = true, yellowfive@57: [120225] = true, yellowfive@57: [120224] = true, yellowfive@57: [120223] = true, yellowfive@57: [120222] = true, yellowfive@57: [120221] = true, yellowfive@57: [120220] = true, yellowfive@57: [120219] = true, yellowfive@57: [120218] = true, yellowfive@57: [120217] = true, yellowfive@57: [120216] = true, yellowfive@57: [120215] = true, yellowfive@57: [120214] = true, yellowfive@57: [120213] = true, yellowfive@57: [120212] = true, yellowfive@57: [120211] = true, yellowfive@57: [120210] = true, yellowfive@57: [120209] = true, yellowfive@57: [120208] = true, yellowfive@57: [120207] = true, yellowfive@57: [120206] = true, yellowfive@57: [119323] = true, yellowfive@57: [119322] = true, yellowfive@57: [119321] = true, yellowfive@57: [119320] = true, yellowfive@57: [119319] = true, yellowfive@57: [119318] = true, yellowfive@57: [119316] = true, yellowfive@57: [119315] = true, yellowfive@57: [119314] = true, yellowfive@57: [119313] = true, yellowfive@57: [119312] = true, yellowfive@57: [119311] = true, yellowfive@57: [119310] = true, yellowfive@57: [119309] = true, yellowfive@57: [119308] = true, yellowfive@57: [119307] = true, yellowfive@57: [119306] = true, yellowfive@57: [119305] = true, yellowfive@57: [105868] = true, yellowfive@57: [105867] = true, yellowfive@57: [105866] = true, yellowfive@57: [105865] = true, yellowfive@57: [105864] = true, yellowfive@57: [105863] = true, yellowfive@57: [105862] = true, yellowfive@57: [105861] = true, yellowfive@57: [105860] = true, yellowfive@57: [105859] = true, yellowfive@57: [105858] = true, yellowfive@57: [105857] = true, yellowfive@57: [99756] = true, yellowfive@57: [99755] = true, yellowfive@57: [99754] = true, yellowfive@57: [99753] = true, yellowfive@57: [99752] = true, yellowfive@57: [99751] = true, yellowfive@57: [99750] = true, yellowfive@57: [99749] = true, yellowfive@57: [99748] = true, yellowfive@57: [99747] = true, yellowfive@57: [99746] = true, yellowfive@57: [99745] = true, yellowfive@57: [99744] = true, yellowfive@57: [99743] = true, yellowfive@57: [99742] = true, yellowfive@57: [99740] = true, yellowfive@57: [99739] = true, yellowfive@57: [99738] = true, yellowfive@57: [99737] = true, yellowfive@57: [99736] = true, yellowfive@57: [99735] = true, yellowfive@57: [99734] = true, yellowfive@57: [99733] = true, yellowfive@57: [99732] = true, yellowfive@57: [99731] = true, yellowfive@57: [99730] = true, yellowfive@57: [99729] = true, yellowfive@57: [99728] = true, yellowfive@57: [99727] = true, yellowfive@57: [99726] = true, yellowfive@57: [99725] = true, yellowfive@57: [99724] = true, yellowfive@57: [99723] = true, yellowfive@57: [99722] = true, yellowfive@57: [99721] = true, yellowfive@57: [99720] = true, yellowfive@57: [99719] = true, yellowfive@57: [99718] = true, yellowfive@57: [99717] = true, yellowfive@57: [99716] = true, yellowfive@57: [99715] = true, yellowfive@57: [99714] = true, yellowfive@57: [99713] = true, yellowfive@57: [99712] = true, yellowfive@57: [99711] = true, yellowfive@57: [99710] = true, yellowfive@57: [99709] = true, yellowfive@57: [99708] = true, yellowfive@57: [99707] = true, yellowfive@57: [99706] = true, yellowfive@57: [99705] = true, yellowfive@57: [99704] = true, yellowfive@57: [99703] = true, yellowfive@57: [99702] = true, yellowfive@57: [99701] = true, yellowfive@57: [99700] = true, yellowfive@57: [99699] = true, yellowfive@57: [99698] = true, yellowfive@57: [99697] = true, yellowfive@57: [99696] = true, yellowfive@57: [99695] = true, yellowfive@57: [99694] = true, yellowfive@57: [99693] = true, yellowfive@57: [99692] = true, yellowfive@57: [99691] = true, yellowfive@57: [99690] = true, yellowfive@57: [99689] = true, yellowfive@57: [99688] = true, yellowfive@57: [99687] = true, yellowfive@57: [99686] = true, yellowfive@57: [99685] = true, yellowfive@57: [99684] = true, yellowfive@57: [99683] = true, yellowfive@57: [99682] = true, yellowfive@57: [99681] = true, yellowfive@57: [99680] = true, yellowfive@57: [99679] = true, yellowfive@57: [99678] = true, yellowfive@57: [99677] = true, yellowfive@57: [99676] = true, yellowfive@57: [99675] = true, yellowfive@57: [99674] = true, yellowfive@57: [99673] = true, yellowfive@57: [99672] = true, yellowfive@57: [99671] = true, yellowfive@57: [99670] = true, yellowfive@57: [99669] = true, yellowfive@57: [99668] = true, yellowfive@57: [99667] = true, yellowfive@57: [96701] = true, yellowfive@57: [96700] = true, yellowfive@57: [96699] = true, yellowfive@57: [96633] = true, yellowfive@57: [96632] = true, yellowfive@57: [96631] = true, yellowfive@57: [96625] = true, yellowfive@57: [96624] = true, yellowfive@57: [96623] = true, yellowfive@57: [96601] = true, yellowfive@57: [96600] = true, yellowfive@57: [96599] = true, yellowfive@57: [96568] = true, yellowfive@57: [96567] = true, yellowfive@57: [96566] = true, yellowfive@57: [95957] = true, yellowfive@57: [95956] = true, yellowfive@57: [95955] = true, yellowfive@57: [95889] = true, yellowfive@57: [95888] = true, yellowfive@57: [95887] = true, yellowfive@57: [95881] = true, yellowfive@57: [95880] = true, yellowfive@57: [95879] = true, yellowfive@57: [95857] = true, yellowfive@57: [95856] = true, yellowfive@57: [95855] = true, yellowfive@57: [95824] = true, yellowfive@57: [95823] = true, yellowfive@57: [95822] = true, yellowfive@57: [95583] = true, yellowfive@57: [95582] = true, yellowfive@57: [95581] = true, yellowfive@57: [95580] = true, yellowfive@57: [95579] = true, yellowfive@57: [95578] = true, yellowfive@57: [95577] = true, yellowfive@57: [95576] = true, yellowfive@57: [95575] = true, yellowfive@57: [95574] = true, yellowfive@57: [95573] = true, yellowfive@57: [95572] = true, yellowfive@57: [95571] = true, yellowfive@57: [95570] = true, yellowfive@57: [95569] = true, yellowfive@57: [89278] = true, yellowfive@57: [89277] = true, yellowfive@57: [89276] = true, yellowfive@57: [89275] = true, yellowfive@57: [89274] = true, yellowfive@57: [89273] = true, yellowfive@57: [89272] = true, yellowfive@57: [89271] = true, yellowfive@57: [89270] = true, yellowfive@57: [89269] = true, yellowfive@57: [89268] = true, yellowfive@57: [89267] = true, yellowfive@57: [89266] = true, yellowfive@57: [89265] = true, yellowfive@57: [89264] = true, yellowfive@57: [89263] = true, yellowfive@57: [89262] = true, yellowfive@57: [89261] = true, yellowfive@57: [89260] = true, yellowfive@57: [89259] = true, yellowfive@57: [89258] = true, yellowfive@57: [89257] = true, yellowfive@57: [89256] = true, yellowfive@57: [89255] = true, yellowfive@57: [89254] = true, yellowfive@57: [89253] = true, yellowfive@57: [89252] = true, yellowfive@57: [89251] = true, yellowfive@57: [89250] = true, yellowfive@57: [89249] = true, yellowfive@57: [89248] = true, yellowfive@57: [89247] = true, yellowfive@57: [89246] = true, yellowfive@57: [89245] = true, yellowfive@57: [89244] = true, yellowfive@57: [89243] = true, yellowfive@57: [89242] = true, yellowfive@57: [89241] = true, yellowfive@57: [89240] = true, yellowfive@57: [89239] = true, yellowfive@57: [89238] = true, yellowfive@57: [89237] = true, yellowfive@57: [89236] = true, yellowfive@57: [89235] = true, yellowfive@57: [89234] = true, yellowfive@57: [78876] = true, yellowfive@57: [78875] = true, yellowfive@57: [78874] = true, yellowfive@57: [78873] = true, yellowfive@57: [78872] = true, yellowfive@57: [78871] = true, yellowfive@57: [78867] = true, yellowfive@57: [78866] = true, yellowfive@57: [78865] = true, yellowfive@57: [78864] = true, yellowfive@57: [78863] = true, yellowfive@57: [78862] = true, yellowfive@57: [78861] = true, yellowfive@57: [78860] = true, yellowfive@57: [78859] = true, yellowfive@57: [78858] = true, yellowfive@57: [78857] = true, yellowfive@57: [78856] = true, yellowfive@57: [78855] = true, yellowfive@57: [78854] = true, yellowfive@57: [78853] = true, yellowfive@57: [78849] = true, yellowfive@57: [78848] = true, yellowfive@57: [78847] = true, yellowfive@57: [78184] = true, yellowfive@57: [78183] = true, yellowfive@57: [78181] = true, yellowfive@57: [78180] = true, yellowfive@57: [78179] = true, yellowfive@57: [78178] = true, yellowfive@57: [78176] = true, yellowfive@57: [78175] = true, yellowfive@57: [78174] = true, yellowfive@57: [78173] = true, yellowfive@57: [78171] = true, yellowfive@57: [78170] = true, yellowfive@57: [71687] = true, yellowfive@57: [71686] = true, yellowfive@57: [71685] = true, yellowfive@57: [71683] = true, yellowfive@57: [71682] = true, yellowfive@57: [71680] = true, yellowfive@57: [71679] = true, yellowfive@57: [71678] = true, yellowfive@57: [71676] = true, yellowfive@57: [71675] = true, yellowfive@57: [71673] = true, yellowfive@57: [71672] = true, yellowfive@57: [71671] = true, yellowfive@57: [71669] = true, yellowfive@57: [71668] = true, yellowfive@57: [67431] = true, yellowfive@57: [67430] = true, yellowfive@57: [67429] = true, yellowfive@57: [67428] = true, yellowfive@57: [67427] = true, yellowfive@57: [67426] = true, yellowfive@57: [67425] = true, yellowfive@57: [67424] = true, yellowfive@57: [67423] = true, yellowfive@57: [66998] = true, yellowfive@57: [65089] = true, yellowfive@57: [65088] = true, yellowfive@57: [65087] = true, yellowfive@57: [63684] = true, yellowfive@57: [63683] = true, yellowfive@57: [63682] = true, yellowfive@63: [51320] = true, yellowfive@57: [45652] = true, yellowfive@57: [45651] = true, yellowfive@57: [45650] = true, yellowfive@57: [45649] = true, yellowfive@57: [45648] = true, yellowfive@57: [45647] = true, yellowfive@57: [45643] = true, yellowfive@57: [45642] = true, yellowfive@57: [45641] = true, yellowfive@57: [40630] = true, yellowfive@57: [40629] = true, yellowfive@57: [40628] = true, yellowfive@57: [40621] = true, yellowfive@57: [40620] = true, yellowfive@57: [40619] = true, yellowfive@57: [40618] = true, yellowfive@57: [40617] = true, yellowfive@57: [40616] = true, yellowfive@57: [34544] = true, yellowfive@57: [31100] = true, yellowfive@57: [31099] = true, yellowfive@57: [31098] = true, yellowfive@57: [31097] = true, yellowfive@57: [31096] = true, yellowfive@57: [31095] = true, yellowfive@57: [30247] = true, yellowfive@57: [30246] = true, yellowfive@57: [30245] = true, yellowfive@57: [30244] = true, yellowfive@57: [30243] = true, yellowfive@57: [30242] = true, yellowfive@57: [29767] = true, yellowfive@57: [29766] = true, yellowfive@57: [29765] = true, yellowfive@57: [29761] = true, yellowfive@57: [29760] = true, yellowfive@57: [29759] = true yellowfive@57: } yellowfive@57: yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: -- Public Utility Methods yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: yellowfive@81: local function readBonusIdList(parts, first, last) yellowfive@81: local ret = {} yellowfive@81: for i = first, last do yellowfive@81: table.insert(ret, tonumber(parts[i])) yellowfive@81: end yellowfive@81: table.sort(ret) yellowfive@81: return ret yellowfive@81: end yellowfive@81: yellowfive@81: local function setRelicId(item, index, relicBonuses) yellowfive@81: local relicId = item.gemIds[index] .. "" yellowfive@81: for i = 1, #relicBonuses do yellowfive@81: relicId = relicId .. "." .. relicBonuses[i] yellowfive@81: end yellowfive@81: local list = item.gemItemIds or {} yellowfive@81: list[i] = relicId yellowfive@81: end yellowfive@81: yellowfive@81: --|color|Hitem:135820:enchant:gem1:gem2:gem3:gem4:suffixID:uniqueID:playerlevel:spec?:flags:11:numBonusIDs:bonusID1:bonusID2...:playerlevelwhengotitem, 296 for warrior artifact:upgrade ID?:num artifact bonuses?:artifact bonus 1:artifact bonus 2:artifact bonus 3:[item name] yellowfive@81: -- 133004 for relic on my warrior, gem2 yellowfive@81: -- 296::3:767:1507:1809:[item name] this is for warrior artifact with the above relic in storm slot, for parts after the bonus IDs yellowfive@81: yellowfive@81: --|cffa335ee|Hitem:itemID:enchant:gem1:gem2:gem3:gem4:suffixID:uniqueID:level:unknown:unknown:instanceDifficultyID:numBonusIDs:bonusID1:bonusID2...|h[item name]|h|r yellowfive@81: yellowfive@69: -- item link format: |cffa335ee|Hitem:itemID:enchant:gem1:gem2:gem3:gem4:suffixID:uniqueID:level:unknown:unknown:instanceDifficultyID:numBonusIDs:bonusID1:bonusID2...|h[item name]|h|r yellowfive@57: -- get an object with all of the parts of the item link format that we care about yellowfive@57: function Amr.ParseItemLink(itemLink) yellowfive@57: if not itemLink then return nil end yellowfive@57: yellowfive@57: local str = string.match(itemLink, "|Hitem:([\-%d:]+)|") yellowfive@57: if not str then return nil end yellowfive@57: yellowfive@57: local parts = { strsplit(":", str) } yellowfive@57: yellowfive@57: local item = {} yellowfive@81: item.id = tonumber(parts[1]) or 0 yellowfive@81: item.enchantId = tonumber(parts[2]) or 0 yellowfive@81: item.gemIds = { tonumber(parts[3]) or 0, tonumber(parts[4]) or 0, tonumber(parts[5]) or 0, tonumber(parts[6]) or 0 } yellowfive@81: item.suffixId = math.abs(tonumber(parts[7]) or 0) -- convert suffix to positive number, that's what we use in our code yellowfive@81: -- part 8 is some unique ID... we never really used it yellowfive@81: -- part 9 is current player level yellowfive@81: -- part 10 is player spec yellowfive@81: local upgradeIdType = tonumber(parts[11]) or 0 -- part 11 indicates what kind of upgrade ID is just after the bonus IDs yellowfive@81: -- part 12 is instance difficulty id yellowfive@57: yellowfive@81: local numBonuses = tonumber(parts[13]) or 0 yellowfive@81: local offset = numBonuses yellowfive@81: if numBonuses > 0 then yellowfive@81: item.bonusIds = readBonusIdList(parts, 14, 13 + numBonuses) yellowfive@57: end yellowfive@69: yellowfive@81: item.upgradeId = 0 yellowfive@81: item.level = 0 yellowfive@81: yellowfive@81: -- the next part after bonus IDs depends on the upgrade id type; is either the "drop level" or upgrade ID, or not sure for artifacts yellowfive@81: if upgradeIdType == 4 then yellowfive@81: item.upgradeId = tonumber(parts[14 + offset]) or 0 yellowfive@81: elseif upgradeIdType == 512 then yellowfive@81: item.level = tonumber(parts[14 + offset]) or 0 yellowfive@69: end yellowfive@81: yellowfive@81: -- ignore relic stuff in the item link for now, we read the relic information directly and save it with artifact power info yellowfive@81: --[[ yellowfive@81: -- the next part is the number of bonus IDs on the first relic slot of the artifact yellowfive@81: numBonuses = tonumber(parts[15 + offset]) or 0 yellowfive@81: if numBonuses > 0 then yellowfive@81: local relicBonuses = readBonusIdList(16 + offset, 15 + offset + numBonuses, parts) yellowfive@81: setRelicId(item, 1, relicBonuses) yellowfive@81: end yellowfive@81: yellowfive@81: -- second relic slot bonus IDs yellowfive@81: offset = offset + numBonuses yellowfive@81: numBonuses = tonumber(parts[16 + offset]) or 0 yellowfive@81: if numBonuses > 0 then yellowfive@81: local relicBonuses = readBonusIdList(17 + offset, 16 + offset + numBonuses, parts) yellowfive@81: setRelicId(item, 2, relicBonuses) yellowfive@81: end yellowfive@81: yellowfive@81: -- third relic slot bonus IDs yellowfive@81: offset = offset + numBonuses yellowfive@81: numBonuses = tonumber(parts[17 + offset]) or 0 yellowfive@81: if numBonuses > 0 then yellowfive@81: local relicBonuses = readBonusIdList(18 + offset, 17 + offset + numBonuses, parts) yellowfive@81: setRelicId(item, 3, relicBonuses) yellowfive@81: end yellowfive@81: ]] yellowfive@81: yellowfive@57: return item yellowfive@57: end yellowfive@57: yellowfive@81: function Amr.GetItemUniqueId(item, noUpgrade) yellowfive@81: if not item then return "" end yellowfive@81: local ret = item.id .. "" yellowfive@81: if item.bonusIds then yellowfive@81: for i = 1, #item.bonusIds do yellowfive@81: ret = ret .. "b" .. item.bonusIds[i] yellowfive@81: end yellowfive@81: end yellowfive@81: if item.suffixId ~= 0 then yellowfive@81: ret = ret .. "s" .. item.suffixId yellowfive@81: end yellowfive@81: if not noUpgrade and item.upgradeId ~= 0 then yellowfive@81: ret = ret .. "u" .. item.upgradeId yellowfive@81: end yellowfive@81: if item.level ~= 0 then yellowfive@81: ret = ret .. "v" .. item.level yellowfive@81: end yellowfive@81: return ret yellowfive@81: end yellowfive@81: yellowfive@57: -- returns true if this is an instance that AskMrRobot supports for logging yellowfive@57: function Amr.IsSupportedInstanceId(instanceMapID) yellowfive@57: if Amr.SupportedInstanceIds[tonumber(instanceMapID)] then yellowfive@57: return true yellowfive@57: else yellowfive@57: return false yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- returns true if currently in a supported instance for logging yellowfive@57: function Amr.IsSupportedInstance() yellowfive@57: local zone, _, difficultyIndex, _, _, _, _, instanceMapID = GetInstanceInfo() yellowfive@57: return Amr.IsSupportedInstanceId(instanceMapID) yellowfive@57: end yellowfive@57: yellowfive@81: -- helper to iterate over a table in order by its keys yellowfive@81: local function spairs(t, order) yellowfive@81: -- collect the keys yellowfive@81: local keys = {} yellowfive@81: for k in pairs(t) do keys[#keys+1] = k end yellowfive@81: yellowfive@81: -- if order function given, sort by it by passing the table and keys a, b, yellowfive@81: -- otherwise just sort the keys yellowfive@81: if order then yellowfive@81: table.sort(keys, function(a,b) return order(t, a, b) end) yellowfive@81: else yellowfive@81: table.sort(keys) yellowfive@81: end yellowfive@81: yellowfive@81: -- return the iterator function yellowfive@81: local i = 0 yellowfive@81: return function() yellowfive@81: i = i + 1 yellowfive@81: if keys[i] then yellowfive@81: return keys[i], t[keys[i]] yellowfive@81: end yellowfive@81: end yellowfive@81: end yellowfive@81: yellowfive@81: -- scanning tooltip b/c for some odd reason the api has no way to get basic item properties... yellowfive@81: -- so you have to generate a fake item tooltip and search for pre-defined strings in the display text yellowfive@81: local _scanTt yellowfive@81: function Amr.GetScanningTooltip() yellowfive@81: if not _scanTt then yellowfive@81: _scanTt = CreateFrame("GameTooltip", "AmrUiScanTooltip", nil, "GameTooltipTemplate") yellowfive@81: _scanTt:SetOwner(UIParent, "ANCHOR_NONE") yellowfive@81: end yellowfive@81: return _scanTt yellowfive@81: end yellowfive@81: yellowfive@81: -- get the item tooltip for the specified item in one of your bags, or if bagId is nil, an equipped item, or if slotId is also nil, the specified item link yellowfive@81: function Amr.GetItemTooltip(bagId, slotId, link) yellowfive@81: local tt = Amr.GetScanningTooltip() yellowfive@81: tt:ClearLines() yellowfive@81: if bagId then yellowfive@81: tt:SetBagItem(bagId, slotId) yellowfive@81: elseif slotId then yellowfive@81: tt:SetInventoryItem("player", slotId) yellowfive@81: else yellowfive@81: tt:SetHyperlink(link) yellowfive@81: end yellowfive@81: return tt yellowfive@81: end yellowfive@81: yellowfive@81: function Amr.GetItemLevel(bagId, slotId, link) yellowfive@81: local itemLevelPattern = _G["ITEM_LEVEL"]:gsub("%%d", "(%%d+)") yellowfive@81: local tt = Amr.GetItemTooltip(bagId, slotId, link) yellowfive@81: yellowfive@81: local regions = { tt:GetRegions() } yellowfive@81: for i, region in ipairs(regions) do yellowfive@81: if region and region:GetObjectType() == "FontString" then yellowfive@81: local text = region:GetText() yellowfive@81: if text then yellowfive@81: ilvl = tonumber(text:match(itemLevelPattern)) yellowfive@81: if ilvl then yellowfive@81: return ilvl yellowfive@81: end yellowfive@81: end yellowfive@81: end yellowfive@81: end yellowfive@81: yellowfive@81: -- 0 means we couldn't find it for whatever reason yellowfive@81: return 0 yellowfive@81: end yellowfive@81: yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: -- Character Reading yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: yellowfive@57: local function readProfessionInfo(prof, ret) yellowfive@57: if prof then yellowfive@57: local name, icon, skillLevel, maxSkillLevel, numAbilities, spelloffset, skillLine, skillModifier = GetProfessionInfo(prof); yellowfive@57: if Amr.ProfessionSkillLineToName[skillLine] ~= nil then yellowfive@57: ret.Professions[Amr.ProfessionSkillLineToName[skillLine]] = skillLevel; yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@81: --[[ yellowfive@81: local function getTalents(specPos) yellowfive@57: local talentInfo = {} yellowfive@57: local maxTiers = 7 yellowfive@57: for tier = 1, maxTiers do yellowfive@57: for col = 1, 3 do yellowfive@81: local id, name, _, _, _, spellId, _, t, c, selected = GetTalentInfoBySpecialization(specPos, tier, col) yellowfive@57: if selected then yellowfive@57: talentInfo[tier] = col yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: local str = "" yellowfive@57: for i = 1, maxTiers do yellowfive@57: if talentInfo[i] then yellowfive@57: str = str .. talentInfo[i] yellowfive@57: else yellowfive@57: str = str .. '0' yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: return str yellowfive@57: end yellowfive@81: ]] yellowfive@57: yellowfive@81: --[[ yellowfive@57: local function getGlyphs(specGroup) yellowfive@57: local glyphs = {} yellowfive@57: for i = 1, NUM_GLYPH_SLOTS do yellowfive@57: local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, specGroup) yellowfive@57: if (glyphID) then yellowfive@57: table.insert(glyphs, glyphSpellID) yellowfive@57: end yellowfive@57: end yellowfive@57: return glyphs; yellowfive@57: end yellowfive@81: ]] yellowfive@57: yellowfive@81: -- get specs and talents yellowfive@81: local function readSpecs(ret) yellowfive@57: yellowfive@81: for pos = 1, 4 do yellowfive@57: -- spec, convert game spec id to one of our spec ids yellowfive@81: local specId = GetSpecializationInfo(pos) yellowfive@57: if specId then yellowfive@81: ret.Specs[pos] = Amr.SpecIds[specId] yellowfive@81: -- TODO: figure out how to read inactive spec talents if possible... used to be able to but they changed it yellowfive@81: --ret.Talents[pos] = getTalents(pos) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@81: -- TODO: hopefully we can read artifact here when there is an API to get info when the artifact UI is not open yellowfive@81: -- get artifact info yellowfive@81: local function readArtifact() yellowfive@81: yellowfive@81: end yellowfive@81: yellowfive@57: -- get currently equipped items, store with currently active spec yellowfive@57: local function readEquippedItems(ret) yellowfive@57: local equippedItems = {}; yellowfive@57: for slotNum = 1, #Amr.SlotIds do yellowfive@57: local slotId = Amr.SlotIds[slotNum] yellowfive@57: local itemLink = GetInventoryItemLink("player", slotId) yellowfive@57: if itemLink then yellowfive@57: equippedItems[slotId] = itemLink yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- store last-seen equipped gear for each spec yellowfive@81: ret.Equipped[GetSpecialization()] = equippedItems yellowfive@57: end yellowfive@57: yellowfive@57: -- Get all data about the player as an object, includes: yellowfive@57: -- serializer version yellowfive@57: -- region/realm/name yellowfive@57: -- guild yellowfive@57: -- race yellowfive@57: -- faction yellowfive@57: -- level yellowfive@57: -- professions yellowfive@81: -- spec/talent for all specs yellowfive@81: -- artifact for current spec yellowfive@57: -- equipped gear for the current spec yellowfive@57: -- yellowfive@81: function Amr:GetPlayerData() yellowfive@57: yellowfive@57: local ret = {} yellowfive@57: yellowfive@57: ret.Region = Amr.RegionNames[GetCurrentRegion()] yellowfive@57: ret.Realm = GetRealmName() yellowfive@57: ret.Name = UnitName("player") yellowfive@57: ret.Guild = GetGuildInfo("player") yellowfive@81: ret.ActiveSpec = GetSpecialization() yellowfive@57: ret.Level = UnitLevel("player"); yellowfive@57: yellowfive@57: local cls, clsEn = UnitClass("player") yellowfive@57: ret.Class = clsEn; yellowfive@57: yellowfive@57: local race, raceEn = UnitRace("player") yellowfive@57: ret.Race = raceEn; yellowfive@57: ret.Faction = UnitFactionGroup("player") yellowfive@57: yellowfive@57: ret.Professions = {}; yellowfive@57: local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions(); yellowfive@57: readProfessionInfo(prof1, ret) yellowfive@57: readProfessionInfo(prof2, ret) yellowfive@57: readProfessionInfo(archaeology, ret) yellowfive@57: readProfessionInfo(fishing, ret) yellowfive@57: readProfessionInfo(cooking, ret) yellowfive@57: readProfessionInfo(firstAid, ret) yellowfive@57: yellowfive@57: ret.Specs = {} yellowfive@57: ret.Talents = {} yellowfive@81: readSpecs(ret) yellowfive@81: yellowfive@81: ret.Artifacts = {} yellowfive@81: readArtifact() yellowfive@57: yellowfive@57: ret.Equipped = {} yellowfive@57: readEquippedItems(ret) yellowfive@57: yellowfive@57: return ret yellowfive@57: end yellowfive@57: yellowfive@57: yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: -- Serialization yellowfive@57: ---------------------------------------------------------------------------------------- yellowfive@57: yellowfive@57: local function toCompressedNumberList(list) yellowfive@57: -- ensure the values are numbers, sorted from lowest to highest yellowfive@57: local nums = {} yellowfive@57: for i, v in ipairs(list) do yellowfive@57: table.insert(nums, tonumber(v)) yellowfive@57: end yellowfive@57: table.sort(nums) yellowfive@57: yellowfive@57: local ret = {} yellowfive@57: local prev = 0 yellowfive@57: for i, v in ipairs(nums) do yellowfive@57: local diff = v - prev yellowfive@57: table.insert(ret, diff) yellowfive@57: prev = v yellowfive@57: end yellowfive@57: yellowfive@57: return table.concat(ret, ",") yellowfive@57: end yellowfive@57: yellowfive@57: -- make this utility publicly available yellowfive@57: function Amr:ToCompressedNumberList(list) yellowfive@57: return toCompressedNumberList(list) yellowfive@57: end yellowfive@57: yellowfive@57: -- appends a list of items to the export yellowfive@57: local function appendItemsToExport(fields, itemObjects) yellowfive@57: yellowfive@57: -- sort by item id so we can compress it more easily yellowfive@57: table.sort(itemObjects, function(a, b) return a.id < b.id end) yellowfive@57: yellowfive@57: -- append to the export string yellowfive@57: local prevItemId = 0 yellowfive@57: local prevGemId = 0 yellowfive@57: local prevEnchantId = 0 yellowfive@57: local prevUpgradeId = 0 yellowfive@57: local prevBonusId = 0 yellowfive@81: local prevLevel = 0 yellowfive@57: for i, itemData in ipairs(itemObjects) do yellowfive@57: local itemParts = {} yellowfive@57: yellowfive@81: -- for now export the item level of artifacts as the "drop level" because it is a pain in the ass to figure it out from the bonus IDs yellowfive@81: --local _, _, quality = GetItemInfo(itemData.link) yellowfive@81: --if quality == 6 then yellowfive@81: -- itemData.level = Amr.GetItemLevel(nil, nil, itemData.link) yellowfive@81: --end yellowfive@81: yellowfive@57: table.insert(itemParts, itemData.id - prevItemId) yellowfive@57: prevItemId = itemData.id yellowfive@57: yellowfive@57: if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end yellowfive@57: if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end yellowfive@57: if itemData.upgradeId ~= 0 then yellowfive@57: table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId)) yellowfive@57: prevUpgradeId = itemData.upgradeId yellowfive@57: end yellowfive@81: if itemData.level ~= 0 then yellowfive@81: table.insert(itemParts, "v" .. (itemData.level - prevLevel)) yellowfive@81: prevLevel = itemData.level yellowfive@81: end yellowfive@57: if itemData.bonusIds then yellowfive@57: for bIndex, bValue in ipairs(itemData.bonusIds) do yellowfive@57: table.insert(itemParts, "b" .. (bValue - prevBonusId)) yellowfive@57: prevBonusId = bValue yellowfive@57: end yellowfive@57: end yellowfive@81: yellowfive@81: if itemData.gemIds[1] ~= 0 then yellowfive@81: table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId)) yellowfive@81: prevGemId = itemData.gemIds[1] yellowfive@81: end yellowfive@81: if itemData.gemIds[2] ~= 0 then yellowfive@81: table.insert(itemParts, "y" .. (itemData.gemIds[2] - prevGemId)) yellowfive@81: prevGemId = itemData.gemIds[2] yellowfive@81: end yellowfive@81: if itemData.gemIds[3] ~= 0 then yellowfive@81: table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId)) yellowfive@81: prevGemId = itemData.gemIds[3] yellowfive@81: end yellowfive@81: yellowfive@57: if itemData.enchantId ~= 0 then yellowfive@57: table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId)) yellowfive@57: prevEnchantId = itemData.enchantId yellowfive@57: end yellowfive@57: yellowfive@57: table.insert(fields, table.concat(itemParts, "")) yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- Serialize just the identity portion of a player (region/realm/name) in the same format used by the full serialization yellowfive@57: function Amr:SerializePlayerIdentity(data) yellowfive@57: local fields = {} yellowfive@57: table.insert(fields, MINOR) yellowfive@57: table.insert(fields, data.Region) yellowfive@57: table.insert(fields, data.Realm) yellowfive@57: table.insert(fields, data.Name) yellowfive@57: return "$" .. table.concat(fields, ";") .. "$" yellowfive@57: end yellowfive@57: yellowfive@57: -- Serialize player data gathered by GetPlayerData. This can be augmented with extra data if desired (augmenting used mainly by AskMrRobot addon). yellowfive@57: -- Pass complete = true to do a complete export of this extra information, otherwise it is ignored. yellowfive@57: -- Extra data can include: yellowfive@57: -- equipped gear for the player's inactive spec, slot id to item link dictionary yellowfive@57: -- Reputations yellowfive@57: -- BagItems, BankItems, VoidItems, lists of item links yellowfive@57: -- yellowfive@57: function Amr:SerializePlayerData(data, complete) yellowfive@57: yellowfive@57: local fields = {} yellowfive@57: yellowfive@57: -- compressed string uses a fixed order rather than inserting identifiers yellowfive@57: table.insert(fields, MINOR) yellowfive@57: table.insert(fields, data.Region) yellowfive@57: table.insert(fields, data.Realm) yellowfive@57: table.insert(fields, data.Name) yellowfive@57: yellowfive@57: -- guild name yellowfive@57: if data.Guild == nil then yellowfive@57: table.insert(fields, "") yellowfive@57: else yellowfive@57: table.insert(fields, data.Guild) yellowfive@57: end yellowfive@57: yellowfive@57: -- race, default to pandaren if we can't read it for some reason yellowfive@57: local raceval = Amr.RaceIds[data.Race] yellowfive@57: if raceval == nil then raceval = 13 end yellowfive@57: table.insert(fields, raceval) yellowfive@57: yellowfive@57: -- faction, default to alliance if we can't read it for some reason yellowfive@57: raceval = Amr.FactionIds[data.Faction] yellowfive@57: if raceval == nil then raceval = 1 end yellowfive@57: table.insert(fields, raceval) yellowfive@57: yellowfive@57: table.insert(fields, data.Level) yellowfive@57: yellowfive@57: local profs = {} yellowfive@57: local noprofs = true yellowfive@57: if data.Professions then yellowfive@57: for k, v in pairs(data.Professions) do yellowfive@57: local profval = Amr.ProfessionIds[k] yellowfive@57: if profval ~= nil then yellowfive@57: noprofs = false yellowfive@57: table.insert(profs, profval .. ":" .. v) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: if noprofs then yellowfive@57: table.insert(profs, "0:0") yellowfive@57: end yellowfive@57: yellowfive@57: table.insert(fields, table.concat(profs, ",")) yellowfive@57: yellowfive@57: -- export specs yellowfive@57: table.insert(fields, data.ActiveSpec) yellowfive@81: for spec = 1, 4 do yellowfive@57: if data.Specs[spec] and (complete or spec == data.ActiveSpec) then yellowfive@57: table.insert(fields, ".s" .. spec) -- indicates the start of a spec block yellowfive@81: table.insert(fields, data.Specs[spec]) yellowfive@81: table.insert(fields, data.Talents[spec]) yellowfive@57: yellowfive@81: local powerids = {} yellowfive@81: local powerranks = {} yellowfive@81: local reliclinks = {} yellowfive@81: yellowfive@81: local artifactInfo = data.Artifacts and data.Artifacts[spec] yellowfive@81: if artifactInfo and artifactInfo.Powers then yellowfive@81: for k, v in spairs(artifactInfo.Powers) do yellowfive@81: table.insert(powerids, k) yellowfive@81: table.insert(powerranks, v) yellowfive@81: end yellowfive@81: end yellowfive@81: if artifactInfo and artifactInfo.Relics then yellowfive@81: for i, link in ipairs(artifactInfo.Relics) do yellowfive@81: local relic = Amr.ParseItemLink(link) yellowfive@81: table.insert(reliclinks, Amr.GetItemUniqueId(relic) or "") yellowfive@81: end yellowfive@57: end yellowfive@57: yellowfive@81: table.insert(fields, toCompressedNumberList(powerids)) yellowfive@81: table.insert(fields, table.concat(powerranks, ",")) yellowfive@81: table.insert(fields, table.concat(reliclinks, ",")) yellowfive@81: yellowfive@81: --table.insert(fields, toCompressedNumberList(data.Glyphs[spec])) yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- export equipped gear yellowfive@57: if data.Equipped then yellowfive@81: for spec = 1, 4 do yellowfive@57: if data.Equipped[spec] and (complete or spec == data.ActiveSpec) then yellowfive@57: table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block yellowfive@57: yellowfive@57: local itemObjects = {} yellowfive@57: for k, v in pairs(data.Equipped[spec]) do yellowfive@57: local itemData = Amr.ParseItemLink(v) yellowfive@57: itemData.slot = k yellowfive@81: itemData.link = v yellowfive@57: table.insert(itemObjects, itemData) yellowfive@57: end yellowfive@57: yellowfive@57: appendItemsToExport(fields, itemObjects) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: -- if doing a complete export, include reputations and bank/bag items too yellowfive@57: if complete then yellowfive@57: yellowfive@57: -- export reputations yellowfive@57: local reps = {} yellowfive@57: local noreps = true yellowfive@57: if data.Reputations then yellowfive@57: for k, v in pairs(data.Reputations) do yellowfive@57: noreps = false yellowfive@57: table.insert(reps, k .. ":" .. v) yellowfive@57: end yellowfive@57: end yellowfive@57: if noreps then yellowfive@57: table.insert(reps, "_") yellowfive@57: end yellowfive@57: yellowfive@57: table.insert(fields, ".r") yellowfive@57: table.insert(fields, table.concat(reps, ",")) yellowfive@57: yellowfive@57: -- export bag and bank yellowfive@57: local itemObjects = {} yellowfive@57: if data.BagItems then yellowfive@57: for i, v in ipairs(data.BagItems) do yellowfive@57: local itemData = Amr.ParseItemLink(v) yellowfive@85: if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then yellowfive@81: itemData.link = v yellowfive@57: table.insert(itemObjects, itemData) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: if data.BankItems then yellowfive@57: for i, v in ipairs(data.BankItems) do yellowfive@57: local itemData = Amr.ParseItemLink(v) yellowfive@85: if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then yellowfive@81: itemData.link = v yellowfive@57: table.insert(itemObjects, itemData) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: if data.VoidItems then yellowfive@57: for i, v in ipairs(data.VoidItems) do yellowfive@57: local itemData = Amr.ParseItemLink(v) yellowfive@85: if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then yellowfive@81: itemData.link = v yellowfive@57: table.insert(itemObjects, itemData) yellowfive@57: end yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: table.insert(fields, ".inv") yellowfive@57: appendItemsToExport(fields, itemObjects) yellowfive@57: end yellowfive@57: yellowfive@57: return "$" .. table.concat(fields, ";") .. "$" yellowfive@57: yellowfive@57: end yellowfive@57: yellowfive@57: -- Shortcut for the common use case: serialize the player's currently active setup with no extras. yellowfive@57: function Amr:SerializePlayer() yellowfive@57: local data = self:GetPlayerData() yellowfive@57: return self:SerializePlayerData(data) yellowfive@57: end yellowfive@57: yellowfive@81: --[[ yellowfive@57: ---------------------------------------------------------------------------------------------------------------------- yellowfive@57: -- Character Snapshots yellowfive@81: -- This feature snapshots a player's gear/talents/artifact when entering combat. It is enabled by default. Consumers yellowfive@57: -- of this library can create a setting to enable/disable it as desired per a user setting. yellowfive@57: -- yellowfive@57: -- You should register for the AMR_SNAPSHOT_STATE_CHANGED message (sent via AceEvent-3.0 messaging) to ensure that yellowfive@57: -- your addon settings stay in sync with any other addon that may also be trying to control the enabled state. yellowfive@57: -- yellowfive@57: -- Note that if a user has the main AMR addon installed, it will always enable snapshotting, and override any attempt yellowfive@57: -- to disable it by immediately re-enabling it and thus re-triggering AMR_SNAPSHOT_STATE_CHANGED. yellowfive@57: ---------------------------------------------------------------------------------------------------------------------- yellowfive@57: Amr._snapshotEnabled = true yellowfive@57: yellowfive@57: -- Enable snapshotting of character data when entering combat. Sends this player's character data to anyone logging with the AskMrRobot addon. yellowfive@57: function Amr:EnableSnapshots() yellowfive@57: self._snapshotEnabled = true yellowfive@57: self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled) yellowfive@57: end yellowfive@57: yellowfive@57: -- Disable snapshotting of character data when entering combat. yellowfive@57: function Amr:DisableSnapshots() yellowfive@57: self._snapshotEnabled = false yellowfive@57: self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled) yellowfive@57: end yellowfive@57: yellowfive@57: function Amr:IsSnapshotEnabled() yellowfive@57: return self._snapshotEnabled yellowfive@57: end yellowfive@57: yellowfive@57: yellowfive@57: function Amr:PLAYER_REGEN_DISABLED() yellowfive@57: --function Amr:GARRISON_MISSION_NPC_OPENED() yellowfive@57: yellowfive@57: -- send data about this character when a player enters combat in a supported zone yellowfive@57: if self._snapshotEnabled and Amr.IsSupportedInstance() then yellowfive@57: local t = time() yellowfive@57: local player = self:GetPlayerData() yellowfive@57: local msg = self:SerializePlayerData(player) yellowfive@57: msg = string.format("%s\r%s\n%s\n%s\n%s\n%s", MINOR, t, player.Region, player.Realm, player.Name, msg) yellowfive@57: yellowfive@57: self:SendCommMessage(Amr.ChatPrefix, msg, "RAID") yellowfive@57: end yellowfive@57: end yellowfive@57: yellowfive@57: Amr:RegisterEvent("PLAYER_REGEN_DISABLED") yellowfive@81: --Amr:RegisterEvent("GARRISON_MISSION_NPC_OPENED") -- for debugging, fire this event when open mission table yellowfive@81: ]]