yellowfive@57
|
1 -- AskMrRobot-Serializer will serialize and communicate character data between users.
|
yellowfive@57
|
2
|
Yellowfive@197
|
3 local MAJOR, MINOR = "AskMrRobot-Serializer", 96
|
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@185
|
159 Nathria = 2296
|
yellowfive@57
|
160 }
|
yellowfive@57
|
161
|
yellowfive@57
|
162 -- instances that AskMrRobot currently supports logging for
|
yellowfive@57
|
163 Amr.SupportedInstanceIds = {
|
yellowfive@185
|
164 [2296] = true
|
yellowfive@57
|
165 }
|
yellowfive@57
|
166
|
yellowfive@57
|
167
|
yellowfive@57
|
168 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
169 -- Public Utility Methods
|
yellowfive@57
|
170 ----------------------------------------------------------------------------------------
|
yellowfive@57
|
171
|
yellowfive@81
|
172 local function readBonusIdList(parts, first, last)
|
yellowfive@124
|
173 local ret = {}
|
yellowfive@81
|
174 for i = first, last do
|
yellowfive@81
|
175 table.insert(ret, tonumber(parts[i]))
|
yellowfive@81
|
176 end
|
yellowfive@81
|
177 table.sort(ret)
|
yellowfive@81
|
178 return ret
|
yellowfive@81
|
179 end
|
yellowfive@81
|
180
|
Yellowfive@195
|
181 -- 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
Yellowfive@195
|
182 -- itemId:ench:gem1 :gem2 :gem3 :gem4:suf:uid:lvl:spec:flags :instdiffid:numbonusIDs:bonusIDs1...n :varies:? :relic bonus ids
|
Yellowfive@195
|
183 --|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@195
|
184 --|cff1eff00|Hitem:175722: : : : : : : :57 :102 : :11 :1 :6707 :2 :28:1340:9 :54:::|h[name]|h|r
|
yellowfive@57
|
185 -- get an object with all of the parts of the item link format that we care about
|
yellowfive@57
|
186 function Amr.ParseItemLink(itemLink)
|
yellowfive@57
|
187 if not itemLink then return nil end
|
yellowfive@57
|
188
|
yellowfive@57
|
189 local str = string.match(itemLink, "|Hitem:([\-%d:]+)|")
|
yellowfive@57
|
190 if not str then return nil end
|
yellowfive@57
|
191
|
yellowfive@57
|
192 local parts = { strsplit(":", str) }
|
yellowfive@57
|
193
|
yellowfive@124
|
194 local item = {}
|
yellowfive@124
|
195 item.link = itemLink
|
yellowfive@81
|
196 item.id = tonumber(parts[1]) or 0
|
yellowfive@81
|
197 item.enchantId = tonumber(parts[2]) or 0
|
yellowfive@81
|
198 item.gemIds = { tonumber(parts[3]) or 0, tonumber(parts[4]) or 0, tonumber(parts[5]) or 0, tonumber(parts[6]) or 0 }
|
yellowfive@81
|
199 item.suffixId = math.abs(tonumber(parts[7]) or 0) -- convert suffix to positive number, that's what we use in our code
|
yellowfive@81
|
200 -- part 8 is some unique ID... we never really used it
|
yellowfive@81
|
201 -- part 9 is current player level
|
yellowfive@81
|
202 -- part 10 is player spec
|
yellowfive@185
|
203 -- 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
|
204 -- part 12 is instance difficulty id
|
yellowfive@185
|
205
|
yellowfive@185
|
206 -- 13 is num bonus IDs, followed by bonus IDs
|
yellowfive@81
|
207 local numBonuses = tonumber(parts[13]) or 0
|
yellowfive@81
|
208 local offset = numBonuses
|
yellowfive@81
|
209 if numBonuses > 0 then
|
yellowfive@81
|
210 item.bonusIds = readBonusIdList(parts, 14, 13 + numBonuses)
|
yellowfive@57
|
211 end
|
yellowfive@69
|
212
|
yellowfive@81
|
213 item.upgradeId = 0
|
yellowfive@81
|
214 item.level = 0
|
Yellowfive@195
|
215 item.stat1 = 0
|
Yellowfive@195
|
216 item.stat2 = 0
|
yellowfive@185
|
217
|
Yellowfive@195
|
218 -- part 14 + numBonuses, seems to be the number of prop-value "pairs" that will follow,
|
Yellowfive@195
|
219 -- for now we just parse the properties that we care about
|
Yellowfive@195
|
220 local numProps = tonumber(parts[14 + offset]) or 0
|
Yellowfive@195
|
221 if numProps > 0 then
|
Yellowfive@195
|
222 for i = 15 + offset, 14 + offset + numProps * 2, 2 do
|
Yellowfive@195
|
223 local prop = tonumber(parts[i]) or 0
|
Yellowfive@195
|
224 local propVal = tonumber(parts[i + 1]) or 0
|
Yellowfive@195
|
225 if prop == 9 then
|
Yellowfive@195
|
226 item.level = propVal
|
Yellowfive@195
|
227 elseif prop == 29 then
|
Yellowfive@195
|
228 item.stat1 = propVal
|
Yellowfive@195
|
229 elseif prop == 30 then
|
Yellowfive@195
|
230 item.stat2 = propVal
|
Yellowfive@195
|
231 end
|
yellowfive@185
|
232 end
|
yellowfive@185
|
233 end
|
yellowfive@185
|
234
|
yellowfive@185
|
235 -- we don't need relic information anymore
|
yellowfive@185
|
236 --[[elseif #parts > 19 + offset then
|
yellowfive@124
|
237 -- check for relic info
|
yellowfive@124
|
238 item.relicBonusIds = { nil, nil, nil }
|
yellowfive@124
|
239 numBonuses = tonumber(parts[16 + offset])
|
yellowfive@124
|
240 if numBonuses then
|
yellowfive@124
|
241 if numBonuses > 0 then
|
yellowfive@124
|
242 item.relicBonusIds[1] = readBonusIdList(parts, 17 + offset, 16 + offset + numBonuses)
|
yellowfive@124
|
243 end
|
yellowfive@124
|
244
|
yellowfive@129
|
245 offset = offset + numBonuses
|
yellowfive@124
|
246 if #parts > 17 + offset then
|
yellowfive@124
|
247 numBonuses = tonumber(parts[17 + offset])
|
yellowfive@129
|
248 if numBonuses then
|
yellowfive@129
|
249 if numBonuses > 0 then
|
yellowfive@129
|
250 item.relicBonusIds[2] = readBonusIdList(parts, 18 + offset, 17 + offset + numBonuses)
|
yellowfive@129
|
251 end
|
yellowfive@129
|
252
|
yellowfive@129
|
253 offset= offset + numBonuses
|
yellowfive@129
|
254 if #parts > 18 + offset then
|
yellowfive@129
|
255 numBonuses = tonumber(parts[18 + offset])
|
yellowfive@129
|
256 if numBonuses then
|
yellowfive@129
|
257 if numBonuses > 0 then
|
yellowfive@129
|
258 item.relicBonusIds[3] = readBonusIdList(parts, 19 + offset, 18 + offset + numBonuses)
|
yellowfive@129
|
259 end
|
yellowfive@129
|
260 end
|
yellowfive@129
|
261 end
|
yellowfive@124
|
262 end
|
yellowfive@124
|
263 end
|
yellowfive@124
|
264 end
|
yellowfive@185
|
265 end]]
|
yellowfive@81
|
266
|
yellowfive@57
|
267 return item
|
yellowfive@57
|
268 end
|
yellowfive@57
|
269
|
yellowfive@135
|
270 local AZERITE_EMPOWERED_BONUS_ID = 4775
|
yellowfive@135
|
271
|
yellowfive@135
|
272 function Amr.GetItemUniqueId(item, noUpgrade, noAzeriteEmpoweredBonusId)
|
yellowfive@81
|
273 if not item then return "" end
|
yellowfive@81
|
274 local ret = item.id .. ""
|
yellowfive@81
|
275 if item.bonusIds then
|
yellowfive@135
|
276 for i = 1, #item.bonusIds do
|
yellowfive@135
|
277 if not noAzeriteEmpoweredBonusId or item.bonusIds[i] ~= AZERITE_EMPOWERED_BONUS_ID then
|
yellowfive@135
|
278 ret = ret .. "b" .. item.bonusIds[i]
|
yellowfive@135
|
279 end
|
yellowfive@81
|
280 end
|
yellowfive@81
|
281 end
|
yellowfive@81
|
282 if item.suffixId ~= 0 then
|
yellowfive@81
|
283 ret = ret .. "s" .. item.suffixId
|
yellowfive@81
|
284 end
|
yellowfive@81
|
285 if not noUpgrade and item.upgradeId ~= 0 then
|
yellowfive@81
|
286 ret = ret .. "u" .. item.upgradeId
|
yellowfive@81
|
287 end
|
Yellowfive@195
|
288 if item.level and item.level ~= 0 then
|
yellowfive@81
|
289 ret = ret .. "v" .. item.level
|
yellowfive@81
|
290 end
|
Yellowfive@195
|
291 if item.stat1 and item.stat1 ~= 0 then
|
Yellowfive@195
|
292 ret = ret .. "j" .. item.stat1
|
Yellowfive@195
|
293 end
|
Yellowfive@195
|
294 if item.stat2 and item.stat2 ~= 0 then
|
Yellowfive@195
|
295 ret = ret .. "k" .. item.stat2
|
Yellowfive@195
|
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@195
|
598 if itemData.level and 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@195
|
609 if itemData.stat1 and itemData.stat1 ~= 0 then
|
Yellowfive@195
|
610 table.insert(itemParts, "j" .. itemData.stat1)
|
Yellowfive@195
|
611 end
|
Yellowfive@195
|
612 if itemData.stat2 and itemData.stat2 ~= 0 then
|
Yellowfive@195
|
613 table.insert(itemParts, "k" .. itemData.stat2)
|
Yellowfive@195
|
614 end
|
Yellowfive@195
|
615
|
yellowfive@185
|
616 --[[
|
yellowfive@124
|
617 if itemData.azerite then
|
yellowfive@124
|
618 for aIndex, aValue in ipairs(itemData.azerite) do
|
yellowfive@124
|
619 table.insert(itemParts, "a" .. (aValue - prevAzeriteId))
|
yellowfive@124
|
620 prevAzeriteId = aValue
|
yellowfive@124
|
621 end
|
yellowfive@124
|
622 end
|
yellowfive@185
|
623 ]]
|
yellowfive@185
|
624
|
yellowfive@81
|
625 if itemData.gemIds[1] ~= 0 then
|
yellowfive@81
|
626 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId))
|
yellowfive@81
|
627 prevGemId = itemData.gemIds[1]
|
yellowfive@81
|
628 end
|
yellowfive@81
|
629 if itemData.gemIds[2] ~= 0 then
|
yellowfive@81
|
630 table.insert(itemParts, "y" .. (itemData.gemIds[2] - prevGemId))
|
yellowfive@81
|
631 prevGemId = itemData.gemIds[2]
|
yellowfive@81
|
632 end
|
yellowfive@81
|
633 if itemData.gemIds[3] ~= 0 then
|
yellowfive@81
|
634 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId))
|
yellowfive@81
|
635 prevGemId = itemData.gemIds[3]
|
yellowfive@124
|
636 end
|
yellowfive@81
|
637
|
yellowfive@57
|
638 if itemData.enchantId ~= 0 then
|
yellowfive@57
|
639 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId))
|
yellowfive@57
|
640 prevEnchantId = itemData.enchantId
|
yellowfive@57
|
641 end
|
yellowfive@124
|
642
|
yellowfive@124
|
643 if itemData.relicBonusIds and itemData.relicBonusIds[1] ~= nil then
|
yellowfive@124
|
644 for bIndex, bValue in ipairs(itemData.relicBonusIds[1]) do
|
yellowfive@124
|
645 table.insert(itemParts, "p" .. (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[2] ~= nil then
|
yellowfive@124
|
651 for bIndex, bValue in ipairs(itemData.relicBonusIds[2]) do
|
yellowfive@124
|
652 table.insert(itemParts, "q" .. (bValue - prevRelicBonusId))
|
yellowfive@124
|
653 prevRelicBonusId = bValue
|
yellowfive@124
|
654 end
|
yellowfive@124
|
655 end
|
yellowfive@124
|
656
|
yellowfive@124
|
657 if itemData.relicBonusIds and itemData.relicBonusIds[3] ~= nil then
|
yellowfive@124
|
658 for bIndex, bValue in ipairs(itemData.relicBonusIds[3]) do
|
yellowfive@124
|
659 table.insert(itemParts, "r" .. (bValue - prevRelicBonusId))
|
yellowfive@124
|
660 prevRelicBonusId = bValue
|
yellowfive@124
|
661 end
|
Yellowfive@195
|
662 end
|
yellowfive@191
|
663
|
yellowfive@191
|
664 if itemData.guid then
|
yellowfive@191
|
665 table.insert(itemParts, "!" .. itemData.guid)
|
yellowfive@191
|
666 end
|
yellowfive@124
|
667
|
yellowfive@57
|
668 table.insert(fields, table.concat(itemParts, ""))
|
yellowfive@57
|
669 end
|
yellowfive@57
|
670 end
|
yellowfive@57
|
671
|
yellowfive@57
|
672 -- Serialize just the identity portion of a player (region/realm/name) in the same format used by the full serialization
|
yellowfive@57
|
673 function Amr:SerializePlayerIdentity(data)
|
yellowfive@57
|
674 local fields = {}
|
yellowfive@57
|
675 table.insert(fields, MINOR)
|
yellowfive@57
|
676 table.insert(fields, data.Region)
|
yellowfive@57
|
677 table.insert(fields, data.Realm)
|
yellowfive@57
|
678 table.insert(fields, data.Name)
|
yellowfive@57
|
679 return "$" .. table.concat(fields, ";") .. "$"
|
yellowfive@57
|
680 end
|
yellowfive@57
|
681
|
yellowfive@57
|
682 -- Serialize player data gathered by GetPlayerData. This can be augmented with extra data if desired (augmenting used mainly by AskMrRobot addon).
|
yellowfive@57
|
683 -- Pass complete = true to do a complete export of this extra information, otherwise it is ignored.
|
yellowfive@57
|
684 -- Extra data can include:
|
yellowfive@57
|
685 -- equipped gear for the player's inactive spec, slot id to item link dictionary
|
yellowfive@57
|
686 -- Reputations
|
yellowfive@57
|
687 -- BagItems, BankItems, VoidItems, lists of item links
|
yellowfive@57
|
688 --
|
yellowfive@57
|
689 function Amr:SerializePlayerData(data, complete)
|
yellowfive@57
|
690
|
yellowfive@57
|
691 local fields = {}
|
yellowfive@57
|
692
|
yellowfive@57
|
693 -- compressed string uses a fixed order rather than inserting identifiers
|
yellowfive@57
|
694 table.insert(fields, MINOR)
|
yellowfive@57
|
695 table.insert(fields, data.Region)
|
yellowfive@57
|
696 table.insert(fields, data.Realm)
|
yellowfive@57
|
697 table.insert(fields, data.Name)
|
yellowfive@57
|
698
|
yellowfive@57
|
699 -- guild name
|
yellowfive@57
|
700 if data.Guild == nil then
|
yellowfive@57
|
701 table.insert(fields, "")
|
yellowfive@57
|
702 else
|
yellowfive@57
|
703 table.insert(fields, data.Guild)
|
yellowfive@57
|
704 end
|
yellowfive@57
|
705
|
yellowfive@57
|
706 -- race, default to pandaren if we can't read it for some reason
|
yellowfive@57
|
707 local raceval = Amr.RaceIds[data.Race]
|
yellowfive@57
|
708 if raceval == nil then raceval = 13 end
|
yellowfive@57
|
709 table.insert(fields, raceval)
|
yellowfive@57
|
710
|
yellowfive@57
|
711 -- faction, default to alliance if we can't read it for some reason
|
yellowfive@57
|
712 raceval = Amr.FactionIds[data.Faction]
|
yellowfive@57
|
713 if raceval == nil then raceval = 1 end
|
yellowfive@57
|
714 table.insert(fields, raceval)
|
yellowfive@57
|
715
|
yellowfive@124
|
716 table.insert(fields, data.Level)
|
yellowfive@185
|
717
|
yellowfive@57
|
718 local profs = {}
|
yellowfive@57
|
719 local noprofs = true
|
yellowfive@57
|
720 if data.Professions then
|
yellowfive@57
|
721 for k, v in pairs(data.Professions) do
|
yellowfive@57
|
722 local profval = Amr.ProfessionIds[k]
|
yellowfive@57
|
723 if profval ~= nil then
|
yellowfive@57
|
724 noprofs = false
|
yellowfive@57
|
725 table.insert(profs, profval .. ":" .. v)
|
yellowfive@57
|
726 end
|
yellowfive@57
|
727 end
|
yellowfive@57
|
728 end
|
yellowfive@57
|
729
|
yellowfive@57
|
730 if noprofs then
|
yellowfive@57
|
731 table.insert(profs, "0:0")
|
yellowfive@57
|
732 end
|
yellowfive@57
|
733
|
yellowfive@57
|
734 table.insert(fields, table.concat(profs, ","))
|
yellowfive@57
|
735
|
yellowfive@57
|
736 -- export specs
|
yellowfive@57
|
737 table.insert(fields, data.ActiveSpec)
|
yellowfive@81
|
738 for spec = 1, 4 do
|
yellowfive@57
|
739 if data.Specs[spec] and (complete or spec == data.ActiveSpec) then
|
yellowfive@57
|
740 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block
|
yellowfive@81
|
741 table.insert(fields, data.Specs[spec])
|
yellowfive@165
|
742 table.insert(fields, data.Talents[spec] or "")
|
yellowfive@185
|
743 table.insert(fields, data.ActiveSoulbinds and data.ActiveSoulbinds[spec] or "0")
|
yellowfive@185
|
744
|
yellowfive@185
|
745 --[[
|
yellowfive@165
|
746 local essences = {}
|
yellowfive@165
|
747 if data.Essences and data.Essences[spec] then
|
yellowfive@165
|
748 for i, ess in ipairs(data.Essences[spec]) do
|
yellowfive@165
|
749 table.insert(essences, table.concat(ess, "."))
|
yellowfive@165
|
750 end
|
yellowfive@165
|
751 end
|
yellowfive@165
|
752 table.insert(fields, table.concat(essences, "_"))
|
yellowfive@185
|
753 ]]
|
yellowfive@57
|
754 end
|
yellowfive@57
|
755 end
|
yellowfive@57
|
756
|
yellowfive@57
|
757 -- export equipped gear
|
yellowfive@57
|
758 if data.Equipped then
|
yellowfive@81
|
759 for spec = 1, 4 do
|
yellowfive@57
|
760 if data.Equipped[spec] and (complete or spec == data.ActiveSpec) then
|
yellowfive@57
|
761 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block
|
yellowfive@57
|
762
|
yellowfive@57
|
763 local itemObjects = {}
|
yellowfive@124
|
764 for k, itemData in pairs(data.Equipped[spec]) do
|
yellowfive@57
|
765 itemData.slot = k
|
yellowfive@57
|
766 table.insert(itemObjects, itemData)
|
yellowfive@57
|
767 end
|
yellowfive@57
|
768
|
yellowfive@57
|
769 appendItemsToExport(fields, itemObjects)
|
yellowfive@57
|
770 end
|
yellowfive@57
|
771 end
|
yellowfive@57
|
772 end
|
yellowfive@165
|
773
|
yellowfive@185
|
774 -- export soulbind tree info
|
yellowfive@185
|
775 if data.Soulbinds then
|
yellowfive@185
|
776 table.insert(fields, ".sol")
|
yellowfive@185
|
777 for soulbindId, soulbindData in pairs(data.Soulbinds) do
|
yellowfive@185
|
778 table.insert(fields, string.format("u.%s.%s", soulbindId, soulbindData.UnlockedTier))
|
yellowfive@185
|
779 for tier, node in pairs(soulbindData.Nodes) do
|
yellowfive@185
|
780 table.insert(fields, table.concat(node, "."))
|
yellowfive@185
|
781 end
|
yellowfive@185
|
782 end
|
yellowfive@185
|
783 end
|
yellowfive@185
|
784
|
yellowfive@185
|
785 -- export unlocked conduits
|
yellowfive@185
|
786 if data.UnlockedConduits then
|
yellowfive@185
|
787 table.insert(fields, ".con")
|
yellowfive@185
|
788 for i, conduit in ipairs(data.UnlockedConduits) do
|
yellowfive@185
|
789 table.insert(fields, table.concat(conduit, "."))
|
yellowfive@185
|
790 end
|
yellowfive@185
|
791 end
|
yellowfive@185
|
792
|
yellowfive@185
|
793 --[[
|
yellowfive@165
|
794 -- export unlocked essences
|
yellowfive@165
|
795 if data.UnlockedEssences then
|
yellowfive@165
|
796 table.insert(fields, ".ess")
|
yellowfive@165
|
797 for i, ess in ipairs(data.UnlockedEssences) do
|
yellowfive@165
|
798 table.insert(fields, table.concat(ess, "_"))
|
yellowfive@165
|
799 end
|
yellowfive@165
|
800 end
|
yellowfive@185
|
801 ]]
|
yellowfive@185
|
802
|
yellowfive@124
|
803 -- if doing a complete export, include bank/bag items too
|
yellowfive@124
|
804 if complete then
|
yellowfive@124
|
805
|
yellowfive@57
|
806 local itemObjects = {}
|
yellowfive@57
|
807 if data.BagItems then
|
yellowfive@124
|
808 for i, itemData in ipairs(data.BagItems) do
|
yellowfive@124
|
809 if itemData then
|
yellowfive@57
|
810 table.insert(itemObjects, itemData)
|
yellowfive@57
|
811 end
|
yellowfive@57
|
812 end
|
yellowfive@57
|
813 end
|
yellowfive@127
|
814 if data.BankItems then
|
yellowfive@124
|
815 for i, itemData in ipairs(data.BankItems) do
|
yellowfive@127
|
816 if itemData then
|
yellowfive@57
|
817 table.insert(itemObjects, itemData)
|
yellowfive@57
|
818 end
|
yellowfive@57
|
819 end
|
yellowfive@124
|
820 end
|
yellowfive@124
|
821
|
yellowfive@57
|
822 table.insert(fields, ".inv")
|
Yellowfive@197
|
823 appendItemsToExport(fields, itemObjects)
|
Yellowfive@197
|
824
|
Yellowfive@197
|
825 if data.GreatVaultItems then
|
Yellowfive@197
|
826 itemObjects = {}
|
Yellowfive@197
|
827 for i, itemData in ipairs(data.GreatVaultItems) do
|
Yellowfive@197
|
828 if itemData then
|
Yellowfive@197
|
829 table.insert(itemObjects, itemData)
|
Yellowfive@197
|
830 end
|
Yellowfive@197
|
831 end
|
Yellowfive@197
|
832 table.insert(fields, ".gv")
|
Yellowfive@197
|
833 appendItemsToExport(fields, itemObjects)
|
Yellowfive@197
|
834 end
|
yellowfive@57
|
835 end
|
yellowfive@57
|
836
|
yellowfive@57
|
837 return "$" .. table.concat(fields, ";") .. "$"
|
yellowfive@57
|
838
|
yellowfive@57
|
839 end
|
yellowfive@57
|
840
|
yellowfive@165
|
841 --[[
|
yellowfive@57
|
842 -- Shortcut for the common use case: serialize the player's currently active setup with no extras.
|
yellowfive@57
|
843 function Amr:SerializePlayer()
|
yellowfive@57
|
844 local data = self:GetPlayerData()
|
yellowfive@57
|
845 return self:SerializePlayerData(data)
|
yellowfive@57
|
846 end
|
yellowfive@165
|
847 ]]
|
yellowfive@57
|
848
|
yellowfive@81
|
849 --[[
|
yellowfive@57
|
850 ----------------------------------------------------------------------------------------------------------------------
|
yellowfive@57
|
851 -- Character Snapshots
|
yellowfive@81
|
852 -- This feature snapshots a player's gear/talents/artifact when entering combat. It is enabled by default. Consumers
|
yellowfive@57
|
853 -- of this library can create a setting to enable/disable it as desired per a user setting.
|
yellowfive@57
|
854 --
|
yellowfive@57
|
855 -- You should register for the AMR_SNAPSHOT_STATE_CHANGED message (sent via AceEvent-3.0 messaging) to ensure that
|
yellowfive@57
|
856 -- your addon settings stay in sync with any other addon that may also be trying to control the enabled state.
|
yellowfive@57
|
857 --
|
yellowfive@57
|
858 -- Note that if a user has the main AMR addon installed, it will always enable snapshotting, and override any attempt
|
yellowfive@57
|
859 -- to disable it by immediately re-enabling it and thus re-triggering AMR_SNAPSHOT_STATE_CHANGED.
|
yellowfive@57
|
860 ----------------------------------------------------------------------------------------------------------------------
|
yellowfive@57
|
861 Amr._snapshotEnabled = true
|
yellowfive@57
|
862
|
yellowfive@57
|
863 -- Enable snapshotting of character data when entering combat. Sends this player's character data to anyone logging with the AskMrRobot addon.
|
yellowfive@57
|
864 function Amr:EnableSnapshots()
|
yellowfive@57
|
865 self._snapshotEnabled = true
|
yellowfive@57
|
866 self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled)
|
yellowfive@57
|
867 end
|
yellowfive@57
|
868
|
yellowfive@57
|
869 -- Disable snapshotting of character data when entering combat.
|
yellowfive@57
|
870 function Amr:DisableSnapshots()
|
yellowfive@57
|
871 self._snapshotEnabled = false
|
yellowfive@57
|
872 self:SendMessage("AMR_SNAPSHOT_STATE_CHANGED", self._snapshotEnabled)
|
yellowfive@57
|
873 end
|
yellowfive@57
|
874
|
yellowfive@57
|
875 function Amr:IsSnapshotEnabled()
|
yellowfive@57
|
876 return self._snapshotEnabled
|
yellowfive@57
|
877 end
|
yellowfive@57
|
878
|
yellowfive@57
|
879
|
yellowfive@57
|
880 function Amr:PLAYER_REGEN_DISABLED()
|
yellowfive@57
|
881 --function Amr:GARRISON_MISSION_NPC_OPENED()
|
yellowfive@57
|
882
|
yellowfive@57
|
883 -- send data about this character when a player enters combat in a supported zone
|
yellowfive@57
|
884 if self._snapshotEnabled and Amr.IsSupportedInstance() then
|
yellowfive@57
|
885 local t = time()
|
yellowfive@57
|
886 local player = self:GetPlayerData()
|
yellowfive@57
|
887 local msg = self:SerializePlayerData(player)
|
yellowfive@57
|
888 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
|
889
|
yellowfive@57
|
890 self:SendCommMessage(Amr.ChatPrefix, msg, "RAID")
|
yellowfive@57
|
891 end
|
yellowfive@57
|
892 end
|
yellowfive@57
|
893
|
yellowfive@57
|
894 Amr:RegisterEvent("PLAYER_REGEN_DISABLED")
|
yellowfive@81
|
895 --Amr:RegisterEvent("GARRISON_MISSION_NPC_OPENED") -- for debugging, fire this event when open mission table
|
yellowfive@122
|
896 ]]
|