· 6 years ago · Sep 25, 2019, 04:42 PM
1local e, L = unpack(select(2, ...))
2local MAX_LEVEL = 120
3
4local SYNC_VERSION = 'sync4'
5local UPDATE_VERSION = 'update4'
6
7local COLOR_BLUE_BNET = 'ff82c5ff'
8
9local strformat, find = string.format, string.find
10local tremove = table.remove
11
12local NonBNFriend_List = {}
13local BNFriendList = {}
14local FRIEND_LIST = {}
15
16----------------------------------------------------
17----------------------------------------------------
18-- BNet Friend's list API
19-- Collect and store pressence, game pressence IDs
20
21local BNGetFriendInfo = C_BattleNet.GetFriendAccountInfo
22local BNGetGameAccountInfo = C_BattleNet.GetGameAccountInfoByID
23
24-- BNGetNumFOF(BNetID) -- Seems to take first return value from BNGetFriendInfo
25
26local isConnected = BNConnected() -- Determine if connected to BNet, if not disable all comms, check for BN_CONNECTED to re-enable communications, BN_DISCONNECTED disable communications on this event
27
28function e.GetFriendGaID(battleTag)
29 if not BNFriendList[battleTag] then return nil end
30 return BNFriendList[battleTag].gaID
31end
32
33function e.FriendBattleTag(id)
34 return AstralFriends[id][2]:sub(1, AstralFriends[id][2]:find('#') - 1)
35end
36
37-- Updates BNFriendList for friend update
38-- @paremt index int Friend's list index that was updated
39function e.BNFriendUpdate(index)
40 if not index then return end -- No index, event fired from player
41 local presID, pName, battleTag, _, toonName, gaID, client = BNGetFriendInfo(index) -- Let's get some fresh info, client != 'WoW' when on character list it seems
42
43 if not gaID then return end -- No game pressence ID, can't talk to them then
44
45 local guid = select(20, BNGetGameAccountInfo(gaID))
46
47 if client == BNET_CLIENT_WOW and toonName then
48 local fullName = toonName .. '-' .. select(4, BNGetGameAccountInfo(gaID))
49 if FRIEND_LIST[fullName] then
50 FRIEND_LIST[fullName].guid = guid
51 FRIEND_LIST[fullName].pName = pName
52 FRIEND_LIST[fullName].isConnected = true
53 end
54 if NonBNFriend_List[fullName] then
55 NonBNFriend_List[fullName].isBtag = true
56 end
57 end
58
59 if not BNFriendList[battleTag] then
60 BNFriendList[battleTag] = {toonName = toonName, client = client, gaID = gaID, usingAK = false}
61 else
62 BNFriendList[battleTag].client = client --Update client, did they log off WoW?
63 BNFriendList[battleTag].presID = presID or 0 -- If they have a presID force an update, else set to 0. Used for all API needing a pressence ID
64 BNFriendList[battleTag].gaID = gaID -- Might as well keep it up to date
65 end
66
67end
68AstralEvents:Register('BN_FRIEND_INFO_CHANGED', e.BNFriendUpdate, 'update_BNFriend')
69
70----------------------------------------------------
71----------------------------------------------------
72-- Friend Indexing
73
74function e.SetFriendID(unit, id)
75 FRIEND_LIST[unit] = {id = id, isConnected = false}
76end
77
78function e.FriendID(unit)
79 if FRIEND_LIST[unit] then
80 return FRIEND_LIST[unit].id
81 else
82 return nil
83 end
84end
85
86function e.Friend(id)
87 return AstralFriends[id][1]
88end
89
90function e.FriendName(id)
91 return AstralFriends[id][1]:sub(1, AstralFriends[id][1]:find('-') - 1)
92end
93
94function e.FriendGUID(unit)
95 return FRIEND_LIST[unit].guid
96end
97
98function e.FriendGAID(unit)
99 return FRIEND_LIST[unit].gaID
100end
101
102function e.FriendPresName(unit)
103 return FRIEND_LIST[unit].pName
104end
105
106function e.WipeFriendList()
107 wipe(FRIEND_LIST)
108end
109
110function e.IsFriendOnline(unit)
111 if not FRIEND_LIST[unit] then
112 return false
113 else
114 return FRIEND_LIST[unit].isConnected
115 end
116end
117----------------------------------------------------
118----------------------------------------------------
119---- Non BNet Friend stuff
120
121local function UpdateNonBNetFriendList()
122 wipe(NonBNFriend_List)
123
124 for k,v in pairs(FRIEND_LIST) do
125 v.isConnected = false
126 end
127
128 for i = 1, select(2, GetNumFriends()) do -- Only parse over online friends
129 local name = strformat('%s-%s', GetFriendInfo(i), e.PlayerRealm())
130 local guid = select(9, GetFriendInfo(i))
131 NonBNFriend_List[name] = {isBtag = false}
132 if FRIEND_LIST[name] then
133 FRIEND_LIST[name].isConnected = true
134 FRIEND_LIST[name].guid = guid
135 end
136 end
137
138 for i = 1, BNGetNumFriends() do
139 local presID, pName, battleTag, _, toonName, gaID, client = BNGetFriendInfo(i)
140 if gaID and toonName then
141 local guid = select(20, BNGetGameAccountInfo(gaID))
142 BNFriendList[battleTag] = {toonName = toonName, client = client, gaID = gaID, usingAK = false}
143 if client == BNET_CLIENT_WOW then
144 local fullName = toonName .. '-' .. select(4, BNGetGameAccountInfo(gaID))
145 if NonBNFriend_List[fullName] then
146 NonBNFriend_List[fullName].isBtag = true -- don't need to send people on WoW friend and bnet friend the same data.
147 end
148 if FRIEND_LIST[fullName] then
149 FRIEND_LIST[fullName].isConnected = true
150 FRIEND_LIST[fullName].guid = guid
151 FRIEND_LIST[fullName].pName = pName
152 end
153 end
154 end
155 end
156end
157AstralEvents:Register('FRIENDLIST_UPDATE', UpdateNonBNetFriendList, 'update_non_bnet_list')
158
159----------------------------------------------------
160----------------------------------------------------
161-- Friend Syncing
162
163local function RecieveKey(msg, sender)
164 if not AstralKeysSettings.friendOptions.friend_sync.isEnabled then return end
165 local btag
166 if type(sender) == 'number' then
167 local bnetID = select(17, BNGetGameAccountInfo(sender))
168 btag = select(3, BNGetFriendInfo(BNGetFriendIndex(bnetID)))
169 end
170
171 local timeStamp = e.WeekTime()
172 local unit, class, dungeonID, keyLevel, weekly_best, week, faction = strsplit(':', msg)
173
174 dungeonID = tonumber(dungeonID)
175 keyLevel = tonumber(keyLevel)
176 week = tonumber(week)
177 weekly_best = tonumber(weekly_best)
178
179 local id = e.FriendID(unit)
180
181 if id then
182 AstralFriends[id][4] = dungeonID
183 AstralFriends[id][5] = keyLevel
184 AstralFriends[id][6] = week
185 AstralFriends[id][7] = timeStamp
186 AstralFriends[id][9] = weekly_best
187 else
188 AstralFriends[#AstralFriends + 1] = {unit, btag, class, dungeonID, keyLevel, week, timeStamp, faction, weekly_best}
189 e.SetFriendID(unit, #AstralFriends)
190 ShowFriends()
191 end
192
193 e.AddUnitToTable(unit, class, faction, 'FRIENDS', dungeonID, keyLevel, weekly_best, btag)
194
195 if e.FrameListShown() == 'FRIENDS' then
196 e.UpdateFrames()
197 end
198end
199AstralComs:RegisterPrefix('BNET', UPDATE_VERSION, RecieveKey)
200AstralComs:RegisterPrefix('WHISPER', UPDATE_VERSION, RecieveKey)
201
202local function SyncFriendUpdate(entry, sender)
203 if not AstralKeysSettings.friendOptions.friend_sync.isEnabled then return end
204
205 if AstralKeyFrame:IsShown() then
206 AstralKeyFrame:SetScript('OnUpdate', AstralKeyFrame.OnUpdate)
207 AstralKeyFrame.updateDelay = 0
208 end
209
210 local btag
211 if type(sender) == 'number' then
212 local bnetID = select(17, BNGetGameAccountInfo(sender))
213 btag = select(3, BNGetFriendInfo(BNGetFriendIndex(bnetID)))
214 end
215
216 if AstralKeyFrame:IsShown() then
217 AstralKeyFrame:SetScript('OnUpdate', AstralKeyFrame.OnUpdate)
218 AstralKeyFrame.updateDelay = 0
219 end
220
221 local unit, class, dungeonID, keyLevel, week, timeStamp
222
223 local _pos = 0
224 while find(entry, '_', _pos) do
225
226 class, dungeonID, keyLevel, week, timeStamp, faction, weekly_best = entry:match(':(%a+):(%d+):(%d+):(%d+):(%d+):(%d+):(%d+)', entry:find(':', _pos))
227 unit = entry:sub(_pos, entry:find(':', _pos) - 1)
228 _pos = find(entry, '_', _pos) + 1
229
230 dungeonID = tonumber(dungeonID)
231 keyLevel = tonumber(keyLevel)
232 week = tonumber(week)
233 timeStamp = tonumber(timeStamp)
234 weekly_best = tonumber(weekly_best)
235
236 if week >= e.Week then
237 local id = e.FriendID(unit)
238 if id then
239 AstralFriends[id][4] = dungeonID
240 AstralFriends[id][5] = keyLevel
241 AstralFriends[id][6] = week
242 AstralFriends[id][7] = timeStamp
243 AstralFriends[id][9] = weekly_best
244 else
245 AstralFriends[#AstralFriends + 1] = {unit, btag, class, dungeonID, keyLevel, week, timeStamp, faction, weekly_best}
246 e.SetFriendID(unit, #AstralFriends)
247 ShowFriends()
248 end
249 e.AddUnitToTable(unit, class, faction, 'FRIENDS', dungeonID, keyLevel, weekly_best, btag)
250 end
251 end
252end
253AstralComs:RegisterPrefix('BNET', SYNC_VERSION, SyncFriendUpdate)
254AstralComs:RegisterPrefix('WHISPER', SYNC_VERSION, SyncFriendUpdate)
255
256local function UpdateWeekly(msg)
257 local unit, weekly_best = strsplit(':', msg)
258
259 local id = e.FriendID(unit)
260 if id then
261 AstralFriends[id][9] = tonumber(weekly_best)
262 AstralFriends[id][7] = e.WeekTime()
263 end
264end
265AstralComs:RegisterPrefix('BNET', 'friendWeekly', UpdateWeekly)
266AstralComs:RegisterPrefix('WHISPER', 'friendWeekly', UpdateWeekly)
267
268local messageStack = {}
269local messageQueue = {}
270
271local function PushKeysToFriends(target)
272 if not AstralKeysSettings.friendOptions.friend_sync.isEnabled then return end
273 wipe(messageStack)
274 wipe(messageQueue)
275
276 for i = 1, #AstralCharacters do
277 local id = e.UnitID(AstralCharacters[i].unit)
278 if id then -- We have a key for this character, let's get the message and queue it up
279 local map, level = e.UnitMapID(id), e.UnitKeyLevel(id)
280 messageStack[#messageStack + 1] = strformat('%s_', strformat('%s:%s:%d:%d:%d:%d:%d:%d', AstralCharacters[i].unit, e.UnitClass(id), map, level, e.Week, AstralKeys[id][7], AstralCharacters[i].faction, AstralCharacters[i].weekly_best)) -- name-server:class:mapID:keyLevel:week#:weekTime:faction:weekly
281 end
282 end
283
284 local index = 1
285 messageQueue[index] = ''
286 while(messageStack[1]) do
287 local nextMessage = strformat('%s%s', messageQueue[index], messageStack[1])
288 if nextMessage:len() < 2000 then
289 messageQueue[index] = nextMessage
290 table.remove(messageStack, 1)
291 else
292 index = index + 1
293 messageQueue[index] = ''
294 end
295 end
296
297 e.PushKeyDataToFriends(messageQueue, target)
298end
299
300-- Sends data to BNeT friends and Non-BNet friends
301-- @param data table Sync data that includes all keys for all of person's characters
302-- @param data string Update string including only logged in person's characters
303function e.PushKeyDataToFriends(data, target)
304 if not target then
305 for _, unit in pairs(BNFriendList) do
306 if unit.client == BNET_CLIENT_WOW then --and unit.usingAk then -- Only send if they are in WoW
307 if type(data) == 'table' then
308 for i = 1, #data do
309 AstralComs:NewMessage('AstralKeys', strformat('%s %s', SYNC_VERSION, data[i]), 'BNET', unit.gaID)
310 end
311 else
312 AstralComs:NewMessage('AstralKeys', strformat('%s %s', UPDATE_VERSION, data), 'BNET', unit.gaID)
313 end
314 end
315 end
316 for player in pairs(NonBNFriend_List) do
317 if not player.isBtag then
318 if type(data) == 'table' then
319 for i = 1, #data do
320 AstralComs:NewMessage('AstralKeys', strformat('%s %s', SYNC_VERSION, data[i]), 'WHISPER', player)
321 end
322 else
323 AstralComs:NewMessage('AstralKeys', strformat('%s %s', UPDATE_VERSION, data), 'WHISPER', player)
324 end
325 end
326 end
327 else
328 if type(data) == 'table' then
329 for i = 1, #data do
330 AstralComs:NewMessage('AstralKeys', strformat('%s %s', SYNC_VERSION, data[i]), tonumber(target) and 'BNET' or 'WHISPER', target)
331 end
332 else
333 AstralComs:NewMessage('AstralKeys', strformat('%s %s', UPDATE_VERSION, data), tonumber(target) and 'BNET' or 'WHISPER', target)
334 end
335 end
336end
337
338
339-- Let's find out which friends are using Astral Keys, no need to spam every friend, just the ones using Astral keys
340local function PingFriendsForAstralKeys()
341 if not AstralKeysSettings.friendOptions.friend_sync.isEnabled then return end
342 for i = 1, select(2, GetNumFriends()) do -- Only parse over online friends
343 local name = strformat('%s-%s', GetFriendInfo(i), e.PlayerRealm())
344 NonBNFriend_List[name] = {isBtag = false}
345 end
346
347 for i = 1, BNGetNumFriends() do
348 local presID, pName, battleTag, _, toonName, gaID, client = BNGetFriendInfo(i)
349
350 if gaID then
351 local guid = select(20, BNGetGameAccountInfo(gaID))
352 BNFriendList[battleTag] = {toonName = toonName, client = client, gaID = gaID, usingAK = false}
353 if client == BNET_CLIENT_WOW then
354 local fullName = toonName .. '-' .. select(4, BNGetGameAccountInfo(gaID))
355 if NonBNFriend_List[fullName] then
356 NonBNFriend_List[fullName].isBtag = true -- don't need to send people on WoW friend and bnet friend the same data.
357 end
358 if FRIEND_LIST[fullName] then
359 FRIEND_LIST[fullName].isConnected = true
360 FRIEND_LIST[fullName].guid = guid
361 FRIEND_LIST[fullName].pName = pName
362 end
363 end
364 end
365 end
366
367 for _, player in pairs(BNFriendList) do
368 if player.client == BNET_CLIENT_WOW then
369 AstralComs:NewMessage('AstralKeys', 'BNet_query ping', 'BNET', player.gaID)
370 end
371 end
372
373 for player in pairs(NonBNFriend_List) do
374 if not player.isBtag then
375 AstralComs:NewMessage('AstralKeys', 'BNet_query ping', 'WHISPER', player)
376 end
377 end
378
379 AstralEvents:Unregister('FRIENDLIST_UPDATE', 'pingFriends')
380end
381
382-- Figures out who is using AK on friends list, sends them a response and key data
383local function PingResponse(msg, sender)
384 local btag
385 if type(sender) == 'number' then
386 local bnetID = select(17, BNGetGameAccountInfo(sender))
387 btag = select(3, BNGetFriendInfoByID(BNGetFriendIndex(bnetID)))
388 end
389
390 if BNFriendList[btag] then
391 BNFriendList[btag].usingAK = true
392 end
393
394 if NonBNFriend_List[sender] then
395 NonBNFriend_List[sender].usingAK = true
396 end
397
398 if msg:find('ping') then
399 AstralComs:NewMessage('AstralKeys', 'BNet_query response', type(sender) == 'number' and 'BNET' or 'WHISPER', sender)
400 end
401 PushKeysToFriends(sender)
402end
403AstralComs:RegisterPrefix('WHISPER', 'BNet_query', PingResponse)
404AstralComs:RegisterPrefix('BNET', 'BNet_query', PingResponse)
405
406local function Init()
407 ShowFriends()
408 AstralEvents:Unregister('PLAYER_ENTERING_WORLD', 'InitFriends')
409end
410AstralEvents:Register('PLAYER_ENTERING_WORLD', Init, 'InitFriends')
411
412AstralEvents:Register('FRIENDLIST_UPDATE', PingFriendsForAstralKeys, 'pingFriends')
413
414function e.ToggleFriendSync()
415 if AstralKeysSettings.friendOptions.friend_sync.isEnabled then
416 AstralComs:RegisterPrefix('WHISPER', 'BNet_query', PingResponse)
417 AstralComs:RegisterPrefix('BNET', 'BNet_query', PingResponse)
418 AstralComs:RegisterPrefix('BNET', SYNC_VERSION, SyncFriendUpdate)
419 AstralComs:RegisterPrefix('WHISPER', SYNC_VERSION, SyncFriendUpdate)
420 AstralComs:RegisterPrefix('BNET', UPDATE_VERSION, RecieveKey)
421 AstralComs:RegisterPrefix('WHISPER', UPDATE_VERSION, RecieveKey)
422 AstralEvents:Register('FRIENDLIST_UPDATE', UpdateNonBNetFriendList, 'update_non_bnet_list')
423 AstralEvents:Register('BN_FRIEND_INFO_CHANGED', e.BNFriendUpdate, 'update_BNFriend')
424 PingFriendsForAstralKeys()
425 else
426 AstralComs:UnregisterPrefix('WHISPER', 'BNet_query', PingResponse)
427 AstralComs:UnregisterPrefix('BNET', 'BNet_query', PingResponse)
428 AstralComs:UnregisterPrefix('BNET', SYNC_VERSION, SyncFriendUpdate)
429 AstralComs:UnregisterPrefix('WHISPER', SYNC_VERSION, SyncFriendUpdate)
430 AstralComs:UnregisterPrefix('BNET', UPDATE_VERSION, RecieveKey)
431 AstralComs:UnregisterPrefix('WHISPER', UPDATE_VERSION, RecieveKey)
432 AstralEvents:Unregister('FRIENDLIST_UPDATE', UpdateNonBNetFriendList, 'update_non_bnet_list')
433 AstralEvents:Unregister('BN_FRIEND_INFO_CHANGED', e.BNFriendUpdate, 'update_BNFriend')
434 end
435end
436
437----------------------------------------------------
438----------------------------------------------------
439-- Friend Filtering and sorting
440-- Needs non-generic filering for names as well!
441local function FriendFilter(A, filters)
442 if not type(A) == 'table' then return end
443
444 local keyLevelLowerBound, keyLevelUpperBound = 2, 999 -- Lowest key possible, some high enough number
445
446 if filters['key_level'] ~= '' and filters['key_level'] ~= '1' then
447 local keyFilterText = filters['key_level']
448 if tonumber(keyFilterText) then -- only input a single key level
449 keyLevelLowerBound = tonumber(keyFilterText)
450 keyLevelUpperBound = tonumber(keyFilterText)
451 elseif string.match(keyFilterText, '%d+%+') then -- Text input is <number>+, looking for any key at least <number>
452 keyLevelLowerBound = tonumber(string.match(keyFilterText, '%d+'))
453 elseif string.match(keyFilterText, '%d+%-') then -- Text input is <number>-, looking for a key no higher than <number>
454 keyLevelUpperBound = tonumber(string.match(keyFilterText, '%d+'))
455 end
456 end
457
458 for i = 1, #A.FRIENDS do
459 if AstralKeysSettings.frame.show_offline.isEnabled then
460 A.FRIENDS[i].isShown = true
461 else
462 A.FRIENDS[i].isShown = e.IsFriendOnline(A.FRIENDS[i].character_name)
463 end
464
465 if not AstralKeysSettings.friendOptions.show_other_faction.isEnabled then
466 A.FRIENDS[i].isShown = A.FRIENDS[i].isShown and tonumber(A.FRIENDS[i].faction) == e.FACTION
467 end
468
469 local isShownInFilter = true -- Assume there is no filter taking place
470
471 for field, filterText in pairs(filters) do
472 if filterText ~= '' then
473 isShownInFilter = false -- There is a filter, now assume this unit is not to be shown
474 if field == 'dungeon_name' then
475 local mapName = e.GetMapName(A.FRIENDS[i]['mapID'])
476 if strfind(strlower(mapName), strlower(filterText)) then
477 isShownInFilter = true
478 end
479 elseif field == 'key_level' then
480 if A.FRIENDS[i][field] >= keyLevelLowerBound and A.FRIENDS[i][field] <= keyLevelUpperBound then
481 isShownInFilter = true
482 end
483 else
484 if strfind(strlower(A.FRIENDS[i][field]):sub(1, A.FRIENDS[i][field]:find('-') - 1), strlower(filterText)) or strfind(strlower(A.FRIENDS[i].btag), strlower(filterText)) then
485 isShownInFilter = true
486 end
487 end
488 end
489 A.FRIENDS[i].isShown = A.FRIENDS[i].isShown and isShownInFilter
490 end
491
492 if A.FRIENDS[i].isShown then
493 A.numShown = A.numShown + 1
494 end
495 end
496end
497e.AddListFilter('FRIENDS', FriendFilter)
498
499local function CompareFriendNames(a, b)
500 local s = string.lower(a.btag) or '|'
501 local t = string.lower(b.btag) or '|'
502 if AstralKeysSettings.frame.orientation == 0 then
503 if s > t then
504 return true
505 elseif
506 s < t then
507 return false
508 else
509 return string.lower(a.character_name) > string.lower(b.character_name)
510 end
511 else
512 if s < t then
513 return true
514 elseif
515 s > t then
516 return false
517 else
518 return string.lower(a.character_name) < string.lower(b.character_name)
519 end
520 end
521end
522
523local function FriendSort(A, v)
524 if v == 'dungeon_name' then
525 table.sort(A, function(a, b)
526 local aOnline = e.IsFriendOnline(a.character_name) and 1 or 0
527 local bOnline = e.IsFriendOnline(b.character_name) and 1 or 0
528 if not AstralKeysSettings.frame.mingle_offline.isEnabled then
529 aOnline = true
530 bOnline = true
531 end
532 if aOnline == bOnline then
533 if AstralKeysSettings.frame.orientation == 0 then
534 if e.GetMapName(a.mapID) > e.GetMapName(b.mapID) then
535 return true
536 elseif e.GetMapName(b.mapID) > e.GetMapName(a.mapID) then
537 return false
538 else
539 return a.character_name < b.character_name
540 end
541 else
542 if e.GetMapName(a.mapID) > e.GetMapName(b.mapID) then
543 return false
544 elseif e.GetMapName(b.mapID) > e.GetMapName(a.mapID) then
545 return true
546 else
547 return CompareFriendNames(a, b)
548 end
549 end
550 else
551 return aOnline > bOnline
552 end
553 end)
554 else
555 if v == 'character_name' then
556 table.sort(A, function(a, b)
557 local aOnline = e.IsFriendOnline(a.character_name) and 1 or 0
558 local bOnline = e.IsFriendOnline(b.character_name) and 1 or 0
559 if not AstralKeysSettings.frame.mingle_offline.isEnabled then
560 aOnline = true
561 bOnline = true
562 end
563 if aOnline == bOnline then
564 return CompareFriendNames(a, b)
565 else
566 return aOnline > bOnline
567 end
568 end)
569 else
570 table.sort(A, function(a, b)
571 local aOnline = e.IsFriendOnline(a.character_name) and 1 or 0
572 local bOnline = e.IsFriendOnline(b.character_name) and 1 or 0
573 if not AstralKeysSettings.frame.mingle_offline.isEnabled then
574 aOnline = true
575 bOnline = true
576 end
577 if aOnline == bOnline then
578 if AstralKeysSettings.frame.orientation == 0 then
579 if a[v] > b[v] then
580 return true
581 elseif
582 a[v] < b[v] then
583 return false
584 else
585 return CompareFriendNames(a, b)
586 end
587 else
588 if a[v] < b[v] then
589 return true
590 elseif
591 a[v] > b[v] then
592 return false
593 else
594 return CompareFriendNames(a, b)
595 end
596 end
597 else
598 return aOnline > bOnline
599 end
600 end)
601 end
602 end
603end
604
605e.AddListSort('FRIENDS', FriendSort)
606
607-- Friend's list Hooking
608do
609 for i = 1, 5 do
610 local string = FriendsTooltip:CreateFontString('FriendsTooltipAstralKeysInfo' .. i, 'ARTWORK', 'FriendsFont_Small')
611 string:SetJustifyH('LEFT')
612 string:SetSize(168, 0)
613 string:SetTextColor(0.486, 0.518, 0.541)
614 end
615
616 local OnEnter, OnHide
617 function OnEnter(self)
618 if not self.id then return end -- Friend Groups adds fake units with no ide for group heeaders
619 if not AstralKeysSettings.general.show_tooltip_key.isEnabled then return end
620
621 local left = FRIENDS_TOOLTIP_MAX_WIDTH - FRIENDS_TOOLTIP_MARGIN_WIDTH - FriendsTooltipAstralKeysInfo1:GetWidth()
622 local stringShown = false
623
624 local bnetIDAccount, accountName, isBattleTag, characterName, bnetIDGameAccount, client, lastOnline, isAFK, isDND, broadcastText, noteText, isFriend, broadcastTime = BNGetFriendInfo(self.id);
625 -- Call BNGetFriendInfo twice, first time doesn't seem to actually get the info?
626 bnetIDAccount, accountName, battleTag, isBattleTag, characterName, bnetIDGameAccount, client, isOnline, lastOnline, isAFK, isDND, broadcastText, noteText, isFriend, broadcastTime = BNGetFriendInfo(self.id);
627
628 if not bnetIDAccount then return end -- Double check to make sure index is actually a game account and not a Friend Groups group header.
629 if not FriendsTooltip.maxWidth then return end
630
631 local numGameAccounts = 0
632
633 if bnetIDGameAccount then
634 local hasFocus, characterName, client, realmName, realmID, faction, race, class, _, zoneName, level, gameText = BNGetGameAccountInfo(bnetIDGameAccount)
635
636 if client == BNET_CLIENT_WOW then
637 local characterName = characterName .. '-' .. realmName:gsub('%s+', '')
638 local id = e.FriendID(characterName)
639
640 if id then
641 local keyLevel, dungeonID = AstralFriends[id][5], AstralFriends[id][4]
642 FriendsTooltipAstralKeysInfo1:SetFormattedText("|cffffd200Current Keystone|r\n%d - %s", keyLevel, e.GetMapName(dungeonID))
643
644 FriendsTooltipAstralKeysInfo1:SetPoint('TOP', FriendsTooltipGameAccount1Name, 'BOTTOM', 3, -4)
645 FriendsTooltipGameAccount1Info:SetPoint('TOP', FriendsTooltipAstralKeysInfo1, 'BOTTOM', 0, 0)
646 FriendsTooltipAstralKeysInfo1:Show()
647 stringShown = true
648 FriendsTooltip.height = FriendsTooltip:GetHeight() + FriendsTooltipAstralKeysInfo1:GetHeight()
649 FriendsTooltip.maxWidth = max(FriendsTooltip.maxWidth, FriendsTooltipAstralKeysInfo1:GetStringWidth() + left)
650 else
651 FriendsTooltipAstralKeysInfo1:SetText('')
652 FriendsTooltipAstralKeysInfo1:Hide()
653 FriendsTooltipGameAccount1Info:SetPoint('TOP', FriendsTooltipGameAccount1Name, 'BOTTOM', 0, -4)
654 end
655 else
656 FriendsTooltipAstralKeysInfo1:SetText('')
657 FriendsTooltipAstralKeysInfo1:Hide()
658 FriendsTooltipGameAccount1Info:SetPoint('TOP', FriendsTooltipGameAccount1Name, 'BOTTOM', 0, -4)
659 end
660 end
661
662 if isOnline then
663 numGameAccounts = BNGetNumFriendGameAccounts(self.id)
664 end
665
666 local characterNameString, gameInfoString, astralKeyString
667 if numGameAccounts > 1 then
668 for i = 1, numGameAccounts do
669 local hasFocus, characterName, client, realmName, realmID, faction, race, class, _, zoneName, level, gameText = BNGetFriendGameAccountInfo(self.id, i);
670 characterNameString = _G['FriendsTooltipGameAccount' .. i .. 'Name']
671 gameInfoString = _G['FriendsTooltipGameAccount' .. i .. 'Info']
672 astralKeyString = _G['FriendsTooltipAstralKeysInfo' .. i]
673 if client == BNET_CLIENT_WOW then
674 local characterName = characterName .. '-' .. realmName:gsub('%s+', '')
675 local id = e.FriendID(characterName)
676 if id then
677 local keyLevel, dungeonID = AstralFriends[id][5], AstralFriends[id][4]
678 astralKeyString:SetWordWrap(false)
679 astralKeyString:SetFormattedText("|cffffd200Current Keystone|r\n%d - %s", keyLevel, e.GetMapName(dungeonID))
680 astralKeyString:SetWordWrap(true)
681 astralKeyString:SetPoint('TOP', characterNameString, 'BOTTOM', 3, -4)
682 gameInfoString:SetPoint('TOP', astralKeyString, 'BOTTOM', 0, 0)
683 astralKeyString:Show()
684 stringShown = true
685 FriendsTooltip.height = FriendsTooltip:GetHeight() + astralKeyString:GetStringHeight()
686 FriendsTooltip.maxWidth = max(FriendsTooltip.maxWidth, astralKeyString:GetStringWidth() + left)
687 else
688 astralKeyString:SetText('')
689 astralKeyString:Hide()
690 gameInfoString:SetPoint('TOP', characterNameString, 'BOTTOM', 0, -4)
691 end
692 else
693 astralKeyString:SetText('')
694 astralKeyString:Hide()
695 gameInfoString:SetPoint('TOP', characterNameString, 'BOTTOM', 0, -4)
696 end
697 end
698 end
699
700
701 FriendsTooltip:SetWidth(min(FRIENDS_TOOLTIP_MAX_WIDTH, FriendsTooltip.maxWidth + FRIENDS_TOOLTIP_MARGIN_WIDTH));
702 FriendsTooltip:SetHeight(FriendsTooltip.height + (stringShown and 0 or FRIENDS_TOOLTIP_MARGIN_WIDTH))
703 end
704
705 function OnHide()
706 FriendsTooltipAstralKeysInfo1:SetText('')
707 FriendsTooltipAstralKeysInfo1:Hide()
708 end
709
710 local buttons = FriendsListFrameScrollFrame.buttons
711 for i = 1, #buttons do
712 local button = buttons[i]
713 button:HookScript("OnEnter", OnEnter)
714 end
715
716 FriendsTooltip:HookScript('OnHide', OnHide)
717 --hooksecurefunc('FriendsFrameTooltip_Show', OnEnter)
718end
719
720local function TooltipHook(self)
721 if not AstralKeysSettings.general.show_tooltip_key.isEnabled then return end
722
723 local _, uid = self:GetUnit()
724 if not UnitIsPlayer(uid) then return end
725
726 local unitName, unitRealm = UnitFullName(uid)
727 unitRealm = ((unitRealm ~= '' and unitRealm) or GetRealmName()):gsub('%s+', '')
728 local unit = string.format('%s-%s', unitName, (unitRealm or GetRealmName()):gsub('%s+', ''))
729
730 local id = e.UnitID(unit)
731 if id then
732 GameTooltip:AddLine(' ')
733 GameTooltip:AddLine('Current Keystone')
734 GameTooltip:AddDoubleLine(e.GetMapName(e.UnitMapID(id)), e.UnitKeyLevel(id), 1, 1, 1, 1, 1, 1)
735 return
736 end
737
738 local id = e.FriendID(unit)
739 if id then
740 GameTooltip:AddLine(' ')
741 GameTooltip:AddLine('Current Keystone')
742 GameTooltip:AddDoubleLine(e.GetMapName(AstralFriends[id][4]), AstralFriends[id][5], 1, 1, 1, 1, 1, 1)
743 return
744 end
745end
746
747GameTooltip:HookScript('OnTooltipSetUnit', TooltipHook)
748
749local function FriendUnitFunction(self, unit, class, mapID, keyLevel, weekly_best, faction, btag)
750 self.unitID = e.FriendID(unit)
751 self.levelString:SetText(keyLevel)
752 self.dungeonString:SetText(e.GetMapName(mapID))
753 if weekly_best and weekly_best > 1 then
754 local color_code = e.GetDifficultyColour(weekly_best)
755 self.bestString:SetText(WrapTextInColorCode(weekly_best, color_code))
756 else
757 self.bestString:SetText(nil)
758 end
759 --self.weeklyTexture:SetShown(cache == 1)
760 if btag then
761 if tonumber(faction) == e.FACTION then
762 self.nameString:SetText( string.format('%s (%s)', WrapTextInColorCode(btag:sub(1, btag:find('#') - 1), COLOR_BLUE_BNET), WrapTextInColorCode(unit:sub(1, unit:find('-') - 1), select(4, GetClassColor(class)))))
763 else
764 self.nameString:SetText( string.format('%s (%s)', WrapTextInColorCode(btag:sub(1, btag:find('#') - 1), COLOR_BLUE_BNET), WrapTextInColorCode(unit:sub(1, unit:find('-') - 1), 'ff9d9d9d')))
765 end
766 else
767 self.nameString:SetText(WrapTextInColorCode(unit:sub(1, unit:find('-') - 1), select(4, GetClassColor(class))))
768 end
769 if e.IsFriendOnline(unit) then
770 self:SetAlpha(1)
771 else
772 self:SetAlpha(0.4)
773 end
774end
775
776e.AddUnitFunction('FRIENDS', FriendUnitFunction)