-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathiKeystones.lua
2034 lines (1972 loc) · 70.4 KB
/
iKeystones.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
--upvalues
local _sformat, GetQuestObjectiveInfo, IsQuestFlaggedCompleted, _sgsub, _sgmatch, _smatch, _slower, SendChatMessage, _SendAddonMessage = string.format, GetQuestObjectiveInfo, C_QuestLog.IsQuestFlaggedCompleted, string.gsub, string.gmatch, string.match, string.lower, SendChatMessage, C_ChatInfo.SendAddonMessage
local vaultThresholds = {
{1,4,8},
{1250,2500,5500},
{2,5,8},
}
local isLegitServer = false
local addon = CreateFrame('Frame');
addon:SetScript("OnEvent", function(self, event, ...)
self[event](self, ...)
end)
addon:RegisterEvent('ADDON_LOADED')
addon:RegisterEvent('PLAYER_LOGIN')
addon:RegisterEvent('CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN')
addon:RegisterEvent('MYTHIC_PLUS_CURRENT_AFFIX_UPDATE')
addon:RegisterEvent('ITEM_PUSH')
addon:RegisterEvent('BAG_UPDATE')
addon:RegisterEvent('QUEST_LOG_UPDATE')
addon:RegisterEvent('CHAT_MSG_ADDON')
addon:RegisterEvent("WEEKLY_REWARDS_UPDATE")
C_ChatInfo.RegisterAddonMessagePrefix('iKeystones')
--C_ChatInfo.RegisterAddonMessagePrefix('AstralKeys') -- AstralKeys guild support
addon:RegisterEvent('CHAT_MSG_PARTY')
addon:RegisterEvent('CHAT_MSG_PARTY_LEADER')
addon:RegisterEvent('CHALLENGE_MODE_COMPLETED')
addon:RegisterEvent('ENCOUNTER_END')
addon:RegisterEvent('WEEKLY_REWARDS_HIDE')
addon:RegisterEvent('ITEM_CHANGED')
local iKS = {}
iKS.currentMax = 0
iKS.frames = {}
local shouldBeCorrectInfoForWeekly = false
local player = UnitGUID('player')
local unitName = UnitName('player')
local playerFaction = UnitFactionGroup('player')
local font = GameFontNormal:GetFont()
local currentMaxLevel = 60
-- popup for loading the first time
StaticPopupDialogs["IKS_MIDWEEKFIRSTLOAD"] = {
text = "You are logging in for the first time on this character, iKeystones might have incorrect data for the first reset.\r (missing runs and/or raid kills)",
button1 = OKAY,
hideOnEscape = true,
}
function iKS:ShowTooltip(str)
GameTooltip:SetOwner(iKeystonesWindowAnchor, "ANCHOR_NONE")
GameTooltip:SetPoint("TOPLEFT", iKeystonesWindowAnchor, "TOPRIGHT", 0, 0)
GameTooltip:ClearLines()
GameTooltip:SetText(str)
GameTooltip:Show()
end
iKS.keystonesToMapIDs = {
--[[
[197] = 1456, -- Eye of Azhara
[198] = 1466, -- Darkhearth Thicket
[199] = 1501, -- Blackrook Hold
[200] = 1477, -- Halls of Valor
[206] = 1458, -- Neltharion's Lair
[207] = 1493, -- Vault of the Wardens
[208] = 1492, -- Maw of Souls
[209] = 1516, -- The Arcway
[210] = 1571, -- Court of Stars
[227] = 1651, -- Return to Karazhan: Lower
[233] = 1677, -- Cathedral of Eternal Night
[234] = 1651, -- Return to Karazhan: Upper
[239] = 1753, -- The Seat of the Triumvirate
[244] = 1763, -- Atal'Dazar
[245] = 1754, -- Freehold
[246] = 1771, -- Tol Dagor
[247] = 1594, -- The Motherlode
[248] = 1862, -- Waycrest Manor
[249] = 1762, -- King's Rest
[250] = 1877, -- Temple of Sethraliss
[251] = 1841, -- The Underrot
[252] = 1864, -- Shrine of the Storm
[353] = 1822, -- Siege of Boralus
[369] = 2097, -- Operation Mechagon - Junkyard
[370] = 2097, -- Operation Mechagon - Workshop
--]]
[375] = 2290, -- Mists of Tirna Scithe
[376] = 2286, -- The Necrotic Wake
[377] = 2291, -- De Other Side
[378] = 2287, -- Halls of Atonement
[379] = 2289, -- Plaguefall
[380] = 2284, -- Sanguine Depths
[381] = 2285, -- Spires of Ascension
[382] = 2293, -- Theater of Pain
[391] = 2441, -- Tazavesh: Streets of Wonder
[392] = 2441, -- Tazavesh: So'leah's Gambit
}
iKS.IsleQuests = {
['Horde'] = 53435,
['Alliance'] = 53436,
}
iKS.currentAffixes = {0,0,0,0}
local sortedAffixes = {
[10] = 1, --Fortified
[9] = 1, --Tyrannical
[7] = 2, --Bolstering
[6] = 2, --Raging
[8] = 2, --Sanguine
[5] = 2, --Teeming
[11] = 2, --Bursting
[122] = 2, -- Inspiring
[123] = 2, -- Spiteful
[4] = 3, --Necrotic
[2] = 3, --Skittish
[3] = 3, --Volcanic
[13] = 3, --Explosive
[14] = 3, --Quaking
[12] = 3, --Grievous
[124] = 3, -- Storming
--[15] = ?, --Relentless
[16] = 4, --Infested, BFA S1
[117] = 4, --Reaping, BFA S2
[119] = 4, -- Beguiling, BFA S3
[120] = 4, -- Awekened, BFA S4
[121] = 4, -- Prideful, SL S1
[128] = 4, -- Tormented SL S2
[130] = 4, -- Encrypted SL S3
[131] = 4, -- Shrouded SL S4
}
do
local affixIDS = {
FORTIFIED = 10,
TYRANNICAL = 9,
BOLSTERING = 7,
RAGING = 6,
SANGUINE = 8,
TEEMING = 5,
BURSTING = 11,
INSPIRING = 122,
SPITEFUL = 123,
NECROTIC = 4,
SKITTISH = 2,
VOLCANIC = 3,
EXPLOSIVE = 13,
QUAKING = 14,
GRIEVOUS = 12,
STORMING = 124,
}
iKS.affixCycles = {
{affixIDS.FORTIFIED, affixIDS.BURSTING, affixIDS.STORMING},
{affixIDS.TYRANNICAL, affixIDS.RAGING, affixIDS.VOLCANIC},
{affixIDS.FORTIFIED, affixIDS.INSPIRING, affixIDS.GRIEVOUS},
{affixIDS.TYRANNICAL, affixIDS.SPITEFUL, affixIDS.NECROTIC},
{affixIDS.FORTIFIED, affixIDS.BOLSTERING, affixIDS.QUAKING},
{affixIDS.TYRANNICAL,affixIDS.SANGUINE, affixIDS.STORMING},
{affixIDS.FORTIFIED, affixIDS.RAGING, affixIDS.EXPLOSIVE},
{affixIDS.TYRANNICAL, affixIDS.BURSTING, affixIDS.VOLCANIC},
{affixIDS.FORTIFIED, affixIDS.SPITEFUL, affixIDS.GRIEVOUS},
{affixIDS.TYRANNICAL, affixIDS.INSPIRING, affixIDS.QUAKING},
{affixIDS.FORTIFIED, affixIDS.SANGUINE, affixIDS.NECROTIC},
{affixIDS.TYRANNICAL, affixIDS.BOLSTERING, affixIDS.EXPLOSIVE},
}
end
--C_MythicPlus.GetLastWeeklyBestInformation();
--[[
2 = 1000
3 = 1050
4 = 1100
5 = 1150
6 = 1200,
7 = 1250,
8 = 1300,
9 = 1350,
10 = 1400,
]]
local function spairs(t, order)
-- collect the keys
local keys = {}
for k in pairs(t) do keys[#keys+1] = k end
-- if order function given, sort by it by passing the table and keys a, b,
-- otherwise just sort the keys
if order then
table.sort(keys, function(a,b) return order(t, a, b) end)
else
table.sort(keys)
end
-- return the iterator function
local i = 0
return function()
i = i + 1
if keys[i] then
return keys[i], t[keys[i]]
end
end
end
function iKS:weeklyReset()
for guid,data in pairs(iKeystonesDB) do
if data.PvP.progress > vaultThresholds[2][1] then
data.canLoot = true
end
if not data.canLoot and data.raidHistory then
local c = 0
for difID,v in pairs(data.raidHistory) do
for k in pairs(v) do
c = c + 1
end
end
if c >= vaultThresholds[3][1] then
data.canLoot = true
end
end
if not data.canLoot and data.runHistory then
local c = 0
for k,v in pairs(data.runHistory) do
c = c + v
end
if c >= vaultThresholds[1][1] then
data.canLoot = true
end
end
data.raidHistory = {}
data.runHistory = {}
data.torghast = {}
data.key = {}
data.PvP = {progress = 0, level = 0}
end
iKS:scanInventory()
iKS:scanCharacterMaps()
end
do -- Torghast
--64347 conduit?
--[[
local questIDs = {
{58198, 58199, 58200, 58201, 58202, 58203, 61975, 61976, 63880, 63881, 63882, 63883}, -- Coldhearth Insignia
{58186, 58187, 58188, 58189, 58190, 58191, 61971, 61972, 63872, 63873, 63874, 63875}, -- Fracture Chambers
{58205, 58205, 59326, 59334, 59335, 59336, 61977, 61978, 63884, 63885, 63886, 63887}, -- Mort'regar
{58192, 58193, 58194, 58195, 58196, 58197, 61973, 61974, 63876, 63877, 63878, 63879}, -- The Soulforges
{59337, 61101, 61131, 61132, 61133, 61134, 61979, 61980, 63888, 63889, 63890, 63891}, -- Upper Reaches
{59328, 59329, 59330, 59331, 59332, 59333, 61969, 61970, 63868, 63869, 63870, 63871}, -- Skoldus Hall
}
--]]
-- Only check if conduit weekly quest is done
function iKS:checkTorghast()
if not iKS:createPlayer() then return end
iKeystonesDB[player].torghast = IsQuestFlaggedCompleted(64347) and 1 or 0
--[[
for zone, questIDs in pairs(questIDs) do
local count = 0
for _, id in pairs(questIDs) do
if IsQuestFlaggedCompleted(id) then
count = count + 1
end
end
if count > 0 then
iKeystonesDB[player].torghast[zone] = count
end
end
--]]
end
end
function iKS:createPlayer(login)
if not isLegitServer then return false end
if player and not iKeystonesDB[player] then
if UnitLevel('player') >= currentMaxLevel and not iKeystonesConfig.ignoreList[player] then
iKeystonesDB[player] = {
name = UnitName('player'),
server = GetRealmName(),
class = select(2, UnitClass('player')),
key = {},
canLoot = C_WeeklyRewards.HasAvailableRewards(),
faction = UnitFactionGroup('player'),
PvP = {progress = 0, level = 0},
torghast = 0,
runHistory = {},
}
iKS:scanCharacterMaps(true)
return true
else
return false
end
elseif player and UnitLevel('player') < currentMaxLevel and iKeystonesDB[player] then
iKeystonesDB[player] = nil
return false
elseif player and iKeystonesDB[player] then
if login then
iKeystonesDB[player].name = UnitName('player') -- fix for name changing
iKeystonesDB[player].faction = UnitFactionGroup('player') -- faction change (tbh i think guid would change) and update old DB
end
return true
else
return false
end
end
--C_MythicPlus.RequestCurrentAffixes();
--C_MythicPlus.RequestMapInfo();
--C_MythicPlus.RequestRewards();
--for i = 1, #self.maps do
-- C_ChallengeMode.RequestLeaders(self.maps[i]);
--end
local validDungeons
local function IsValidDungeon(dungeonID)
dungeonID = tonumber(dungeonID)
if not dungeonID then return end
if not validDungeons then
validDungeons = {}
C_MythicPlus.RequestMapInfo()
local t = C_ChallengeMode.GetMapTable()
for _,v in pairs(t) do
validDungeons[v] = true
end
end
return validDungeons[dungeonID]
end
function iKS:scanCharacterMaps(newChar)
if not newChar and not iKS:createPlayer() then return end
--[[
local maps = C_ChallengeMode.GetMapTable()
local maxCompleted = 0
for _, mapID in pairs(maps) do
local _, level, _, affixes, members = C_MythicPlus.GetWeeklyBestForMap(mapID)
if members then
for _,member in pairs(members) do -- Avoid leaking from another char (wtf??, how is this even possible)
if member.name == unitName then
if level and level > maxCompleted then
maxCompleted = level
end
break
end
end
end
end
if iKeystonesDB[player].maxCompleted and iKeystonesDB[player].maxCompleted < maxCompleted then
iKeystonesDB[player].maxCompleted = maxCompleted
end
--]]
-- type: 1 m+, 2 pvp, 3 raid
local isFirstLogin = false
if not iKeystonesDB[player].raidHistory or newChar then
iKeystonesDB[player].raidHistory = {}
isFirstLogin = true
StaticPopup_Show("IKS_MIDWEEKFIRSTLOAD")
end
local t = C_WeeklyRewards.GetActivities() -- for pvp
if not t then print("Error: Activities not found") return end
if isFirstLogin then
if t[3] then -- apparently sometimes data isn't loaded fast enough, cba to try catching it since it's only the first reset which will be messy anyway
for k,v in pairs(t[3]) do
if type(v) ~= "table" then break end -- hopefully fixes problems when reaching L60
local dif = (v.level == 17 and "lfr") or (v.level == 14 and "normal") or (v.level == 15 and "heroic") or (v.level == 16 and "mythic") or "unknown"
if v.progress >= v.threshold then
if not iKeystonesDB[player].raidHistory[dif] or iKeystonesDB[player].raidHistory[dif] < v.threshold then
iKeystonesDB[player].raidHistory[dif] = v.threshold
end
elseif v.progress > 0 then
iKeystonesDB[player].raidHistory[dif] = v.progress
end
end
end
end
if isFirstLogin then
iKeystonesDB[player].runHistory = {}
local history = C_MythicPlus.GetRunHistory(false, true);
for k,v in pairs(history) do
if v.thisWeek then -- is this necessery?
iKeystonesDB[player].runHistory[v.level] = iKeystonesDB[player].runHistory[v.level] and iKeystonesDB[player].runHistory[v.level] + 1 or 1
end
end
end
if t[4] then -- first pvp box
iKeystonesDB[player].PvP = {progress = t[4].progress, level = t[4].level}
end
if IsQuestFlaggedCompleted(62079) then -- collecting weekly rewards doesn't proc quest_log_update?
iKeystonesDB[player].canLoot = false
else
iKeystonesDB[player].canLoot = C_WeeklyRewards.HasAvailableRewards()
end
end
function iKS:scanInventory(requestingSlots, requestingItemLink)
if not iKS:createPlayer() then return end
local _map = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
local _level = C_MythicPlus.GetOwnedKeystoneLevel()
if not _map or not _level then return end
if requestingSlots or requestingItemLink then
for bagID = 0, 4 do
for invID = 1, GetContainerNumSlots(bagID) do
local itemID = GetContainerItemID(bagID, invID)
if itemID and itemID == 180653 then
if requestingSlots then
return bagID, invID
end
return GetContainerItemLink(bagID, invID)
end
end
end
end
iKeystonesDB[player].key = {
['map'] = _map,
['level'] = _level,
}
if (iKS.keyLevel and iKS.keyLevel < _level) or not iKS.keyLevel then
local itemLink = iKS:getKeystoneLink(_level, _map)
print('iKS: New keystone - ' .. itemLink)
end
iKS.keyLevel = _level
iKS.mapID = _map
end
function iKS:getItemColor(level)
if level < 4 then -- Epic
return '|cffa335ee'
elseif level < 7 then -- Green
return '|cff3fbf3f'
elseif level < 10 then -- Yellow
return '|cffffd100'
elseif level < 15 then -- orange
return '|cffff7f3f'
else -- Red
return '|cffff1919'
end
end
function iKS:getZoneInfo(mapID, zone)
local name, arg2, timeLimit = C_ChallengeMode.GetMapUIInfo(mapID)
if zone then
return iKS.keystonesToMapIDs[mapID]
else
return name
end
end
function iKS:getKeystoneLink(keyLevel, map)
return _sformat('%s|Hkeystone:%d:%d:%d:%d:%d:%d|h[%s (%s)]|h|r', iKS:getItemColor(keyLevel), map, keyLevel, (keyLevel >= 4 and iKS.currentAffixes[2] or 0), (keyLevel >= 7 and iKS.currentAffixes[3] or 0), iKS.currentAffixes[1],((keyLevel >= 10 and iKS.currentAffixes[4]) and iKS.currentAffixes[4] or 0), iKS:getZoneInfo(map), keyLevel)
end
function iKS:printKeystones()
local allCharacters = {}
for guid,data in pairs(iKeystonesDB) do
local itemLink = ''
if data.key.map then
itemLink = iKS:getKeystoneLink(data.key.level,data.key.map)
else
itemLink = UNKNOWN
end
local str = ''
local maxCompleted = 0
for k,v in pairs(data.runHistory) do
if k > maxCompleted then
maxCompleted = k
end
end
if data.server == GetRealmName() then
str = _sformat('|c%s%s\124r: %s M:%s', RAID_CLASS_COLORS[data.class].colorStr, data.name, itemLink, (maxCompleted >= iKS.currentMax and '|cff00ff00' .. maxCompleted) or maxCompleted)
else
str = _sformat('|c%s%s-%s\124r: %s M:%s', RAID_CLASS_COLORS[data.class].colorStr, data.name, data.server,itemLink,(maxCompleted >= iKS.currentMax and '|cff00ff00' .. maxCompleted) or maxCompleted)
end
print(str)
end
end
function iKS:shouldReportKey(KeyLevel, exactLevel, minLevel, maxLevel)
if not KeyLevel then return false end
if not exactLevel and not minLevel and not maxLevel then return true end
if exactLevel then if KeyLevel == exactLevel then return true else return end end
if minLevel then if KeyLevel >= minLevel and (not maxLevel or (maxLevel and KeyLevel <= maxLevel)) then return true else return end end
end
function iKS:PasteKeysToChat(all,channel, exactLevel, minLevel, maxLevel, requestingWeekly, mapID)
if all then -- All keys for this faction
local i = 0
local totalCounter = 0
local str = ''
local faction = UnitFactionGroup('player')
local msgs = {}
for guid,data in pairs(iKeystonesDB) do
if i == 3 then
SendChatMessage(str, channel)
str = ''
i = 0
end
if data.faction == faction and (mapID == data.key.map or not mapID) then
--if not level or (level and data.key.level and data.key.level >= level) then
local maxCompleted = 0
for k,v in pairs(data.runHistory) do
if k > maxCompleted then
maxCompleted = k
end
end
if not requestingWeekly or (requestingWeekly and maxCompleted < iKS.currentMax) then
if iKS:shouldReportKey(data.key.level, exactLevel, minLevel, maxLevel) then
local itemLink = ''
if data.key.map then
if i > 0 then
str = str .. ' - '
end
itemLink = _sformat('%s (%s)', iKS:getZoneInfo(data.key.map), data.key.level)
str = str.._sformat('%s: %s', data.name, itemLink)
i = i + 1
totalCounter = totalCounter + 1
end
end
end
end
end
if totalCounter > 0 then
if i > 0 then
SendChatMessage(str, channel)
end
elseif exactLevel and not requestingWeekly then
SendChatMessage("No keystones at " .. exactLevel..".", channel)
elseif minLevel and not maxLevel and not requestingWeekly then
SendChatMessage("No keystones at or above " .. minLevel..".", channel)
elseif minLevel and maxLevel and not requestingWeekly then
SendChatMessage("No keystones between "..minLevel.." and "..maxLevel..".", channel)
elseif mapID then
local n = C_ChallengeMode.GetMapUIInfo(mapID)
SendChatMessage("No keystones for "..n..".", channel)
elseif not requestingWeekly then
SendChatMessage("No keystones.", channel)
end
else -- Only this char
local data = iKeystonesDB[player]
if data then
if data.key.map then
local itemLink = iKS:scanInventory(false, true)
if itemLink then -- nil check
SendChatMessage(itemLink, channel)
else
SendChatMessage(UNKNOWN, channel)
end
else
SendChatMessage("No keystones.", channel)
end
else
SendChatMessage("No keystones.", channel)
end
end
end
function iKS:help()
print([[iKeystones:
/iks reset - reset all characters
/iks start (s) - start dungeon
/iks next (n) - print affixes for next reset
/iks ignore (i) - ignore this character
/iks whitelist (w) - enable tracking for this character (remove ignore)
/iks help (h) - show this help
/iks delete (d) characterName serverName - delete specific character
/iks list (i) - paste all dungeon ids
/iks guild (g) - request keys from guild]])
end
function addon:PLAYER_LOGIN()
player = UnitGUID('player')
C_MythicPlus.RequestCurrentAffixes()
C_MythicPlus.RequestMapInfo()
C_MythicPlus.RequestRewards()
local realm = GetRealmName()
if not (realm:lower():match("mythic dungeons") or realm:lower():match("arena champions")) then
isLegitServer = true
end
GarrisonLandingPageMinimapButton:HookScript('OnEnter', function()
if IsShiftKeyDown() then
iKS:createMainWindow()
else
GameTooltip:AddLine('Shift-Hover to show iKeystones')
end
GameTooltip:Show() -- force refresh to resize
end)
GarrisonLandingPageMinimapButton:HookScript('OnLeave', function()
if iKS.anchor then
iKS.anchor:Hide()
end
end)
iKS:scanCharacterMaps()
end
local version = 1.966
function addon:ADDON_LOADED(addonName)
if addonName == 'iKeystones' then
iKeystonesDB = iKeystonesDB or {}
iKeystonesConfig = iKeystonesConfig or {
version = version,
ignoreList = {},
affstring = "",
}
if not iKeystonesConfig.version or iKeystonesConfig.version < version then
if iKeystonesConfig.version and iKeystonesConfig.version < 1.930 then -- reset data for new expansion (db doesn't have level data)
iKeystonesDB = nil
iKeystonesDB = {}
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.949 then -- remove tournament realms
local guidsToDelete = {}
for guid,data in pairs(iKeystonesDB) do
local server = data.server:lower()
if server:match("mythic dungeons") or server:match("arena champions") then
guidsToDelete[guid] = true
end
end
for k,v in pairs(guidsToDelete) do
iKeystonesDB[k] = nil
end
end
if not iKeystonesConfig.version or iKeystonesConfig.version <= 1.940 then
for guid,data in pairs(iKeystonesDB) do
data.torghast = {}
end
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.943 then -- remove activities and convert it into .PvP
for guid,data in pairs(iKeystonesDB) do
local p = data.activities[2][1].progress
local l = data.activities[2][1].level
data.PvP = {progress = p or 0, level = l or 0}
data.activities = nil
end
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.946 then -- remove activities and convert it into .PvP
for guid,data in pairs(iKeystonesDB) do
if data.pvp then
data.pvp = nil
end
if not data.PvP then
data.PvP = {progress = p or 0, level = l or 0}
end
end
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.945 then
for guid,data in pairs(iKeystonesDB) do
if not data.runHistory then
data.runHistory = {}
end
end
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.961 then
for guid,data in pairs(iKeystonesDB) do
data.torghast = 0
end
end
if iKeystonesConfig.version and iKeystonesConfig.version < 1.963 then -- ya fucked up dungeon servers again somehow
local guidsToDelete = {}
for guid,data in pairs(iKeystonesDB) do
local server = data.server:lower()
if data.server:lower():match("mythic dungeons") or data.server:lower():match("arena champions") then
guidsToDelete[guid] = true
end
end
for k,v in pairs(guidsToDelete) do
iKeystonesDB[k] = nil
end
end
iKeystonesConfig.version = version
end
if not iKeystonesConfig.ignoreList then
iKeystonesConfig.ignoreList = {}
end
if not iKeystonesConfig.affstring then --remove old stuff and reset chars
iKeystonesDB = {}
iKeystonesConfig.aff = nil
iKeystonesConfig.affstring = ""
end
--LoadAddOn("Blizzard_ChallengesUI")
elseif addonName == 'Blizzard_ChallengesUI' then
addon:MYTHIC_PLUS_CURRENT_AFFIX_UPDATE()
end
iKS:checkTorghast()
end
--Fix for Blizzard_ChallengesUI gving errors from 9.0.1 when loaded during loading screens
addon:RegisterEvent("LOADING_SCREEN_DISABLED")
function addon:LOADING_SCREEN_DISABLED()
if not IsAddOnLoaded("Blizzard_ChallengesUI") then
LoadAddOn("Blizzard_ChallengesUI")
end
addon:UnregisterEvent("LOADING_SCREEN_DISABLED")
end
local delayLoadingTimer
function addon:MYTHIC_PLUS_CURRENT_AFFIX_UPDATE()
local temp = C_MythicPlus.GetCurrentAffixes()
if not temp then
if not delayLoadingTimer then
delayLoadingTimer = C_Timer.NewTimer(2, function()
addon:MYTHIC_PLUS_CURRENT_AFFIX_UPDATE()
end)
end
return
end
if temp[1] then
iKS.currentAffixes[sortedAffixes[temp[1].id]] = temp[1].id
end
if temp[2] then
iKS.currentAffixes[sortedAffixes[temp[2].id]] = temp[2].id
end
if temp[3] then
iKS.currentAffixes[sortedAffixes[temp[3].id]] = temp[3].id
end
if temp[4] then
iKS.currentAffixes[sortedAffixes[temp[4].id]] = temp[4].id
end
if iKeystonesDB[player] then
iKeystonesDB[player].canLoot = C_WeeklyRewards.HasAvailableRewards()
end
if not isLegitServer then return end
local affstring = _sformat("2%d%d%d%d", iKS.currentAffixes[1], iKS.currentAffixes[2],iKS.currentAffixes[3],iKS.currentAffixes[4])
if iKeystonesConfig.affstring ~= affstring then
iKeystonesConfig.affstring = affstring
iKS:weeklyReset()
end
if not iKS:createPlayer(true) then return end
local key = C_MythicPlus.GetOwnedKeystoneLevel()
local mapID = C_MythicPlus.GetOwnedKeystoneChallengeMapID()
iKS.keyLevel = key
iKS.mapID = mapID
iKeystonesDB[player].key = {
['map'] = mapID,
['level'] = key,
}
--Get max dynamically
local lastMax = 0
local currentMaxLevel = 0
for i = 2, 30 do
local ilvl = C_MythicPlus.GetRewardLevelForDifficultyLevel(i)
if lastMax < ilvl then
lastMax = ilvl
iKS.currentMax = i
end
end
end
function addon:CHALLENGE_MODE_COMPLETED()
if not iKS:createPlayer() then return end
local activeKeystoneLevel = C_ChallengeMode.GetActiveKeystoneInfo()
if not activeKeystoneLevel then return end
iKeystonesDB[player].runHistory[activeKeystoneLevel] = iKeystonesDB[player].runHistory[activeKeystoneLevel] and iKeystonesDB[player].runHistory[activeKeystoneLevel] + 1 or 1
end
function addon:BAG_UPDATE()
iKS:scanInventory()
end
do
local _changeTimer
function addon:ITEM_CHANGED(prevHyperlink, newHyperlink) -- cba to parse it from link, check after a delay if key was changed
if _changeTimer then
_changeTimer:Cancel()
end
_changeTimer = C_Timer.NewTimer(2, function()
iKS:scanInventory()
end)
end
end
function addon:ITEM_PUSH(bag, id)
if id == 525134 then
iKS:scanInventory()
end
end
function addon:WEEKLY_REWARDS_UPDATE()
iKS:scanCharacterMaps()
end
function addon:QUEST_LOG_UPDATE()
if not iKS:createPlayer() then return end
iKS:checkTorghast()
if IsQuestFlaggedCompleted(62079) then
iKeystonesDB[player].canLoot = false
end
end
function addon:WEEKLY_REWARDS_HIDE()
C_Timer.After(3, function()
if IsQuestFlaggedCompleted(62079) then
iKeystonesDB[player].canLoot = false
end
end)
end
local function ChatHandling(msg, channel)
if not msg then return end -- not sure if this can even happen, maybe?
msg = msg:lower()
if msg == '.keys' or msg == "!keys" then
iKS:PasteKeysToChat(false,channel)
elseif msg == '.weekly' or msg == "!weekly" then
iKS:PasteKeysToChat(true,channel,nil,iKS.currentMax,nil, true)
elseif msg:find('^[!%.]allkeys') then
if msg:find('^[!%.]allkeys s') then
local mapID = msg:match('^[!%.]allkeys s (%d*)')
mapID = tonumber(mapID)
if iKS.keystonesToMapIDs[mapID] then
iKS:PasteKeysToChat(true,channel,nil,nil,nil,nil,mapID)
end
else
local level = msg:match('^[!%.]allkeys (%d*)')
if msg:match('^[!%.]allkeys (%d*)%+$') then -- .allkeys x+
local level = msg:match('^[!%.]allkeys (%d*)%+$')
iKS:PasteKeysToChat(true,channel,nil,tonumber(level))
elseif msg:match('^[!%.]allkeys (%d*)%-(%d*)$') then -- .allkeys x-y
local minlevel, maxlevel = msg:match('^[!%.]allkeys (%d*)%-(%d*)$')
iKS:PasteKeysToChat(true,channel,nil, tonumber(minlevel), tonumber(maxlevel))
elseif msg:match('^[!%.]allkeys (%d*)') then -- .allkeys 15
local level = msg:match('^[!%.]allkeys (%d*)')
iKS:PasteKeysToChat(true,channel,tonumber(level))
else
iKS:PasteKeysToChat(true,channel)
end
end
elseif msg == ".covenant" or msg == "!covenant" then
local c = C_Covenants.GetActiveCovenantID()
if not c then return end
local covenantData = C_Covenants.GetCovenantData(c)
if not covenantData then return end
SendChatMessage(covenantData.name, channel)
end
end
function addon:CHAT_MSG_GUILD(msg)
ChatHandling(msg, 'guild')
end
function addon:CHAT_MSG_GUILD_LEADER(msg)
ChatHandling(msg, 'guild')
end
function addon:CHAT_MSG_OFFICER(msg,...)
ChatHandling(msg, 'officer')
end
function addon:CHAT_MSG_INSTANCE(msg)
ChatHandling(msg, 'instance')
end
function addon:CHAT_MSG_INSTANCE_LEADER(msg)
ChatHandling(msg, 'instance')
end
function addon:CHAT_MSG_PARTY(msg)
ChatHandling(msg, 'party')
end
function addon:CHAT_MSG_PARTY_LEADER(msg)
ChatHandling(msg, 'party')
end
function addon:CHAT_MSG_RAID(msg)
ChatHandling(msg, 'raid')
end
function addon:CHAT_MSG_RAID_LEADER(msg)
ChatHandling(msg, 'raid')
end
do
local validEncounters = {
--[[ i don't think we need these anymore
[2405] = true, -- Artificer Xy'mox
[2383] = true, -- Hungering Destoyer
[2418] = true, -- Huntsman Altimor
[2406] = true, -- Lady Inerva Darkvein
[2398] = true, -- Shriekwing
[2407] = true, -- Sire Denathrius
[2399] = true, -- Sludgefist
[2417] = true, -- Stone Legion Generals
[2402] = true, -- Sun King's Salvation
[2412] = true, -- The Council of Blood
[2423] = true, -- The Tarragrue
[2433] = true, -- The Eye of the Jailer
[2429] = true, -- The Nine
[2432] = true, -- Remnant of Ner'zhul
[2430] = true, -- Painsmith Raznal
[2434] = true, -- Soulrender Dormazain
[2436] = true, -- Guardian of the First Ones
[2431] = true, -- Fatescribe Roh-Kalo
[2422] = true, -- Kel'Thuzad
[2435] = true, -- Sylvanas Windrunner
--]]
[2512] = true, -- Vigilant Guardian
[2542] = true, -- Skolex, the Insatiable Ravener
[2553] = true, -- Artificer Xymox
[2540] = true, -- Dausegne, the Fallen Oracle
[2544] = true, -- Prototype Pantheon
[2539] = true, -- Lihuvim, Principal Architect
[2529] = true, -- Halondrus the Reclaimer
[2546] = true, -- Anduin Wrynn
[2549] = true, -- Lord of Dread
[2549] = true, -- Rygelon
[2537] = true, -- The Jailer
}
function addon:ENCOUNTER_END(encounterID, encounterName, difficultyID, raidSize, kill)
if not iKS:createPlayer() then return end
if kill == 1 and validEncounters[encounterID] then
if not iKeystonesDB[player].raidHistory then -- kill without first initiating history (level up to max and straigth to raid?)
iKS:scanCharacterMaps()
end
if not iKeystonesDB[player].raidHistory[difficultyID] then
iKeystonesDB[player].raidHistory[difficultyID] = {}
end
-- Track kill history, afaik killing boss multiple times on same difficulty doesn't count toward the vault
if not iKeystonesDB[player].raidHistory[difficultyID][encounterID] then
iKeystonesDB[player].raidHistory[difficultyID][encounterID] = true
end
end
end
end
function addon:CHALLENGE_MODE_KEYSTONE_RECEPTABLE_OPEN()
local _, _, _, _, _, _, _, mapID = GetInstanceInfo()
if iKS.mapID and iKS.keystonesToMapIDs[iKS.mapID] == mapID then
local bagID, slotID = iKS:scanInventory(true)
PickupContainerItem(bagID, slotID)
C_Timer.After(0.1, function()
if CursorHasItem() then
C_ChallengeMode.SlotKeystone()
end
end)
end
end
local function chatFiltering(self, event, msg, ...)
if event == 'CHAT_MSG_LOOT' then
local linkStart = msg:find('Hitem:180653')
if linkStart then
--print(msg:gsub("|", "||")) -- DEBUG
local preLink = msg:sub(1, linkStart-12)
local linkStuff = msg:sub(math.max(linkStart-11, 0))
local tempTable = {strsplit(':', linkStuff)}
--[[
1 |cffa335ee|Hitem:
2 180653:
3 :
4 :
5 :
6 :
7 :
8 :
9 :
10 60:
11 66:
12 :
13 :
14 :
15 4:
16 28:
17 1279:
18 17:
19 382:
20 18:
21 2:
22 19:
23 10:
24 :
25 :
27 |h[Mythic Keystone]|h|r. 5 --]]
--/script SendChatMessage("\124cffa335ee\124Hitem:180653::::::::60:66::::4:28:1279:17:382:18:4:19:10:::\124h[Mythic Keystone]\124h\124r")
-- strsplit("|cffa335ee \124Hitem:180653::::::::60:581::::5:17:380:18:9:19:9:20:7:21:124:::\124h[Mythic Keystone]|h|r.") 5 first box
--[[
local str = {strsplit(":","||cffa335ee|||Hitem:180653::::::::60:581::::5:17:380:18:9:19:9:20:7:21:124:::||h[Mythic Keystone]||h||r. 5")};for k,v in pairs(str) do print(k,v) end
--dh first week 9
[10:50:20] 1 ||cffa335ee|||Hitem
[10:50:20] 2 180653
[10:50:20] 3
[10:50:20] 4
[10:50:20] 5
[10:50:20] 6
[10:50:20] 7
[10:50:20] 8
[10:50:20] 9
[10:50:20] 10 60
[10:50:20] 11 581
[10:50:20] 12
[10:50:20] 13
[10:50:20] 14
[10:50:20] 15 5
[10:50:20] 16 17
[10:50:20] 17 380
[10:50:20] 18 18
[10:50:20] 19 9
[10:50:20] 20 19
[10:50:20] 21 9
[10:50:20] 22 20
[10:50:20] 23 7
[10:50:20] 24 21
[10:50:20] 25 124
-- paladin first week 2
local str = {strsplit(":","|cffa335ee|Hitem:180653::::::::60:66::::3:17:381:18:2:19:9:::|h[Mythic Keystone]|h|r. 5")};for k,v in pairs(str) do print(k,v) end
[10:56:34] 1 |cffa335ee|Hitem
[10:56:34] 2 180653
[10:56:34] 3
[10:56:34] 4
[10:56:34] 5
[10:56:34] 6
[10:56:34] 7
[10:56:34] 8
[10:56:34] 9
[10:56:34] 10 60
[10:56:34] 11 66
[10:56:34] 12
[10:56:34] 13
[10:56:34] 14
[10:56:34] 15 3
[10:56:34] 16 17
[10:56:34] 17 381
[10:56:34] 18 18
[10:56:34] 19 2
[10:56:34] 20 19
[10:56:34] 21 9
[10:56:34] 22
[10:56:34] 23
[10:56:34] 24 |h[Mythic Keystone]|h|r. 5
dk first week 13
local str = {strsplit(":","|cffa335ee|Hitem:180653::::::::60:250::::6:17:381:18:13:19:9:20:7:21:124:22:121:::|h[Mythic Keystone]|h|r. 5")};for k,v in pairs(str) do print(k,v) end
|cffa335ee|Hitem:180653::::::::60:250::::6:17:381:18:13:19:9:20:7:21:124:22:121:::|h[Mythic Keystone]|h|r. 5
[11:18:31] 9
[11:18:31] 10 60
[11:18:31] 11 250
[11:18:31] 12
[11:18:31] 13
[11:18:31] 14