comparison AskMrRobot-Serializer/AskMrRobot-Serializer.lua @ 124:e31b02b24488

Updated for 8.0 pre-patch and BfA.
author yellowfive
date Tue, 17 Jul 2018 09:57:39 -0700
parents f1da233629be
children 65c285394049
comparison
equal deleted inserted replaced
123:7a6364917f86 124:e31b02b24488
1 -- AskMrRobot-Serializer will serialize and communicate character data between users. 1 -- AskMrRobot-Serializer will serialize and communicate character data between users.
2 -- This is used primarily to associate character information to logs uploaded to askmrrobot.com. 2
3 3 local MAJOR, MINOR = "AskMrRobot-Serializer", 58
4 local MAJOR, MINOR = "AskMrRobot-Serializer", 57
5 local Amr, oldminor = LibStub:NewLibrary(MAJOR, MINOR) 4 local Amr, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
6 5
7 if not Amr then return end -- already loaded by something else 6 if not Amr then return end -- already loaded by something else
8 7
9 -- event and comm used for player snapshotting on entering combat 8 -- event and comm used for player snapshotting on entering combat
165 [1648] = true, 164 [1648] = true,
166 [1676] = true, 165 [1676] = true,
167 [1712] = true 166 [1712] = true
168 } 167 }
169 168
170 -- just to make life easier, maps ID of each artifact weapon to the spec number (1-4)
171 Amr.ArtifactIdToSpecNumber = {
172 [128402] = 1, -- DK
173 [128292] = 2,
174 [128403] = 3,
175 [127829] = 1, -- DH
176 [128832] = 2,
177 [128858] = 1, -- Druid
178 [128860] = 2,
179 [128821] = 3,
180 [128306] = 4,
181 [128861] = 1, -- Hunter
182 [128826] = 2,
183 [128808] = 3,
184 [127857] = 1, -- Mage
185 [128820] = 2,
186 [128862] = 3,
187 [128938] = 1, -- Monk
188 [128937] = 2,
189 [128940] = 3,
190 [128823] = 1, -- Paladin
191 [128866] = 2,
192 [120978] = 3,
193 [128868] = 1, -- Priest
194 [128825] = 2,
195 [128827] = 3,
196 [128870] = 1, -- Rogue
197 [128872] = 2,
198 [128476] = 3,
199 [128935] = 1, -- Shaman
200 [128819] = 2,
201 [128911] = 3,
202 [128942] = 1, -- Warlock
203 [128943] = 2,
204 [128941] = 3,
205 [128910] = 1, -- Warrior
206 [128908] = 2,
207 [128289] = 3,
208
209 --[128293] = 2, -- Frost OH
210 --[127830] = 1, -- Havoc OH
211 --[128831] = 2, -- Vengeance OH
212 --[128859] = 2, -- Feral OH
213 --[128822] = 3, -- Guardian OH
214 --[133959] = 2, -- Fire OH
215 --[133948] = 3, -- Windwalker OH
216 --[128867] = 2, -- Prot MH
217 --[133958] = 3, -- Shadow OH
218 --[128869] = 1, -- Rogue OH's
219 --[134552] = 2,
220 --[128479] = 3,
221 --[128936] = 1, -- Shaman OH's
222 --[128873] = 2,
223 --[128934] = 3,
224 --[137246] = 2, -- Demo MH
225 --[134553] = 2, -- Fury OH
226 --[128288] = 3 -- Prot MH
227 }
228
229 -- IDs of set tokens that we would care about in a player's inventory
230 Amr.SetTokenIds = {
231 [127970] = true,
232 [127969] = true,
233 [127968] = true,
234 [127967] = true,
235 [127966] = true,
236 [127965] = true,
237 [127964] = true,
238 [127963] = true,
239 [127962] = true,
240 [127961] = true,
241 [127960] = true,
242 [127959] = true,
243 [127958] = true,
244 [127957] = true,
245 [127956] = true,
246 [127955] = true,
247 [127954] = true,
248 [127953] = true,
249 [120285] = true,
250 [120284] = true,
251 [120283] = true,
252 [120282] = true,
253 [120281] = true,
254 [120280] = true,
255 [120279] = true,
256 [120278] = true,
257 [120277] = true,
258 [120256] = true,
259 [120255] = true,
260 [120254] = true,
261 [120253] = true,
262 [120252] = true,
263 [120251] = true,
264 [120250] = true,
265 [120249] = true,
266 [120248] = true,
267 [120247] = true,
268 [120246] = true,
269 [120245] = true,
270 [120244] = true,
271 [120243] = true,
272 [120242] = true,
273 [120241] = true,
274 [120240] = true,
275 [120239] = true,
276 [120238] = true,
277 [120237] = true,
278 [120236] = true,
279 [120235] = true,
280 [120234] = true,
281 [120233] = true,
282 [120232] = true,
283 [120231] = true,
284 [120230] = true,
285 [120229] = true,
286 [120228] = true,
287 [120227] = true,
288 [120226] = true,
289 [120225] = true,
290 [120224] = true,
291 [120223] = true,
292 [120222] = true,
293 [120221] = true,
294 [120220] = true,
295 [120219] = true,
296 [120218] = true,
297 [120217] = true,
298 [120216] = true,
299 [120215] = true,
300 [120214] = true,
301 [120213] = true,
302 [120212] = true,
303 [120211] = true,
304 [120210] = true,
305 [120209] = true,
306 [120208] = true,
307 [120207] = true,
308 [120206] = true,
309 [119323] = true,
310 [119322] = true,
311 [119321] = true,
312 [119320] = true,
313 [119319] = true,
314 [119318] = true,
315 [119316] = true,
316 [119315] = true,
317 [119314] = true,
318 [119313] = true,
319 [119312] = true,
320 [119311] = true,
321 [119310] = true,
322 [119309] = true,
323 [119308] = true,
324 [119307] = true,
325 [119306] = true,
326 [119305] = true,
327 [105868] = true,
328 [105867] = true,
329 [105866] = true,
330 [105865] = true,
331 [105864] = true,
332 [105863] = true,
333 [105862] = true,
334 [105861] = true,
335 [105860] = true,
336 [105859] = true,
337 [105858] = true,
338 [105857] = true,
339 [99756] = true,
340 [99755] = true,
341 [99754] = true,
342 [99753] = true,
343 [99752] = true,
344 [99751] = true,
345 [99750] = true,
346 [99749] = true,
347 [99748] = true,
348 [99747] = true,
349 [99746] = true,
350 [99745] = true,
351 [99744] = true,
352 [99743] = true,
353 [99742] = true,
354 [99740] = true,
355 [99739] = true,
356 [99738] = true,
357 [99737] = true,
358 [99736] = true,
359 [99735] = true,
360 [99734] = true,
361 [99733] = true,
362 [99732] = true,
363 [99731] = true,
364 [99730] = true,
365 [99729] = true,
366 [99728] = true,
367 [99727] = true,
368 [99726] = true,
369 [99725] = true,
370 [99724] = true,
371 [99723] = true,
372 [99722] = true,
373 [99721] = true,
374 [99720] = true,
375 [99719] = true,
376 [99718] = true,
377 [99717] = true,
378 [99716] = true,
379 [99715] = true,
380 [99714] = true,
381 [99713] = true,
382 [99712] = true,
383 [99711] = true,
384 [99710] = true,
385 [99709] = true,
386 [99708] = true,
387 [99707] = true,
388 [99706] = true,
389 [99705] = true,
390 [99704] = true,
391 [99703] = true,
392 [99702] = true,
393 [99701] = true,
394 [99700] = true,
395 [99699] = true,
396 [99698] = true,
397 [99697] = true,
398 [99696] = true,
399 [99695] = true,
400 [99694] = true,
401 [99693] = true,
402 [99692] = true,
403 [99691] = true,
404 [99690] = true,
405 [99689] = true,
406 [99688] = true,
407 [99687] = true,
408 [99686] = true,
409 [99685] = true,
410 [99684] = true,
411 [99683] = true,
412 [99682] = true,
413 [99681] = true,
414 [99680] = true,
415 [99679] = true,
416 [99678] = true,
417 [99677] = true,
418 [99676] = true,
419 [99675] = true,
420 [99674] = true,
421 [99673] = true,
422 [99672] = true,
423 [99671] = true,
424 [99670] = true,
425 [99669] = true,
426 [99668] = true,
427 [99667] = true,
428 [96701] = true,
429 [96700] = true,
430 [96699] = true,
431 [96633] = true,
432 [96632] = true,
433 [96631] = true,
434 [96625] = true,
435 [96624] = true,
436 [96623] = true,
437 [96601] = true,
438 [96600] = true,
439 [96599] = true,
440 [96568] = true,
441 [96567] = true,
442 [96566] = true,
443 [95957] = true,
444 [95956] = true,
445 [95955] = true,
446 [95889] = true,
447 [95888] = true,
448 [95887] = true,
449 [95881] = true,
450 [95880] = true,
451 [95879] = true,
452 [95857] = true,
453 [95856] = true,
454 [95855] = true,
455 [95824] = true,
456 [95823] = true,
457 [95822] = true,
458 [95583] = true,
459 [95582] = true,
460 [95581] = true,
461 [95580] = true,
462 [95579] = true,
463 [95578] = true,
464 [95577] = true,
465 [95576] = true,
466 [95575] = true,
467 [95574] = true,
468 [95573] = true,
469 [95572] = true,
470 [95571] = true,
471 [95570] = true,
472 [95569] = true,
473 [89278] = true,
474 [89277] = true,
475 [89276] = true,
476 [89275] = true,
477 [89274] = true,
478 [89273] = true,
479 [89272] = true,
480 [89271] = true,
481 [89270] = true,
482 [89269] = true,
483 [89268] = true,
484 [89267] = true,
485 [89266] = true,
486 [89265] = true,
487 [89264] = true,
488 [89263] = true,
489 [89262] = true,
490 [89261] = true,
491 [89260] = true,
492 [89259] = true,
493 [89258] = true,
494 [89257] = true,
495 [89256] = true,
496 [89255] = true,
497 [89254] = true,
498 [89253] = true,
499 [89252] = true,
500 [89251] = true,
501 [89250] = true,
502 [89249] = true,
503 [89248] = true,
504 [89247] = true,
505 [89246] = true,
506 [89245] = true,
507 [89244] = true,
508 [89243] = true,
509 [89242] = true,
510 [89241] = true,
511 [89240] = true,
512 [89239] = true,
513 [89238] = true,
514 [89237] = true,
515 [89236] = true,
516 [89235] = true,
517 [89234] = true,
518 [78876] = true,
519 [78875] = true,
520 [78874] = true,
521 [78873] = true,
522 [78872] = true,
523 [78871] = true,
524 [78867] = true,
525 [78866] = true,
526 [78865] = true,
527 [78864] = true,
528 [78863] = true,
529 [78862] = true,
530 [78861] = true,
531 [78860] = true,
532 [78859] = true,
533 [78858] = true,
534 [78857] = true,
535 [78856] = true,
536 [78855] = true,
537 [78854] = true,
538 [78853] = true,
539 [78849] = true,
540 [78848] = true,
541 [78847] = true,
542 [78184] = true,
543 [78183] = true,
544 [78181] = true,
545 [78180] = true,
546 [78179] = true,
547 [78178] = true,
548 [78176] = true,
549 [78175] = true,
550 [78174] = true,
551 [78173] = true,
552 [78171] = true,
553 [78170] = true,
554 [71687] = true,
555 [71686] = true,
556 [71685] = true,
557 [71683] = true,
558 [71682] = true,
559 [71680] = true,
560 [71679] = true,
561 [71678] = true,
562 [71676] = true,
563 [71675] = true,
564 [71673] = true,
565 [71672] = true,
566 [71671] = true,
567 [71669] = true,
568 [71668] = true,
569 [67431] = true,
570 [67430] = true,
571 [67429] = true,
572 [67428] = true,
573 [67427] = true,
574 [67426] = true,
575 [67425] = true,
576 [67424] = true,
577 [67423] = true,
578 [66998] = true,
579 [65089] = true,
580 [65088] = true,
581 [65087] = true,
582 [63684] = true,
583 [63683] = true,
584 [63682] = true,
585 [51320] = true,
586 [45652] = true,
587 [45651] = true,
588 [45650] = true,
589 [45649] = true,
590 [45648] = true,
591 [45647] = true,
592 [45643] = true,
593 [45642] = true,
594 [45641] = true,
595 [40630] = true,
596 [40629] = true,
597 [40628] = true,
598 [40621] = true,
599 [40620] = true,
600 [40619] = true,
601 [40618] = true,
602 [40617] = true,
603 [40616] = true,
604 [34544] = true,
605 [31100] = true,
606 [31099] = true,
607 [31098] = true,
608 [31097] = true,
609 [31096] = true,
610 [31095] = true,
611 [30247] = true,
612 [30246] = true,
613 [30245] = true,
614 [30244] = true,
615 [30243] = true,
616 [30242] = true,
617 [29767] = true,
618 [29766] = true,
619 [29765] = true,
620 [29761] = true,
621 [29760] = true,
622 [29759] = true
623 }
624
625 169
626 ---------------------------------------------------------------------------------------- 170 ----------------------------------------------------------------------------------------
627 -- Public Utility Methods 171 -- Public Utility Methods
628 ---------------------------------------------------------------------------------------- 172 ----------------------------------------------------------------------------------------
629 173
630 local function readBonusIdList(parts, first, last) 174 local function readBonusIdList(parts, first, last)
631 local ret = {} 175 local ret = {}
632 for i = first, last do 176 for i = first, last do
633 table.insert(ret, tonumber(parts[i])) 177 table.insert(ret, tonumber(parts[i]))
634 end 178 end
635 table.sort(ret) 179 table.sort(ret)
636 return ret 180 return ret
637 end 181 end
638 182
639 local function setRelicId(item, index, relicBonuses) 183 -- 1 2 3 4 5 6 7 8 9 10 11 12
640 local relicId = item.gemIds[index] .. "" 184 -- itemId:ench:gem1 :gem2 :gem3 :gem4:suf:uid:lvl:spec:flags :instdiffid:numbonusIDs:bonusIDs1...n :varies:?:relic bonus ids
641 for i = 1, #relicBonuses do 185 --|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
642 relicId = relicId .. "." .. relicBonuses[i] 186 --
643 end
644 local list = item.gemItemIds or {}
645 list[i] = relicId
646 end
647
648 --|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]
649 -- 133004 for relic on my warrior, gem2
650 -- 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
651
652 --|cffa335ee|Hitem:itemID:enchant:gem1:gem2:gem3:gem4:suffixID:uniqueID:level:unknown:unknown:instanceDifficultyID:numBonusIDs:bonusID1:bonusID2...|h[item name]|h|r
653
654 -- 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
655 -- get an object with all of the parts of the item link format that we care about 187 -- get an object with all of the parts of the item link format that we care about
656 function Amr.ParseItemLink(itemLink) 188 function Amr.ParseItemLink(itemLink)
657 if not itemLink then return nil end 189 if not itemLink then return nil end
658 190
659 local str = string.match(itemLink, "|Hitem:([\-%d:]+)|") 191 local str = string.match(itemLink, "|Hitem:([\-%d:]+)|")
660 if not str then return nil end 192 if not str then return nil end
661 193
662 local parts = { strsplit(":", str) } 194 local parts = { strsplit(":", str) }
663 195
664 local item = {} 196 local item = {}
197 item.link = itemLink
665 item.id = tonumber(parts[1]) or 0 198 item.id = tonumber(parts[1]) or 0
666 item.enchantId = tonumber(parts[2]) or 0 199 item.enchantId = tonumber(parts[2]) or 0
667 item.gemIds = { tonumber(parts[3]) or 0, tonumber(parts[4]) or 0, tonumber(parts[5]) or 0, tonumber(parts[6]) or 0 } 200 item.gemIds = { tonumber(parts[3]) or 0, tonumber(parts[4]) or 0, tonumber(parts[5]) or 0, tonumber(parts[6]) or 0 }
668 item.suffixId = math.abs(tonumber(parts[7]) or 0) -- convert suffix to positive number, that's what we use in our code 201 item.suffixId = math.abs(tonumber(parts[7]) or 0) -- convert suffix to positive number, that's what we use in our code
669 -- part 8 is some unique ID... we never really used it 202 -- part 8 is some unique ID... we never really used it
679 end 212 end
680 213
681 item.upgradeId = 0 214 item.upgradeId = 0
682 item.level = 0 215 item.level = 0
683 216
684 -- 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 217 -- the next part after bonus IDs depends on the upgrade id type
685 if upgradeIdType == 4 then 218 if upgradeIdType == 4 then
686 item.upgradeId = tonumber(parts[14 + offset]) or 0 219 item.upgradeId = tonumber(parts[14 + offset]) or 0
687 elseif upgradeIdType == 512 then 220 elseif upgradeIdType == 512 then
688 item.level = tonumber(parts[14 + offset]) or 0 221 item.level = tonumber(parts[14 + offset]) or 0
689 end 222 elseif #parts > 16 + offset then
690 223 -- check for relic info
691 -- ignore relic stuff in the item link for now, we read the relic information directly and save it with artifact power info 224 item.relicBonusIds = { nil, nil, nil }
692 --[[ 225 numBonuses = tonumber(parts[16 + offset])
693 -- the next part is the number of bonus IDs on the first relic slot of the artifact 226 if numBonuses then
694 numBonuses = tonumber(parts[15 + offset]) or 0 227 if numBonuses > 0 then
695 if numBonuses > 0 then 228 item.relicBonusIds[1] = readBonusIdList(parts, 17 + offset, 16 + offset + numBonuses)
696 local relicBonuses = readBonusIdList(16 + offset, 15 + offset + numBonuses, parts) 229 end
697 setRelicId(item, 1, relicBonuses) 230
698 end 231 offset= offset + numBonuses
699 232 if #parts > 17 + offset then
700 -- second relic slot bonus IDs 233 numBonuses = tonumber(parts[17 + offset])
701 offset = offset + numBonuses 234 if numBonuses > 0 then
702 numBonuses = tonumber(parts[16 + offset]) or 0 235 item.relicBonusIds[2] = readBonusIdList(parts, 18 + offset, 17 + offset + numBonuses)
703 if numBonuses > 0 then 236 end
704 local relicBonuses = readBonusIdList(17 + offset, 16 + offset + numBonuses, parts) 237
705 setRelicId(item, 2, relicBonuses) 238 offset= offset + numBonuses
706 end 239 if #parts > 18 + offset then
707 240 numBonuses = tonumber(parts[18 + offset])
708 -- third relic slot bonus IDs 241 if numBonuses > 0 then
709 offset = offset + numBonuses 242 item.relicBonusIds[3] = readBonusIdList(parts, 19 + offset, 18 + offset + numBonuses)
710 numBonuses = tonumber(parts[17 + offset]) or 0 243 end
711 if numBonuses > 0 then 244 end
712 local relicBonuses = readBonusIdList(18 + offset, 17 + offset + numBonuses, parts) 245 end
713 setRelicId(item, 3, relicBonuses) 246 end
714 end 247 end
715 ]]
716 248
717 return item 249 return item
718 end 250 end
719 251
720 function Amr.GetItemUniqueId(item, noUpgrade) 252 function Amr.GetItemUniqueId(item, noUpgrade)
799 tt:SetHyperlink(link) 331 tt:SetHyperlink(link)
800 end 332 end
801 return tt 333 return tt
802 end 334 end
803 335
804 function Amr.GetItemLevel(bagId, slotId, link) 336 function Amr.GetItemLevel(bagId, slotId, link)
805 local itemLevelPattern = _G["ITEM_LEVEL"]:gsub("%%d", "(%%d+)") 337 local itemLevelPattern = _G["ITEM_LEVEL"]:gsub("%%d", "(%%d+)")
806 local tt = Amr.GetItemTooltip(bagId, slotId, link) 338 local tt = Amr.GetItemTooltip(bagId, slotId, link)
807 339
808 local regions = { tt:GetRegions() } 340 local regions = { tt:GetRegions() }
809 for i, region in ipairs(regions) do 341 for i, region in ipairs(regions) do
834 ret.Professions[Amr.ProfessionSkillLineToName[skillLine]] = skillLevel; 366 ret.Professions[Amr.ProfessionSkillLineToName[skillLine]] = skillLevel;
835 end 367 end
836 end 368 end
837 end 369 end
838 370
839 --[[ 371 -- get specs
840 local function getTalents(specPos)
841 local talentInfo = {}
842 local maxTiers = 7
843 for tier = 1, maxTiers do
844 for col = 1, 3 do
845 local id, name, _, _, _, spellId, _, t, c, selected = GetTalentInfoBySpecialization(specPos, tier, col)
846 if selected then
847 talentInfo[tier] = col
848 end
849 end
850 end
851
852 local str = ""
853 for i = 1, maxTiers do
854 if talentInfo[i] then
855 str = str .. talentInfo[i]
856 else
857 str = str .. '0'
858 end
859 end
860
861 return str
862 end
863 ]]
864
865 --[[
866 local function getGlyphs(specGroup)
867 local glyphs = {}
868 for i = 1, NUM_GLYPH_SLOTS do
869 local _, _, _, glyphSpellID, _, glyphID = GetGlyphSocketInfo(i, specGroup)
870 if (glyphID) then
871 table.insert(glyphs, glyphSpellID)
872 end
873 end
874 return glyphs;
875 end
876 ]]
877
878 -- get specs and talents
879 local function readSpecs(ret) 372 local function readSpecs(ret)
880 373
881 for pos = 1, 4 do 374 for pos = 1, 4 do
882 -- spec, convert game spec id to one of our spec ids 375 -- spec, convert game spec id to one of our spec ids
883 local specId = GetSpecializationInfo(pos) 376 local specId = GetSpecializationInfo(pos)
884 if specId then 377 if specId then
885 ret.Specs[pos] = Amr.SpecIds[specId] 378 ret.Specs[pos] = Amr.SpecIds[specId]
886 -- TODO: figure out how to read inactive spec talents if possible... used to be able to but they changed it
887 --ret.Talents[pos] = getTalents(pos)
888 end 379 end
380 end
381 end
382
383 local function dump(o)
384 if type(o) == 'table' then
385 local s = '{ '
386 for k,v in pairs(o) do
387 if type(k) ~= 'number' then k = '"'..k..'"' end
388 s = s .. '['..k..'] = ' .. dump(v) .. ','
389 end
390 return s .. '} '
391 else
392 return tostring(o)
393 end
394 end
395
396 -- read azerite powers on the item in loc and put it on itemData
397 function Amr.ReadAzeritePowers(loc)
398 local ret = {}
399 local hasSome = false
400
401 local tiers = C_AzeriteEmpoweredItem.GetAllTierInfo(loc)
402 for tier, tierInfo in ipairs(tiers) do
403 for _, power in ipairs(tierInfo.azeritePowerIDs) do
404 if C_AzeriteEmpoweredItem.IsPowerSelected(loc, power) then
405 local powerInfo = C_AzeriteEmpoweredItem.GetPowerInfo(power)
406 table.insert(ret, powerInfo.spellID)
407 hasSome = true
408 end
409 end
410 end
411
412 if hasSome then
413 return ret
414 else
415 return nil
889 end 416 end
890 end 417 end
891 418
892 -- get currently equipped items, store with currently active spec 419 -- get currently equipped items, store with currently active spec
893 local function readEquippedItems(ret) 420 local function readEquippedItems(ret)
894 local equippedItems = {}; 421 local equippedItems = {};
422 local loc = ItemLocation.CreateEmpty()
895 for slotNum = 1, #Amr.SlotIds do 423 for slotNum = 1, #Amr.SlotIds do
896 local slotId = Amr.SlotIds[slotNum] 424 local slotId = Amr.SlotIds[slotNum]
897 local itemLink = GetInventoryItemLink("player", slotId) 425 local itemLink = GetInventoryItemLink("player", slotId)
898 if itemLink then 426 if itemLink then
899 equippedItems[slotId] = itemLink 427 local itemData = Amr.ParseItemLink(itemLink)
428 if itemData then
429 -- see if this is an azerite item and read azerite power ids
430 loc:SetEquipmentSlot(slotId)
431 if C_AzeriteEmpoweredItem.IsAzeriteEmpoweredItem(loc) then
432 local powers = Amr.ReadAzeritePowers(loc)
433 if powers then
434 itemData.azerite = powers
435 end
436 end
437
438 equippedItems[slotId] = itemData
439 end
900 end 440 end
901 end 441 end
902 442
903 -- store last-seen equipped gear for each spec 443 -- store last-seen equipped gear for each spec
904 ret.Equipped[GetSpecialization()] = equippedItems 444 ret.Equipped[GetSpecialization()] = equippedItems
445 end
446
447 local function readHeartOfAzerothLevel(ret)
448 local azeriteItemLocation = C_AzeriteItem.FindActiveAzeriteItem();
449 if azeriteItemLocation then
450 local azeriteItem = Item:CreateFromItemLocation(azeriteItemLocation);
451 ret.HeartOfAzerothLevel = C_AzeriteItem.GetPowerLevel(azeriteItemLocation)
452 else
453 ret.HeartOfAzerothLevel = 0
454 end
455 end
456
457 -- Get just the player's currently equipped gear
458 function Amr:GetEquipped()
459 local ret= {}
460 ret.Equipped = {}
461 readEquippedItems(ret)
462 return ret
905 end 463 end
906 464
907 -- Get all data about the player as an object, includes: 465 -- Get all data about the player as an object, includes:
908 -- serializer version 466 -- serializer version
909 -- region/realm/name 467 -- region/realm/name
911 -- race 469 -- race
912 -- faction 470 -- faction
913 -- level 471 -- level
914 -- professions 472 -- professions
915 -- spec/talent for all specs 473 -- spec/talent for all specs
916 -- artifact for current spec
917 -- equipped gear for the current spec 474 -- equipped gear for the current spec
918 -- 475 --
919 function Amr:GetPlayerData() 476 function Amr:GetPlayerData()
920 477
921 local ret = {} 478 local ret = {}
924 ret.Realm = GetRealmName() 481 ret.Realm = GetRealmName()
925 ret.Name = UnitName("player") 482 ret.Name = UnitName("player")
926 ret.Guild = GetGuildInfo("player") 483 ret.Guild = GetGuildInfo("player")
927 ret.ActiveSpec = GetSpecialization() 484 ret.ActiveSpec = GetSpecialization()
928 ret.Level = UnitLevel("player"); 485 ret.Level = UnitLevel("player");
929 486 readHeartOfAzerothLevel(ret)
487
930 local cls, clsEn = UnitClass("player") 488 local cls, clsEn = UnitClass("player")
931 ret.Class = clsEn; 489 ret.Class = clsEn;
932 490
933 local race, raceEn = UnitRace("player") 491 local race, raceEn = UnitRace("player")
934 ret.Race = raceEn; 492 ret.Race = raceEn;
945 503
946 ret.Specs = {} 504 ret.Specs = {}
947 ret.Talents = {} 505 ret.Talents = {}
948 readSpecs(ret) 506 readSpecs(ret)
949 507
950 ret.Artifacts = {} 508 ret.Equipped = {}
951
952 ret.Equipped = {}
953 readEquippedItems(ret) 509 readEquippedItems(ret)
954 510
955 return ret 511 return ret
956 end 512 end
957 513
995 local prevGemId = 0 551 local prevGemId = 0
996 local prevEnchantId = 0 552 local prevEnchantId = 0
997 local prevUpgradeId = 0 553 local prevUpgradeId = 0
998 local prevBonusId = 0 554 local prevBonusId = 0
999 local prevLevel = 0 555 local prevLevel = 0
556 local prevAzeriteId = 0
557 local prevRelicBonusId = 0
1000 for i, itemData in ipairs(itemObjects) do 558 for i, itemData in ipairs(itemObjects) do
1001 local itemParts = {} 559 local itemParts = {}
1002 560
1003 -- 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
1004 --local _, _, quality = GetItemInfo(itemData.link)
1005 --if quality == 6 then
1006 -- itemData.level = Amr.GetItemLevel(nil, nil, itemData.link)
1007 --end
1008
1009 table.insert(itemParts, itemData.id - prevItemId) 561 table.insert(itemParts, itemData.id - prevItemId)
1010 prevItemId = itemData.id 562 prevItemId = itemData.id
1011 563
1012 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end 564 if itemData.slot ~= nil then table.insert(itemParts, "s" .. itemData.slot) end
1013 if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end 565 --if itemData.suffixId ~= 0 then table.insert(itemParts, "f" .. itemData.suffixId) end
1014 if itemData.upgradeId ~= 0 then 566 if itemData.upgradeId ~= 0 then
1015 table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId)) 567 table.insert(itemParts, "u" .. (itemData.upgradeId - prevUpgradeId))
1016 prevUpgradeId = itemData.upgradeId 568 prevUpgradeId = itemData.upgradeId
1017 end 569 end
1018 if itemData.level ~= 0 then 570 if itemData.level ~= 0 then
1022 if itemData.bonusIds then 574 if itemData.bonusIds then
1023 for bIndex, bValue in ipairs(itemData.bonusIds) do 575 for bIndex, bValue in ipairs(itemData.bonusIds) do
1024 table.insert(itemParts, "b" .. (bValue - prevBonusId)) 576 table.insert(itemParts, "b" .. (bValue - prevBonusId))
1025 prevBonusId = bValue 577 prevBonusId = bValue
1026 end 578 end
1027 end 579 end
580
581 if itemData.azerite then
582 for aIndex, aValue in ipairs(itemData.azerite) do
583 table.insert(itemParts, "a" .. (aValue - prevAzeriteId))
584 prevAzeriteId = aValue
585 end
586 end
1028 587
1029 if itemData.gemIds[1] ~= 0 then 588 if itemData.gemIds[1] ~= 0 then
1030 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId)) 589 table.insert(itemParts, "x" .. (itemData.gemIds[1] - prevGemId))
1031 prevGemId = itemData.gemIds[1] 590 prevGemId = itemData.gemIds[1]
1032 end 591 end
1035 prevGemId = itemData.gemIds[2] 594 prevGemId = itemData.gemIds[2]
1036 end 595 end
1037 if itemData.gemIds[3] ~= 0 then 596 if itemData.gemIds[3] ~= 0 then
1038 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId)) 597 table.insert(itemParts, "z" .. (itemData.gemIds[3] - prevGemId))
1039 prevGemId = itemData.gemIds[3] 598 prevGemId = itemData.gemIds[3]
1040 end 599 end
1041 600
1042 if itemData.enchantId ~= 0 then 601 if itemData.enchantId ~= 0 then
1043 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId)) 602 table.insert(itemParts, "e" .. (itemData.enchantId - prevEnchantId))
1044 prevEnchantId = itemData.enchantId 603 prevEnchantId = itemData.enchantId
1045 end 604 end
1046 605
606 if itemData.relicBonusIds and itemData.relicBonusIds[1] ~= nil then
607 for bIndex, bValue in ipairs(itemData.relicBonusIds[1]) do
608 table.insert(itemParts, "p" .. (bValue - prevRelicBonusId))
609 prevRelicBonusId = bValue
610 end
611 end
612
613 if itemData.relicBonusIds and itemData.relicBonusIds[2] ~= nil then
614 for bIndex, bValue in ipairs(itemData.relicBonusIds[2]) do
615 table.insert(itemParts, "q" .. (bValue - prevRelicBonusId))
616 prevRelicBonusId = bValue
617 end
618 end
619
620 if itemData.relicBonusIds and itemData.relicBonusIds[3] ~= nil then
621 for bIndex, bValue in ipairs(itemData.relicBonusIds[3]) do
622 table.insert(itemParts, "r" .. (bValue - prevRelicBonusId))
623 prevRelicBonusId = bValue
624 end
625 end
626
1047 table.insert(fields, table.concat(itemParts, "")) 627 table.insert(fields, table.concat(itemParts, ""))
1048 end 628 end
1049 end
1050
1051 local function serializeCrucibleInfo(fields, info, pos, prevPowerId)
1052
1053 if not info.Powers or not info.Active then
1054 return prevPowerId
1055 end
1056
1057 local parts = {}
1058
1059 if pos < 4 then
1060 table.insert(parts, pos)
1061 else
1062 local relic = Amr.ParseItemLink(info.ItemLink)
1063 table.insert(parts, Amr.GetItemUniqueId(relic) or "0")
1064 end
1065
1066 for i,powerId in ipairs(info.Powers) do
1067 table.insert(parts, (powerId - prevPowerId) .. "")
1068 prevPowerId = powerId
1069 end
1070
1071 for i,active in ipairs(info.Active) do
1072 table.insert(parts, active and "1" or "0")
1073 end
1074
1075 table.insert(fields, table.concat(parts, ","))
1076
1077 return prevPowerId
1078 end 629 end
1079 630
1080 -- Serialize just the identity portion of a player (region/realm/name) in the same format used by the full serialization 631 -- Serialize just the identity portion of a player (region/realm/name) in the same format used by the full serialization
1081 function Amr:SerializePlayerIdentity(data) 632 function Amr:SerializePlayerIdentity(data)
1082 local fields = {} 633 local fields = {}
1119 -- faction, default to alliance if we can't read it for some reason 670 -- faction, default to alliance if we can't read it for some reason
1120 raceval = Amr.FactionIds[data.Faction] 671 raceval = Amr.FactionIds[data.Faction]
1121 if raceval == nil then raceval = 1 end 672 if raceval == nil then raceval = 1 end
1122 table.insert(fields, raceval) 673 table.insert(fields, raceval)
1123 674
1124 table.insert(fields, data.Level) 675 table.insert(fields, data.Level)
676 table.insert(fields, data.HeartOfAzerothLevel)
1125 677
1126 local profs = {} 678 local profs = {}
1127 local noprofs = true 679 local noprofs = true
1128 if data.Professions then 680 if data.Professions then
1129 for k, v in pairs(data.Professions) do 681 for k, v in pairs(data.Professions) do
1145 table.insert(fields, data.ActiveSpec) 697 table.insert(fields, data.ActiveSpec)
1146 for spec = 1, 4 do 698 for spec = 1, 4 do
1147 if data.Specs[spec] and (complete or spec == data.ActiveSpec) then 699 if data.Specs[spec] and (complete or spec == data.ActiveSpec) then
1148 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block 700 table.insert(fields, ".s" .. spec) -- indicates the start of a spec block
1149 table.insert(fields, data.Specs[spec]) 701 table.insert(fields, data.Specs[spec])
1150 table.insert(fields, data.Talents[spec] or "") 702 table.insert(fields, data.Talents[spec] or "")
1151
1152 local powerids = {}
1153 local powerranks = {}
1154 local reliclinks = {}
1155 local crucibleinfos = {}
1156
1157 local artifactInfo = data.Artifacts and data.Artifacts[spec]
1158 if artifactInfo and artifactInfo.Powers then
1159 for k, v in spairs(artifactInfo.Powers) do
1160 table.insert(powerids, k)
1161 table.insert(powerranks, v)
1162 end
1163 end
1164 if artifactInfo and artifactInfo.Relics then
1165 for i, link in ipairs(artifactInfo.Relics) do
1166 local relic = Amr.ParseItemLink(link)
1167 table.insert(reliclinks, Amr.GetItemUniqueId(relic) or "")
1168 end
1169 end
1170 if artifactInfo and artifactInfo.Crucible then
1171 local prevPowerId = 0
1172 for i = 1,3 do
1173 local relicInfo = #artifactInfo.Crucible.Equipped >= i and artifactInfo.Crucible.Equipped[i]
1174 if relicInfo then
1175 prevPowerId = serializeCrucibleInfo(crucibleinfos, relicInfo, i, prevPowerId)
1176 end
1177 end
1178 if artifactInfo.Crucible.Previewed then
1179 for k,relicInfo in pairs(artifactInfo.Crucible.Previewed) do
1180 if relicInfo then
1181 prevPowerId = serializeCrucibleInfo(crucibleinfos, relicInfo, 4, prevPowerId)
1182 end
1183 end
1184 end
1185 end
1186
1187 table.insert(fields, toCompressedNumberList(powerids))
1188 table.insert(fields, table.concat(powerranks, ","))
1189 table.insert(fields, table.concat(reliclinks, ","))
1190 table.insert(fields, table.concat(crucibleinfos, "/"))
1191
1192 --table.insert(fields, toCompressedNumberList(data.Glyphs[spec]))
1193 end 703 end
1194 end 704 end
1195 705
1196 -- export equipped gear 706 -- export equipped gear
1197 if data.Equipped then 707 if data.Equipped then
1198 for spec = 1, 4 do 708 for spec = 1, 4 do
1199 if data.Equipped[spec] and (complete or spec == data.ActiveSpec) then 709 if data.Equipped[spec] and (complete or spec == data.ActiveSpec) then
1200 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block 710 table.insert(fields, ".q" .. spec) -- indicates the start of an equipped gear block
1201 711
1202 local itemObjects = {} 712 local itemObjects = {}
1203 for k, v in pairs(data.Equipped[spec]) do 713 for k, itemData in pairs(data.Equipped[spec]) do
1204 local itemData = Amr.ParseItemLink(v)
1205 itemData.slot = k 714 itemData.slot = k
1206 itemData.link = v
1207 table.insert(itemObjects, itemData) 715 table.insert(itemObjects, itemData)
1208 end 716 end
1209 717
1210 appendItemsToExport(fields, itemObjects) 718 appendItemsToExport(fields, itemObjects)
1211 end 719 end
1212 end 720 end
1213 end 721 end
1214 722
1215 -- if doing a complete export, include reputations and bank/bag items too 723 -- if doing a complete export, include bank/bag items too
1216 if complete then 724 if complete then
1217 725
1218 -- export reputations
1219 local reps = {}
1220 table.insert(reps, "_")
1221 --[[
1222 local noreps = true
1223 if data.Reputations then
1224 for k, v in pairs(data.Reputations) do
1225 noreps = false
1226 table.insert(reps, k .. ":" .. v)
1227 end
1228 end
1229 if noreps then
1230 table.insert(reps, "_")
1231 end
1232 ]]
1233
1234 table.insert(fields, ".r")
1235 table.insert(fields, table.concat(reps, ","))
1236
1237 -- export bag and bank
1238 local itemObjects = {} 726 local itemObjects = {}
1239 if data.BagItems then 727 if data.BagItems then
1240 for i, v in ipairs(data.BagItems) do 728 for i, itemData in ipairs(data.BagItems) do
1241 local itemData = Amr.ParseItemLink(v) 729 if itemData then
1242 if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then
1243 itemData.link = v
1244 table.insert(itemObjects, itemData) 730 table.insert(itemObjects, itemData)
1245 end 731 end
1246 end 732 end
1247 end 733 end
1248 if data.BankItems then 734 if data.BankItems then
1249 for i, v in ipairs(data.BankItems) do 735 for i, itemData in ipairs(data.BankItems) do
1250 local itemData = Amr.ParseItemLink(v) 736 if itemData then
1251 if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then
1252 itemData.link = v
1253 table.insert(itemObjects, itemData) 737 table.insert(itemObjects, itemData)
1254 end 738 end
1255 end 739 end
1256 end 740 end
1257 if data.VoidItems then 741
1258 for i, v in ipairs(data.VoidItems) do
1259 local itemData = Amr.ParseItemLink(v)
1260 if itemData ~= nil --[[and (IsEquippableItem(v) or Amr.SetTokenIds[itemData.id])]] then
1261 itemData.link = v
1262 table.insert(itemObjects, itemData)
1263 end
1264 end
1265 end
1266
1267 table.insert(fields, ".inv") 742 table.insert(fields, ".inv")
1268 appendItemsToExport(fields, itemObjects) 743 appendItemsToExport(fields, itemObjects)
1269 end 744 end
1270 745
1271 return "$" .. table.concat(fields, ";") .. "$" 746 return "$" .. table.concat(fields, ";") .. "$"