yellowfive@57
|
1 -- AskMrRobot-Serializer will serialize and communicate character data between users.
|
yellowfive@57
|
2
|
yellowfive@191
|
3 local MAJOR, MINOR = "AskMrRobot-Serializer", 93
|
yellowfive@57
|
4 local Amr, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
|
yellowfive@57
|
5
|
yellowfive@57
|
6 if not Amr then return end -- already loaded by something else
|
yellowfive@57
|
7
|
yellowfive@57
|
8 -- event and comm used for player snapshotting on entering combat
|
yellowfive@57
|
9 LibStub("AceEvent-3.0"):Embed(Amr)
|
yellowfive@57
|
10 LibStub("AceComm-3.0"):Embed(Amr)
|
yellowfive@57
|
11
|
yellowfive@57
|
12 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
13 -- Constants
|
yellowfive@57
|
14 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
15
|
yellowfive@57
|
16 -- prefix used for communicating gear snapshots created by the AMR serializer
|
yellowfive@57
|
17 Amr.ChatPrefix = "_AMRS"
|
yellowfive@57
|
18
|
yellowfive@57
|
19 -- map of region ids to AMR region names
|
yellowfive@57
|
20 Amr.RegionNames = {
|
yellowfive@57
|
21 [1] = "US",
|
yellowfive@57
|
22 [2] = "KR",
|
yellowfive@57
|
23 [3] = "EU",
|
yellowfive@57
|
24 [4] = "TW",
|
yellowfive@57
|
25 [5] = "CN"
|
yellowfive@57
|
26 }
|
yellowfive@57
|
27
|
yellowfive@57
|
28 -- map of the skillLine returned by profession API to the AMR profession name
|
yellowfive@57
|
29 Amr.ProfessionSkillLineToName = {
|
yellowfive@57
|
30 [794] = "Archaeology",
|
yellowfive@57
|
31 [171] = "Alchemy",
|
yellowfive@57
|
32 [164] = "Blacksmithing",
|
yellowfive@57
|
33 [185] = "Cooking",
|
yellowfive@57
|
34 [333] = "Enchanting",
|
yellowfive@57
|
35 [202] = "Engineering",
|
yellowfive@57
|
36 [129] = "First Aid",
|
yellowfive@57
|
37 [356] = "Fishing",
|
yellowfive@57
|
38 [182] = "Herbalism",
|
yellowfive@57
|
39 [773] = "Inscription",
|
yellowfive@57
|
40 [755] = "Jewelcrafting",
|
yellowfive@57
|
41 [165] = "Leatherworking",
|
yellowfive@57
|
42 [186] = "Mining",
|
yellowfive@57
|
43 [393] = "Skinning",
|
yellowfive@57
|
44 [197] = "Tailoring"
|
yellowfive@57
|
45 }
|
yellowfive@57
|
46
|
yellowfive@57
|
47 -- all slot IDs that we care about, ordered in AMR standard display order
|
yellowfive@57
|
48 Amr.SlotIds = { 16, 17, 1, 2, 3, 15, 5, 9, 10, 6, 7, 8, 11, 12, 13, 14 }
|
yellowfive@57
|
49
|
yellowfive@57
|
50 Amr.SpecIds = {
|
yellowfive@57
|
51 [250] = 1, -- DeathKnightBlood
|
yellowfive@57
|
52 [251] = 2, -- DeathKnightFrost
|
yellowfive@57
|
53 [252] = 3, -- DeathKnightUnholy
|
yellowfive@81
|
54 [577] = 4, -- DemonHunterHavoc
|
yellowfive@81
|
55 [581] = 5, -- DemonHunterVengeance
|
yellowfive@81
|
56 [102] = 6, -- DruidBalance
|
yellowfive@81
|
57 [103] = 7, -- DruidFeral
|
yellowfive@81
|
58 [104] = 8, -- DruidGuardian
|
yellowfive@81
|
59 [105] = 9, -- DruidRestoration
|
yellowfive@81
|
60 [253] = 10, -- HunterBeastMastery
|
yellowfive@81
|
61 [254] = 11, -- HunterMarksmanship
|
yellowfive@81
|
62 [255] = 12, -- HunterSurvival
|
yellowfive@81
|
63 [62] = 13, -- MageArcane
|
yellowfive@81
|
64 [63] = 14, -- MageFire
|
yellowfive@81
|
65 [64] = 15, -- MageFrost
|
yellowfive@81
|
66 [268] = 16, -- MonkBrewmaster
|
yellowfive@81
|
67 [270] = 17, -- MonkMistweaver
|
yellowfive@81
|
68 [269] = 18, -- MonkWindwalker
|
yellowfive@81
|
69 [65] = 19, -- PaladinHoly
|
yellowfive@81
|
70 [66] = 20, -- PaladinProtection
|
yellowfive@81
|
71 [70] = 21, -- PaladinRetribution
|
yellowfive@81
|
72 [256] = 22, -- PriestDiscipline
|
yellowfive@81
|
73 [257] = 23, -- PriestHoly
|
yellowfive@81
|
74 [258] = 24, -- PriestShadow
|
yellowfive@81
|
75 [259] = 25, -- RogueAssassination
|
yellowfive@81
|
76 [260] = 26, -- RogueOutlaw
|
yellowfive@81
|
77 [261] = 27, -- RogueSubtlety
|
yellowfive@81
|
78 [262] = 28, -- ShamanElemental
|
yellowfive@81
|
79 [263] = 29, -- ShamanEnhancement
|
yellowfive@81
|
80 [264] = 30, -- ShamanRestoration
|
yellowfive@81
|
81 [265] = 31, -- WarlockAffliction
|
yellowfive@81
|
82 [266] = 32, -- WarlockDemonology
|
yellowfive@81
|
83 [267] = 33, -- WarlockDestruction
|
yellowfive@81
|
84 [71] = 34, -- WarriorArms
|
yellowfive@81
|
85 [72] = 35, -- WarriorFury
|
yellowfive@81
|
86 [73] = 36 -- WarriorProtection
|
yellowfive@57
|
87 }
|
yellowfive@57
|
88
|
yellowfive@57
|
89 Amr.ClassIds = {
|
yellowfive@57
|
90 ["NONE"] = 0,
|
yellowfive@57
|
91 ["DEATHKNIGHT"] = 1,
|
yellowfive@81
|
92 ["DEMONHUNTER"] = 2,
|
yellowfive@81
|
93 ["DRUID"] = 3,
|
yellowfive@81
|
94 ["HUNTER"] = 4,
|
yellowfive@81
|
95 ["MAGE"] = 5,
|
yellowfive@81
|
96 ["MONK"] = 6,
|
yellowfive@81
|
97 ["PALADIN"] = 7,
|
yellowfive@81
|
98 ["PRIEST"] = 8,
|
yellowfive@81
|
99 ["ROGUE"] = 9,
|
yellowfive@81
|
100 ["SHAMAN"] = 10,
|
yellowfive@81
|
101 ["WARLOCK"] = 11,
|
yellowfive@81
|
102 ["WARRIOR"] = 12,
|
yellowfive@57
|
103 }
|
yellowfive@57
|
104
|
yellowfive@57
|
105 Amr.ProfessionIds = {
|
yellowfive@57
|
106 ["None"] = 0,
|
yellowfive@57
|
107 ["Mining"] = 1,
|
yellowfive@57
|
108 ["Skinning"] = 2,
|
yellowfive@57
|
109 ["Herbalism"] = 3,
|
yellowfive@57
|
110 ["Enchanting"] = 4,
|
yellowfive@57
|
111 ["Jewelcrafting"] = 5,
|
yellowfive@57
|
112 ["Engineering"] = 6,
|
yellowfive@57
|
113 ["Blacksmithing"] = 7,
|
yellowfive@57
|
114 ["Leatherworking"] = 8,
|
yellowfive@57
|
115 ["Inscription"] = 9,
|
yellowfive@57
|
116 ["Tailoring"] = 10,
|
yellowfive@57
|
117 ["Alchemy"] = 11,
|
yellowfive@57
|
118 ["Fishing"] = 12,
|
yellowfive@57
|
119 ["Cooking"] = 13,
|
yellowfive@57
|
120 ["First Aid"] = 14,
|
yellowfive@57
|
121 ["Archaeology"] = 15
|
yellowfive@57
|
122 }
|
yellowfive@57
|
123
|
yellowfive@57
|
124 Amr.RaceIds = {
|
yellowfive@57
|
125 ["None"] = 0,
|
yellowfive@57
|
126 ["BloodElf"] = 1,
|
yellowfive@57
|
127 ["Draenei"] = 2,
|
yellowfive@57
|
128 ["Dwarf"] = 3,
|
yellowfive@57
|
129 ["Gnome"] = 4,
|
yellowfive@57
|
130 ["Human"] = 5,
|
yellowfive@57
|
131 ["NightElf"] = 6,
|
yellowfive@57
|
132 ["Orc"] = 7,
|
yellowfive@57
|
133 ["Tauren"] = 8,
|
yellowfive@57
|
134 ["Troll"] = 9,
|
yellowfive@57
|
135 ["Scourge"] = 10,
|
yellowfive@57
|
136 ["Undead"] = 10,
|
yellowfive@57
|
137 ["Goblin"] = 11,
|
yellowfive@57
|
138 ["Worgen"] = 12,
|
yellowfive@120
|
139 ["Pandaren"] = 13,
|
yellowfive@120
|
140 ["Nightborne"] = 14,
|
yellowfive@120
|
141 ["HighmountainTauren"] = 15,
|
yellowfive@120
|
142 ["VoidElf"] = 16,
|
yellowfive@135
|
143 ["LightforgedDraenei"] = 17,
|
yellowfive@135
|
144 ["DarkIronDwarf"] = 18,
|
yellowfive@155
|
145 ["MagharOrc"] = 19,
|
yellowfive@155
|
146 ["ZandalariTroll"] = 20,
|
yellowfive@173
|
147 ["KulTiran"] = 21,
|
yellowfive@173
|
148 ["Vulpera"] = 22,
|
yellowfive@173
|
149 ["Mechagnome"] = 23
|
yellowfive@57
|
150 }
|
yellowfive@57
|
151
|
yellowfive@57
|
152 Amr.FactionIds = {
|
yellowfive@57
|
153 ["None"] = 0,
|
yellowfive@57
|
154 ["Alliance"] = 1,
|
yellowfive@57
|
155 ["Horde"] = 2
|
yellowfive@57
|
156 }
|
yellowfive@57
|
157
|
yellowfive@57
|
158 Amr.InstanceIds = {
|
yellowfive@189
|
159 Uldir = 1861,
|
yellowfive@189
|
160 Dazar = 2070,
|
yellowfive@189
|
161 Storms = 2096,
|
yellowfive@189
|
162 Palace = 2164,
|
yellowfive@189
|
163 Nyalotha = 2217,
|
yellowfive@185
|
164 Nathria = 2296
|
yellowfive@57
|
165 }
|
yellowfive@57
|
166
|
yellowfive@57
|
167 -- instances that AskMrRobot currently supports logging for
|
yellowfive@57
|
168 Amr.SupportedInstanceIds = {
|
yellowfive@189
|
169 [1861] = true,
|
yellowfive@189
|
170 [2070] = true,
|
yellowfive@189
|
171 [2096] = true,
|
yellowfive@189
|
172 [2164] = true,
|
yellowfive@189
|
173 [2217] = true,
|
yellowfive@185
|
174 [2296] = true
|
yellowfive@57
|
175 }
|
yellowfive@57
|
176
|
yellowfive@57
|
177
|
yellowfive@57
|
178 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
179 -- Public Utility Methods
|
yellowfive@57
|
180 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
181
|
yellowfive@81
|
182 local function readBonusIdList(parts, first, last)
|
yellowfive@124
|
183 local ret = {}
|
yellowfive@81
|
184 for i = first, last do
|
yellowfive@81
|
185 table.insert(ret, tonumber(parts[i]))
|
yellowfive@81
|
186 end
|
yellowfive@81
|
187 table.sort(ret)
|
yellowfive@81
|
188 return ret
|
yellowfive@81
|
189 end
|
yellowfive@81
|
190
|
yellowfive@124
|
191 -- 1 2 3 4 5 6 7 8 9 10 11 12
|
yellowfive@124
|
192 -- itemId:ench:gem1 :gem2 :gem3 :gem4:suf:uid:lvl:spec:flags :instdiffid:numbonusIDs:bonusIDs1...n :varies:?:relic bonus ids
|
yellowfive@124
|
193 --|cffe6cc80|Hitem:128866: :152046:147100:152025: : : :110:66 :16777472:9 :4 :736:1494:1490:1495:709 :1:3:3610:1472:3528:3:3562:1483:3528:3:3610:1477:3336|h[Truthguard]|h|r
|
yellowfive@124
|
194 --
|
yellowfive@57
|
195 -- get an object with all of the parts of the item link format that we care about
|
yellowfive@57
|
196 function Amr.ParseItemLink(itemLink)
|
yellowfive@57
|
197 if not itemLink then return nil end
|
yellowfive@57
|
198
|
yellowfive@57
|
199 local str = string.match(itemLink, "|Hitem:([\-%d:]+)|")
|
yellowfive@57
|
200 if not str then return nil end
|
yellowfive@57
|
201
|
yellowfive@57
|
202 local parts = { strsplit(":", str) }
|
yellowfive@57
|
203
|
yellowfive@124
|
204 local item = {}
|
yellowfive@124
|
205 item.link = itemLink
|
yellowfive@81
|
206 item.id = tonumber(parts[1]) or 0
|
yellowfive@81
|
207 item.enchantId = tonumber(parts[2]) or 0
|
yellowfive@81
|
208 item.gemIds = { tonumber(parts[3]) or 0, tonumber(parts[4]) or 0, tonumber(parts[5]) or 0, tonumber(parts[6]) or 0 }
|
yellowfive@81
|
209 item.suffixId = math.abs(tonumber(parts[7]) or 0) -- convert suffix to positive number, that's what we use in our code
|
yellowfive@81
|
210 -- part 8 is some unique ID... we never really used it
|
yellowfive@81
|
211 -- part 9 is current player level
|
yellowfive@81
|
212 -- part 10 is player spec
|
yellowfive@185
|
213 -- unsure what 11 is now --local upgradeIdType = tonumber(parts[11]) or 0 -- part 11 indicates what kind of upgrade ID is just after the bonus IDs
|
yellowfive@81
|
214 -- part 12 is instance difficulty id
|
yellowfive@185
|
215
|
yellowfive@185
|
216 -- 13 is num bonus IDs, followed by bonus IDs
|
yellowfive@81
|
217 local numBonuses = tonumber(parts[13]) or 0
|
yellowfive@81
|
218 local offset = numBonuses
|
yellowfive@81
|
219 if numBonuses > 0 then
|
yellowfive@81
|
220 item.bonusIds = readBonusIdList(parts, 14, 13 + numBonuses)
|
yellowfive@57
|
221 end
|
yellowfive@69
|
222
|
yellowfive@81
|
223 item.upgradeId = 0
|
yellowfive@81
|
224 item.level = 0
|
yellowfive@185
|
225
|
yellowfive@185
|
226 -- part 14 + numBonuses, unsure what this is... sometimes it is "2"
|
yellowfive@185
|
227 -- part 15 + numBonuses, unsure what this is... may indicate what part 16 will mean?
|
yellowfive@185
|
228 -- part 16 + numBonuses, is player level at drop when applicable
|
yellowfive@185
|
229 -- part 17 + numBonuses, unsure what this is...
|
yellowfive@185
|
230 -- part 18 + numBonuses, unsure what this is...
|
yellowfive@185
|
231 -- part 19 + numBonuses, relic info would be here for legion artifacts
|
yellowfive@185
|
232
|
yellowfive@185
|
233 local someNumber = tonumber(parts[15 + offset]) or 0
|
yellowfive@185
|
234 if someNumber ~= 0 then
|
yellowfive@185
|
235 local lvl = tonumber(parts[16 + offset]) or 0
|
yellowfive@185
|
236 if lvl <= 60 then
|
yellowfive@185
|
237 item.level = lvl
|
yellowfive@185
|
238 end
|
yellowfive@185
|
239 end
|
yellowfive@185
|
240
|
yellowfive@185
|
241 -- we don't need relic information anymore
|
yellowfive@185
|
242 --[[elseif #parts > 19 + offset then
|
yellowfive@124
|
243 -- check for relic info
|
yellowfive@124
|
244 item.relicBonusIds = { nil, nil, nil }
|
yellowfive@124
|
245 numBonuses = tonumber(parts[16 + offset])
|
yellowfive@124
|
246 if numBonuses then
|
yellowfive@124
|
247 if numBonuses > 0 then
|
yellowfive@124
|
248 item.relicBonusIds[1] = readBonusIdList(parts, 17 + offset, 16 + offset + numBonuses)
|
yellowfive@124
|
249 end
|
yellowfive@124
|
250
|
yellowfive@129
|
251 offset = offset + numBonuses
|
yellowfive@124
|
252 if #parts > 17 + offset then
|
yellowfive@124
|
253 numBonuses = tonumber(parts[17 + offset])
|
yellowfive@129
|
254 if numBonuses then
|
yellowfive@129
|
255 if numBonuses > 0 then
|
yellowfive@129
|
256 item.relicBonusIds[2] = readBonusIdList(parts, 18 + offset, 17 + offset + numBonuses)
|
yellowfive@129
|
257 end
|
yellowfive@129
|
258
|
yellowfive@129
|
259 offset= offset + numBonuses
|
yellowfive@129
|
260 if #parts > 18 + offset then
|
yellowfive@129
|
261 numBonuses = tonumber(parts[18 + offset])
|
yellowfive@129
|
262 if numBonuses then
|
yellowfive@129
|
263 if numBonuses > 0 then
|
yellowfive@129
|
264 item.relicBonusIds[3] = readBonusIdList(parts, 19 + offset, 18 + offset + numBonuses)
|
yellowfive@129
|
265 end
|
yellowfive@129
|
266 end
|
yellowfive@129
|
267 end
|
yellowfive@124
|
268 end
|
yellowfive@124
|
269 end
|
yellowfive@124
|
270 end
|
yellowfive@185
|
271 end]]
|
yellowfive@81
|
272
|
yellowfive@57
|
273 return item
|
yellowfive@57
|
274 end
|
yellowfive@57
|
275
|
yellowfive@135
|
276 local AZERITE_EMPOWERED_BONUS_ID = 4775
|
yellowfive@135
|
277
|
yellowfive@135
|
278 function Amr.GetItemUniqueId(item, noUpgrade, noAzeriteEmpoweredBonusId)
|
yellowfive@81
|
279 if not item then return "" end
|
yellowfive@81
|
280 local ret = item.id .. ""
|
yellowfive@81
|
281 if item.bonusIds then
|
yellowfive@135
|
282 for i = 1, #item.bonusIds do
|
yellowfive@135
|
283 if not noAzeriteEmpoweredBonusId or item.bonusIds[i] ~= AZERITE_EMPOWERED_BONUS_ID then
|
yellowfive@135
|
284 ret = ret .. "b" .. item.bonusIds[i]
|
yellowfive@135
|
285 end
|
yellowfive@81
|
286 end
|
yellowfive@81
|
287 end
|
yellowfive@81
|
288 if item.suffixId ~= 0 then
|
yellowfive@81
|
289 ret = ret .. "s" .. item.suffixId
|
yellowfive@81
|
290 end
|
yellowfive@81
|
291 if not noUpgrade and item.upgradeId ~= 0 then
|
yellowfive@81
|
292 ret = ret .. "u" .. item.upgradeId
|
yellowfive@81
|
293 end
|
yellowfive@81
|
294 if item.level ~= 0 then
|
yellowfive@81
|
295 ret = ret .. "v" .. item.level
|
yellowfive@81
|
296 end
|
yellowfive@81
|
297 return ret
|
yellowfive@81
|
298 end
|
yellowfive@81
|
299
|
yellowfive@57
|
300 -- returns true if this is an instance that AskMrRobot supports for logging
|
yellowfive@57
|
301 function Amr.IsSupportedInstanceId(instanceMapID)
|
yellowfive@57
|
302 if Amr.SupportedInstanceIds[tonumber(instanceMapID)] then
|
yellowfive@57
|
303 return true
|
yellowfive@57
|
304 else
|
yellowfive@57
|
305 return false
|
yellowfive@57
|
306 end
|
yellowfive@57
|
307 end
|
yellowfive@57
|
308
|
yellowfive@57
|
309 -- returns true if currently in a supported instance for logging
|
yellowfive@57
|
310 function Amr.IsSupportedInstance()
|
yellowfive@133
|
311 local _, _, _, _, _, _, _, instanceMapID = GetInstanceInfo()
|
yellowfive@57
|
312 return Amr.IsSupportedInstanceId(instanceMapID)
|
yellowfive@57
|
313 end
|
yellowfive@57
|
314
|
yellowfive@133
|
315 --[[
|
yellowfive@81
|
316 -- scanning tooltip b/c for some odd reason the api has no way to get basic item properties...
|
yellowfive@81
|
317 -- so you have to generate a fake item tooltip and search for pre-defined strings in the display text
|
yellowfive@81
|
318 local _scanTt
|
yellowfive@81
|
319 function Amr.GetScanningTooltip()
|
yellowfive@81
|
320 if not _scanTt then
|
yellowfive@81
|
321 _scanTt = CreateFrame("GameTooltip", "AmrUiScanTooltip", nil, "GameTooltipTemplate")
|
yellowfive@81
|
322 _scanTt:SetOwner(UIParent, "ANCHOR_NONE")
|
yellowfive@81
|
323 end
|
yellowfive@81
|
324 return _scanTt
|
yellowfive@81
|
325 end
|
yellowfive@81
|
326
|
yellowfive@81
|
327 -- 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
|
328 function Amr.GetItemTooltip(bagId, slotId, link)
|
yellowfive@81
|
329 local tt = Amr.GetScanningTooltip()
|
yellowfive@81
|
330 tt:ClearLines()
|
yellowfive@81
|
331 if bagId then
|
yellowfive@81
|
332 tt:SetBagItem(bagId, slotId)
|
yellowfive@81
|
333 elseif slotId then
|
yellowfive@81
|
334 tt:SetInventoryItem("player", slotId)
|
yellowfive@81
|
335 else
|
yellowfive@81
|
336 tt:SetHyperlink(link)
|
yellowfive@81
|
337 end
|
yellowfive@81
|
338 return tt
|
yellowfive@81
|
339 end
|
yellowfive@133
|
340 ]]
|
yellowfive@81
|
341
|
yellowfive@133
|
342 --[[
|
yellowfive@124
|
343 function Amr.GetItemLevel(bagId, slotId, link)
|
yellowfive@81
|
344 local itemLevelPattern = _G["ITEM_LEVEL"]:gsub("%%d", "(%%d+)")
|
yellowfive@81
|
345 local tt = Amr.GetItemTooltip(bagId, slotId, link)
|
yellowfive@81
|
346
|
yellowfive@81
|
347 local regions = { tt:GetRegions() }
|
yellowfive@81
|
348 for i, region in ipairs(regions) do
|
yellowfive@81
|
349 if region and region:GetObjectType() == "FontString" then
|
yellowfive@81
|
350 local text = region:GetText()
|
yellowfive@81
|
351 if text then
|
yellowfive@81
|
352 ilvl = tonumber(text:match(itemLevelPattern))
|
yellowfive@81
|
353 if ilvl then
|
yellowfive@81
|
354 return ilvl
|
yellowfive@81
|
355 end
|
yellowfive@81
|
356 end
|
yellowfive@81
|
357 end
|
yellowfive@81
|
358 end
|
yellowfive@81
|
359
|
yellowfive@81
|
360 -- 0 means we couldn't find it for whatever reason
|
yellowfive@81
|
361 return 0
|
yellowfive@81
|
362 end
|
yellowfive@133
|
363 ]]
|
yellowfive@81
|
364
|
yellowfive@57
|
365
|
yellowfive@57
|
366 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
367 -- Character Reading
|
yellowfive@57
|
368 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
369
|
yellowfive@57
|
370 local function readProfessionInfo(prof, ret)
|
yellowfive@57
|
371 if prof then
|
yellowfive@133
|
372 local _, _, skillLevel, _, _, _, skillLine = GetProfessionInfo(prof);
|
yellowfive@57
|
373 if Amr.ProfessionSkillLineToName[skillLine] ~= nil then
|
yellowfive@57
|
374 ret.Professions[Amr.ProfessionSkillLineToName[skillLine]] = skillLevel;
|
yellowfive@57
|
375 end
|
yellowfive@57
|
376 end
|
yellowfive@57
|
377 end
|
yellowfive@57
|
378
|
yellowfive@124
|
379 -- get specs
|
yellowfive@81
|
380 local function readSpecs(ret)
|
yellowfive@57
|
381
|
yellowfive@81
|
382 for pos = 1, 4 do
|
yellowfive@57
|
383 -- spec, convert game spec id to one of our spec ids
|
yellowfive@81
|
384 local specId = GetSpecializationInfo(pos)
|
yellowfive@57
|
385 if specId then
|
yellowfive@81
|
386 ret.Specs[pos] = Amr.SpecIds[specId]
|
yellowfive@57
|
387 end
|
yellowfive@57
|
388 end
|
yellowfive@57
|
389 end
|
yellowfive@57
|
390
|
yellowfive@124
|
391 local function dump(o)
|
yellowfive@124
|
392 if type(o) == 'table' then
|
yellowfive@124
|
393 local s = '{ '
|
yellowfive@124
|
394 for k,v in pairs(o) do
|
yellowfive@124
|
395 if type(k) ~= 'number' then k = '"'..k..'"' end
|
yellowfive@124
|
396 s = s .. '['..k..'] = ' .. dump(v) .. ','
|
yellowfive@124
|
397 end
|
yellowfive@124
|
398 return s .. '} '
|
yellowfive@124
|
399 else
|
yellowfive@124
|
400 return tostring(o)
|
yellowfive@124
|
401 end
|
yellowfive@124
|
402 end
|
yellowfive@124
|
403
|
yellowfive@185
|
404 --[[
|
yellowfive@124
|
405 -- read azerite powers on the item in loc and put it on itemData
|
yellowfive@124
|
406 function Amr.ReadAzeritePowers(loc)
|
yellowfive@124
|
407 local ret = {}
|
yellowfive@124
|
408 local hasSome = false
|
yellowfive@124
|
409
|
yellowfive@124
|
410 local tiers = C_AzeriteEmpoweredItem.GetAllTierInfo(loc)
|
yellowfive@124
|
411 for tier, tierInfo in ipairs(tiers) do
|
yellowfive@124
|
412 for _, power in ipairs(tierInfo.azeritePowerIDs) do
|
yellowfive@124
|
413 if C_AzeriteEmpoweredItem.IsPowerSelected(loc, power) then
|
yellowfive@124
|
414 local powerInfo = C_AzeriteEmpoweredItem.GetPowerInfo(power)
|
yellowfive@124
|
415 table.insert(ret, powerInfo.spellID)
|
yellowfive@124
|
416 hasSome = true
|
yellowfive@124
|
417 end
|
yellowfive@124
|
418 end
|
yellowfive@124
|
419 end
|
yellowfive@124
|
420
|
yellowfive@124
|
421 if hasSome then
|
yellowfive@124
|
422 return ret
|
yellowfive@124
|
423 else
|
yellowfive@124
|
424 return nil
|
yellowfive@124
|
425 end
|
yellowfive@124
|
426 end
|
yellowfive@185
|
427 ]]
|
yellowfive@124
|
428
|
yellowfive@57
|
429 -- get currently equipped items, store with currently active spec
|
yellowfive@57
|
430 local function readEquippedItems(ret)
|
yellowfive@124
|
431 local equippedItems = {};
|
yellowfive@191
|
432 --local loc = ItemLocation.CreateEmpty()
|
yellowfive@191
|
433 local item
|
yellowfive@57
|
434 for slotNum = 1, #Amr.SlotIds do
|
yellowfive@57
|
435 local slotId = Amr.SlotIds[slotNum]
|
yellowfive@57
|
436 local itemLink = GetInventoryItemLink("player", slotId)
|
yellowfive@57
|
437 if itemLink then
|
yellowfive@124
|
438 local itemData = Amr.ParseItemLink(itemLink)
|
yellowfive@124
|
439 if itemData then
|
yellowfive@191
|
440 item = Item:CreateFromEquipmentSlot(slotId)
|
yellowfive@191
|
441
|
yellowfive@191
|
442 -- seems to be of the form Item-1147-0-4000000XXXXXXXXX, so we take just the last 9 digits
|
yellowfive@191
|
443 itemData.guid = item:GetItemGUID()
|
yellowfive@191
|
444 if itemData.guid and strlen(itemData.guid) > 9 then
|
yellowfive@191
|
445 itemData.guid = strsub(itemData.guid, -9)
|
yellowfive@191
|
446 end
|
yellowfive@191
|
447
|
yellowfive@185
|
448 --[[
|
yellowfive@124
|
449 -- see if this is an azerite item and read azerite power ids
|
yellowfive@124
|
450 loc:SetEquipmentSlot(slotId)
|
yellowfive@124
|
451 if C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItem(loc) then
|
yellowfive@124
|
452 local powers = Amr.ReadAzeritePowers(loc)
|
yellowfive@124
|
453 if powers then
|
yellowfive@124
|
454 itemData.azerite = powers
|
yellowfive@124
|
455 end
|
yellowfive@124
|
456 end
|
yellowfive@185
|
457 ]]
|
yellowfive@124
|
458
|
yellowfive@124
|
459 equippedItems[slotId] = itemData
|
yellowfive@124
|
460 end
|
yellowfive@57
|
461 end
|
yellowfive@57
|
462 end
|
yellowfive@57
|
463
|
yellowfive@57
|
464 -- store last-seen equipped gear for each spec
|
yellowfive@81
|
465 ret.Equipped[GetSpecialization()] = equippedItems
|
yellowfive@57
|
466 end
|
yellowfive@57
|
467
|
yellowfive@185
|
468 --[[
|
yellowfive@124
|
469 local function readHeartOfAzerothLevel(ret)
|
yellowfive@124
|
470 local azeriteItemLocation = C_AzeriteItem.FindActiveAzeriteItem();
|
yellowfive@124
|
471 if azeriteItemLocation then
|
yellowfive@124
|
472 local azeriteItem = Item:CreateFromItemLocation(azeriteItemLocation);
|
yellowfive@124
|
473 ret.HeartOfAzerothLevel = C_AzeriteItem.GetPowerLevel(azeriteItemLocation)
|
yellowfive@124
|
474 else
|
yellowfive@124
|
475 ret.HeartOfAzerothLevel = 0
|
yellowfive@124
|
476 end
|
yellowfive@124
|
477 end
|
yellowfive@185
|
478 ]]
|
yellowfive@124
|
479
|
yellowfive@124
|
480 -- Get just the player's currently equipped gear
|
yellowfive@124
|
481 function Amr:GetEquipped()
|
yellowfive@124
|
482 local ret= {}
|
yellowfive@124
|
483 ret.Equipped = {}
|
yellowfive@124
|
484 readEquippedItems(ret)
|
yellowfive@124
|
485 return ret
|
yellowfive@124
|
486 end
|
yellowfive@124
|
487
|
yellowfive@57
|
488 -- Get all data about the player as an object, includes:
|
yellowfive@57
|
489 -- serializer version
|
yellowfive@57
|
490 -- region/realm/name
|
yellowfive@57
|
491 -- guild
|
yellowfive@57
|
492 -- race
|
yellowfive@57
|
493 -- faction
|
yellowfive@57
|
494 -- level
|
yellowfive@57
|
495 -- professions
|
yellowfive@81
|
496 -- spec/talent for all specs
|
yellowfive@57
|
497 -- equipped gear for the current spec
|
yellowfive@57
|
498 --
|
yellowfive@81
|
499 function Amr:GetPlayerData()
|
yellowfive@57
|
500
|
yellowfive@57
|
501 local ret = {}
|
yellowfive@57
|
502
|
yellowfive@57
|
503 ret.Region = Amr.RegionNames[GetCurrentRegion()]
|
yellowfive@57
|
504 ret.Realm = GetRealmName()
|
yellowfive@57
|
505 ret.Name = UnitName("player")
|
yellowfive@57
|
506 ret.Guild = GetGuildInfo("player")
|
yellowfive@81
|
507 ret.ActiveSpec = GetSpecialization()
|
yellowfive@57
|
508 ret.Level = UnitLevel("player");
|
yellowfive@185
|
509 --readHeartOfAzerothLevel(ret)
|
yellowfive@124
|
510
|
yellowfive@133
|
511 local _, clsEn = UnitClass("player")
|
yellowfive@57
|
512 ret.Class = clsEn;
|
yellowfive@57
|
513
|
yellowfive@133
|
514 local _, raceEn = UnitRace("player")
|
yellowfive@57
|
515 ret.Race = raceEn;
|
yellowfive@57
|
516 ret.Faction = UnitFactionGroup("player")
|
yellowfive@57
|
517
|
yellowfive@57
|
518 ret.Professions = {};
|
yellowfive@57
|
519 local prof1, prof2, archaeology, fishing, cooking, firstAid = GetProfessions();
|
yellowfive@57
|
520 readProfessionInfo(prof1, ret)
|
yellowfive@57
|
521 readProfessionInfo(prof2, ret)
|
yellowfive@57
|
522 readProfessionInfo(archaeology, ret)
|
yellowfive@57
|
523 readProfessionInfo(fishing, ret)
|
yellowfive@57
|
524 readProfessionInfo(cooking, ret)
|
yellowfive@57
|
525 readProfessionInfo(firstAid, ret)
|
yellowfive@57
|
526
|
yellowfive@57
|
527 ret.Specs = {}
|
yellowfive@57
|
528 ret.Talents = {}
|
yellowfive@81
|
529 readSpecs(ret)
|
yellowfive@165
|
530
|
yellowfive@165
|
531 -- these get updated later, since need to cache info for inactive specs
|
yellowfive@185
|
532 --ret.UnlockedEssences = {}
|
yellowfive@185
|
533 --ret.Essences = {}
|
yellowfive@81
|
534
|
yellowfive@124
|
535 ret.Equipped = {}
|
yellowfive@57
|
536 readEquippedItems(ret)
|
yellowfive@57
|
537
|
yellowfive@57
|
538 return ret
|
yellowfive@57
|
539 end
|
yellowfive@57
|
540
|
yellowfive@57
|
541
|
yellowfive@57
|
542 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
543 -- Serialization
|
yellowfive@57
|
544 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
545
|
yellowfive@57
|
546 local function toCompressedNumberList(list)
|
yellowfive@57
|
547 -- ensure the values are numbers, sorted from lowest to highest
|
yellowfive@57
|
548 local nums = {}
|
yellowfive@57
|
549 for i, v in ipairs(list) do
|
yellowfive@57
|
550 table.insert(nums, tonumber(v))
|
yellowfive@57
|
551 end
|
yellowfive@57
|
552 table.sort(nums)
|
yellowfive@57
|
553
|
yellowfive@57
|
554 local ret = {}
|
yellowfive@57
|
555 local prev = 0
|
yellowfive@57
|
556 for i, v in ipairs(nums) do
|
yellowfive@57
|
557 local diff = v - prev
|
yellowfive@57
|
558 table.insert(ret, diff)
|
yellowfive@57
|
559 prev = v
|
yellowfive@57
|
560 end
|
yellowfive@57
|
561
|
yellowfive@57
|
562 return table.concat(ret, ",")
|
yellowfive@57
|
563 end
|
yellowfive@57
|
564
|
yellowfive@57
|
565 -- make this utility publicly available
|
yellowfive@57
|
566 function Amr:ToCompressedNumberList(list)
|
yellowfive@57
|
567 return toCompressedNumberList(list)
|
yellowfive@57
|
568 end
|
yellowfive@57
|
569
|
yellowfive@57
|
570 -- appends a list of items to the export
|
yellowfive@57
|
571 local function appendItemsToExport(fields, itemObjects)
|
yellowfive@57
|
572
|
yellowfive@57
|
573 -- sort by item id so we can compress it more easily
|
yellowfive@57
|
574 table.sort(itemObjects, function(a, b) return a.id < b.id end)
|
yellowfive@57
|
575
|
yellowfive@57
|
576 -- append to the export string
|
yellowfive@57
|
577 local prevItemId = 0
|
yellowfive@57
|
578 local prevGemId = 0
|
yellowfive@57
|
579 local prevEnchantId = 0
|
yellowfive@57
|
580 local prevUpgradeId = 0
|
yellowfive@57
|
581 local prevBonusId = 0
|
yellowfive@81
|
582 local prevLevel = 0
|
yellowfive@185
|
583 --local prevAzeriteId = 0
|
yellowfive@124
|
584 local prevRelicBonusId = 0
|
yellowfive@191
|
585
|
yellowfive@57
|
586 for i, itemData in ipairs(itemObjects) do
|
yellowfive@57
|
587 local itemParts = {}
|
yellowfive@57
|
588
|
yellowfive@57
|
589 table.insert(itemParts, itemData.id - prevItemId)
|
yellowfive@57
|
590 prevItemId = itemData.id
|
yellowfive@57
|
591
|
yellowfive@57
|
592 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end
|
yellowfive@124
|
593 --if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end
|
yellowfive@57
|
594 if itemData.upgradeId ~= 0 then
|
yellowfive@57
|
595 table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId))
|
yellowfive@57
|
596 prevUpgradeId = itemData.upgradeId
|
yellowfive@57
|
597 end
|
yellowfive@81
|
598 if itemData.level ~= 0 then
|
yellowfive@81
|
599 table.insert(itemParts, "v" .. (itemData.level - prevLevel))
|
yellowfive@81
|
600 prevLevel = itemData.level
|
yellowfive@81
|
601 end
|
yellowfive@57
|
602 if itemData.bonusIds then
|
yellowfive@57
|
603 for bIndex, bValue in ipairs(itemData.bonusIds) do
|
yellowfive@57
|
604 table.insert(itemParts, "b" .. (bValue - prevBonusId))
|
yellowfive@57
|
605 prevBonusId = bValue
|
yellowfive@57
|
606 end
|
yellowfive@124
|
607 end
|
yellowfive@124
|
608
|
yellowfive@185
|
609 --[[
|
yellowfive@124
|
610 if itemData.azerite then
|
yellowfive@124
|
611 for aIndex, aValue in ipairs(itemData.azerite) do
|
yellowfive@124
|
612 table.insert(itemParts, "a" .. (aValue - prevAzeriteId))
|
yellowfive@124
|
613 prevAzeriteId = aValue
|
yellowfive@124
|
614 end
|
yellowfive@124
|
615 end
|
yellowfive@185
|
616 ]]
|
yellowfive@185
|
617
|
yellowfive@81
|
618 if itemData.gemIds[1] ~= 0 then
|
yellowfive@81
|
619 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId))
|
yellowfive@81
|
620 prevGemId = itemData.gemIds[1]
|
yellowfive@81
|
621 end
|
yellowfive@81
|
622 if itemData.gemIds[2] ~= 0 then
|
yellowfive@81
|
623 table.insert(itemParts, "y" .. (itemData.gemIds[2] - prevGemId))
|
yellowfive@81
|
624 prevGemId = itemData.gemIds[2]
|
yellowfive@81
|
625 end
|
yellowfive@81
|
626 if itemData.gemIds[3] ~= 0 then
|
yellowfive@81
|
627 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId))
|
yellowfive@81
|
628 prevGemId = itemData.gemIds[3]
|
yellowfive@124
|
629 end
|
yellowfive@81
|
630
|
yellowfive@57
|
631 if itemData.enchantId ~= 0 then
|
yellowfive@57
|
632 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId))
|
yellowfive@57
|
633 prevEnchantId = itemData.enchantId
|
yellowfive@57
|
634 end
|
yellowfive@124
|
635
|
yellowfive@124
|
636 if itemData.relicBonusIds and itemData.relicBonusIds[1] ~= nil then
|
yellowfive@124
|
637 for bIndex, bValue in ipairs(itemData.relicBonusIds[1]) do
|
yellowfive@124
|
638 table.insert(itemParts, "p" .. (bValue - prevRelicBonusId))
|
yellowfive@124
|
639 prevRelicBonusId = bValue
|
yellowfive@124
|
640 end
|
yellowfive@124
|
641 end
|
yellowfive@124
|
642
|
yellowfive@124
|
643 if itemData.relicBonusIds and itemData.relicBonusIds[2] ~= nil then
|
yellowfive@124
|
644 for bIndex, bValue in ipairs(itemData.relicBonusIds[2]) do
|
yellowfive@124
|
645 table.insert(itemParts, "q" .. (bValue - prevRelicBonusId))
|
yellowfive@124
|
646 prevRelicBonusId = bValue
|
yellowfive@124
|
647 end
|
yellowfive@124
|
648 end
|
yellowfive@124
|
649
|
yellowfive@124
|
650 if itemData.relicBonusIds and itemData.relicBonusIds[3] ~= nil then
|
yellowfive@124
|
651 for bIndex, bValue in ipairs(itemData.relicBonusIds[3]) do
|
yellowfive@124
|
652 table.insert(itemParts, "r" .. (bValue - prevRelicBonusId))
|
yellowfive@124
|
653 prevRelicBonusId = bValue
|
yellowfive@124
|
654 end
|
yellowfive@124
|
655 end
|
yellowfive@191
|
656
|
yellowfive@191
|
657 if itemData.guid then
|
yellowfive@191
|
658 table.insert(itemParts, "!" .. itemData.guid)
|
yellowfive@191
|
659 end
|
yellowfive@124
|
660
|
yellowfive@57
|
661 table.insert(fields, table.concat(itemParts, ""))
|
yellowfive@57
|
662 end
|
yellowfive@57
|
663 end
|
yellowfive@57
|
664
|
yellowfive@57
|
665 -- Serialize just the identity portion of a player (region/realm/name) in the same format used by the full serialization
|
yellowfive@57
|
666 function Amr:SerializePlayerIdentity(data)
|
yellowfive@57
|
667 local fields = {}
|
yellowfive@57
|
668 table.insert(fields, MINOR)
|
yellowfive@57
|
669 table.insert(fields, data.Region)
|
yellowfive@57
|
670 table.insert(fields, data.Realm)
|
yellowfive@57
|
671 table.insert(fields, data.Name)
|
yellowfive@57
|
672 return "$" .. table.concat(fields, ";") .. "$"
|
yellowfive@57
|
673 end
|
yellowfive@57
|
674
|
yellowfive@57
|
675 -- Serialize player data gathered by GetPlayerData. This can be augmented with extra data if desired (augmenting used mainly by AskMrRobot addon).
|
yellowfive@57
|
676 -- Pass complete = true to do a complete export of this extra information, otherwise it is ignored.
|
yellowfive@57
|
677 -- Extra data can include:
|
yellowfive@57
|
678 -- equipped gear for the player's inactive spec, slot id to item link dictionary
|
yellowfive@57
|
679 -- Reputations
|
yellowfive@57
|
680 -- BagItems, BankItems, VoidItems, lists of item links
|
yellowfive@57
|
681 --
|
yellowfive@57
|
682 function Amr:SerializePlayerData(data, complete)
|
yellowfive@57
|
683
|
yellowfive@57
|
684 local fields = {}
|
yellowfive@57
|
685
|
yellowfive@57
|
686 -- compressed string uses a fixed order rather than inserting identifiers
|
yellowfive@57
|
687 table.insert(fields, MINOR)
|
yellowfive@57
|
688 table.insert(fields, data.Region)
|
yellowfive@57
|
689 table.insert(fields, data.Realm)
|
yellowfive@57
|
690 table.insert(fields, data.Name)
|
yellowfive@57
|
691
|
yellowfive@57
|
692 -- guild name
|
yellowfive@57
|
693 if data.Guild == nil then
|
yellowfive@57
|
694 table.insert(fields, "")
|
yellowfive@57
|
695 else
|
yellowfive@57
|
696 table.insert(fields, data.Guild)
|
yellowfive@57
|
697 end
|
yellowfive@57
|
698
|
yellowfive@57
|
699 -- race, default to pandaren if we can't read it for some reason
|
yellowfive@57
|
700 local raceval = Amr.RaceIds[data.Race]
|
yellowfive@57
|
701 if raceval == nil then raceval = 13 end
|
yellowfive@57
|
702 table.insert(fields, raceval)
|
yellowfive@57
|
703
|
yellowfive@57
|
704 -- faction, default to alliance if we can't read it for some reason
|
yellowfive@57
|
705 raceval = Amr.FactionIds[data.Faction]
|
yellowfive@57
|
706 if raceval == nil then raceval = 1 end
|
yellowfive@57
|
707 table.insert(fields, raceval)
|
yellowfive@57
|
708
|
yellowfive@124
|
709 table.insert(fields, data.Level)
|
yellowfive@185
|
710
|
yellowfive@57
|
711 local profs = {}
|
yellowfive@57
|
712 local noprofs = true
|
yellowfive@57
|
713 if data.Professions then
|
yellowfive@57
|
714 for k, v in pairs(data.Professions) do
|
yellowfive@57
|
715 local profval = Amr.ProfessionIds[k]
|
yellowfive@57
|
716 if profval ~= nil then
|
yellowfive@57
|
717 noprofs = false
|
yellowfive@57
|
718 table.insert(profs, profval .. ":" .. v)
|
yellowfive@57
|
719 end
|
yellowfive@57
|
720 end
|
yellowfive@57
|
721 end
|
yellowfive@57
|
722
|
yellowfive@57
|
723 if noprofs then
|
yellowfive@57
|
724 table.insert(profs, "0:0")
|
yellowfive@57
|
725 end
|
yellowfive@57
|
726
|
yellowfive@57
|
727 table.insert(fields, table.concat(profs, ","))
|
yellowfive@57
|
728
|
yellowfive@57
|
729 -- export specs
|
yellowfive@57
|
730 table.insert(fields, data.ActiveSpec)
|
yellowfive@81
|
731 for spec = 1, 4 do
|
yellowfive@57
|
732 if data.Specs[spec] and (complete or spec == data.ActiveSpec) then
|
yellowfive@57
|
733 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block
|
yellowfive@81
|
734 table.insert(fields, data.Specs[spec])
|
yellowfive@165
|
735 table.insert(fields, data.Talents[spec] or "")
|
yellowfive@185
|
736 table.insert(fields, data.ActiveSoulbinds and data.ActiveSoulbinds[spec] or "0")
|
yellowfive@185
|
737
|
yellowfive@185
|
738 --[[
|
yellowfive@165
|
739 local essences = {}
|
yellowfive@165
|
740 if data.Essences and data.Essences[spec] then
|
yellowfive@165
|
741 for i, ess in ipairs(data.Essences[spec]) do
|
yellowfive@165
|
742 table.insert(essences, table.concat(ess, "."))
|
yellowfive@165
|
743 end
|
yellowfive@165
|
744 end
|
yellowfive@165
|
745 table.insert(fields, table.concat(essences, "_"))
|
yellowfive@185
|
746 ]]
|
yellowfive@57
|
747 end
|
yellowfive@57
|
748 end
|
yellowfive@57
|
749
|
yellowfive@57
|
750 -- export equipped gear
|
yellowfive@57
|
751 if data.Equipped then
|
yellowfive@81
|
752 for spec = 1, 4 do
|
yellowfive@57
|
753 if data.Equipped[spec] and (complete or spec == data.ActiveSpec) then
|
yellowfive@57
|
754 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block
|
yellowfive@57
|
755
|
yellowfive@57
|
756 local itemObjects = {}
|
yellowfive@124
|
757 for k, itemData in pairs(data.Equipped[spec]) do
|
yellowfive@57
|
758 itemData.slot = k
|
yellowfive@57
|
759 table.insert(itemObjects, itemData)
|
yellowfive@57
|
760 end
|
yellowfive@57
|
761
|
yellowfive@57
|
762 appendItemsToExport(fields, itemObjects)
|
yellowfive@57
|
763 end
|
yellowfive@57
|
764 end
|
yellowfive@57
|
765 end
|
yellowfive@165
|
766
|
yellowfive@185
|
767 -- export soulbind tree info
|
yellowfive@185
|
768 if data.Soulbinds then
|
yellowfive@185
|
769 table.insert(fields, ".sol")
|
yellowfive@185
|
770 for soulbindId, soulbindData in pairs(data.Soulbinds) do
|
yellowfive@185
|
771 table.insert(fields, string.format("u.%s.%s", soulbindId, soulbindData.UnlockedTier))
|
yellowfive@185
|
772 for tier, node in pairs(soulbindData.Nodes) do
|
yellowfive@185
|
773 table.insert(fields, table.concat(node, "."))
|
yellowfive@185
|
774 end
|
yellowfive@185
|
775 end
|
yellowfive@185
|
776 end
|
yellowfive@185
|
777
|
yellowfive@185
|
778 -- export unlocked conduits
|
yellowfive@185
|
779 if data.UnlockedConduits then
|
yellowfive@185
|
780 table.insert(fields, ".con")
|
yellowfive@185
|
781 for i, conduit in ipairs(data.UnlockedConduits) do
|
yellowfive@185
|
782 table.insert(fields, table.concat(conduit, "."))
|
yellowfive@185
|
783 end
|
yellowfive@185
|
784 end
|
yellowfive@185
|
785
|
yellowfive@185
|
786 --[[
|
yellowfive@165
|
787 -- export unlocked essences
|
yellowfive@165
|
788 if data.UnlockedEssences then
|
yellowfive@165
|
789 table.insert(fields, ".ess")
|
yellowfive@165
|
790 for i, ess in ipairs(data.UnlockedEssences) do
|
yellowfive@165
|
791 table.insert(fields, table.concat(ess, "_"))
|
yellowfive@165
|
792 end
|
yellowfive@165
|
793 end
|
yellowfive@185
|
794 ]]
|
yellowfive@185
|
795
|
yellowfive@124
|
796 -- if doing a complete export, include bank/bag items too
|
yellowfive@124
|
797 if complete then
|
yellowfive@124
|
798
|
yellowfive@57
|
799 local itemObjects = {}
|
yellowfive@57
|
800 if data.BagItems then
|
yellowfive@124
|
801 for i, itemData in ipairs(data.BagItems) do
|
yellowfive@124
|
802 if itemData then
|
yellowfive@57
|
803 table.insert(itemObjects, itemData)
|
yellowfive@57
|
804 end
|
yellowfive@57
|
805 end
|
yellowfive@57
|
806 end
|
yellowfive@127
|
807 if data.BankItems then
|
yellowfive@124
|
808 for i, itemData in ipairs(data.BankItems) do
|
yellowfive@127
|
809 if itemData then
|
yellowfive@57
|
810 table.insert(itemObjects, itemData)
|
yellowfive@57
|
811 end
|
yellowfive@57
|
812 end
|
yellowfive@124
|
813 end
|
yellowfive@124
|
814
|
yellowfive@57
|
815 table.insert(fields, ".inv")
|
yellowfive@57
|
816 appendItemsToExport(fields, itemObjects)
|
yellowfive@57
|
817 end
|
yellowfive@57
|
818
|
yellowfive@57
|
819 return "$" .. table.concat(fields, ";") .. "$"
|
yellowfive@57
|
820
|
yellowfive@57
|
821 end
|
yellowfive@57
|
822
|
yellowfive@165
|
823 --[[
|
yellowfive@57
|
824 -- Shortcut for the common use case: serialize the player's currently active setup with no extras.
|
yellowfive@57
|
825 function Amr:SerializePlayer()
|
yellowfive@57
|
826 local data = self:GetPlayerData()
|
yellowfive@57
|
827 return self:SerializePlayerData(data)
|
yellowfive@57
|
828 end
|
yellowfive@165
|
829 ]]
|
yellowfive@57
|
830
|
yellowfive@81
|
831 --[[
|
yellowfive@57
|
832 ----------------------------------------------------------------------------------------------------------------------
|
yellowfive@57
|
833 -- Character Snapshots
|
yellowfive@81
|
834 -- This feature snapshots a player's gear/talents/artifact when entering combat. It is enabled by default. Consumers
|
yellowfive@57
|
835 -- of this library can create a setting to enable/disable it as desired per a user setting.
|
yellowfive@57
|
836 --
|
yellowfive@57
|
837 -- You should register for the AMR_SNAPSHOT_STATE_CHANGED message (sent via AceEvent-3.0 messaging) to ensure that
|
yellowfive@57
|
838 -- your addon settings stay in sync with any other addon that may also be trying to control the enabled state.
|
yellowfive@57
|
839 --
|
yellowfive@57
|
840 -- Note that if a user has the main AMR addon installed, it will always enable snapshotting, and override any attempt
|
yellowfive@57
|
841 -- to disable it by immediately re-enabling it and thus re-triggering AMR_SNAPSHOT_STATE_CHANGED.
|
yellowfive@57
|
842 ----------------------------------------------------------------------------------------------------------------------
|
yellowfive@57
|
843 Amr._snapshotEnabled = true
|
yellowfive@57
|
844
|
yellowfive@57
|
845 -- Enable snapshotting of character data when entering combat. Sends this player's character data to anyone logging with the AskMrRobot addon.
|
yellowfive@57
|
846 function Amr:EnableSnapshots()
|
yellowfive@57
|
847 self._snapshotEnabled = true
|
yellowfive@57
|
848 self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled)
|
yellowfive@57
|
849 end
|
yellowfive@57
|
850
|
yellowfive@57
|
851 -- Disable snapshotting of character data when entering combat.
|
yellowfive@57
|
852 function Amr:DisableSnapshots()
|
yellowfive@57
|
853 self._snapshotEnabled = false
|
yellowfive@57
|
854 self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled)
|
yellowfive@57
|
855 end
|
yellowfive@57
|
856
|
yellowfive@57
|
857 function Amr:IsSnapshotEnabled()
|
yellowfive@57
|
858 return self._snapshotEnabled
|
yellowfive@57
|
859 end
|
yellowfive@57
|
860
|
yellowfive@57
|
861
|
yellowfive@57
|
862 function Amr:PLAYER_REGEN_DISABLED()
|
yellowfive@57
|
863 --function Amr:GARRISON_MISSION_NPC_OPENED()
|
yellowfive@57
|
864
|
yellowfive@57
|
865 -- send data about this character when a player enters combat in a supported zone
|
yellowfive@57
|
866 if self._snapshotEnabled and Amr.IsSupportedInstance() then
|
yellowfive@57
|
867 local t = time()
|
yellowfive@57
|
868 local player = self:GetPlayerData()
|
yellowfive@57
|
869 local msg = self:SerializePlayerData(player)
|
yellowfive@57
|
870 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
|
871
|
yellowfive@57
|
872 self:SendCommMessage(Amr.ChatPrefix, msg, "RAID")
|
yellowfive@57
|
873 end
|
yellowfive@57
|
874 end
|
yellowfive@57
|
875
|
yellowfive@57
|
876 Amr:RegisterEvent("PLAYER_REGEN_DISABLED")
|
yellowfive@81
|
877 --Amr:RegisterEvent("GARRISON_MISSION_NPC_OPENED") -- for debugging, fire this event when open mission table
|
yellowfive@122
|
878 ]]
|