Thread Tools Display Modes
05-18-14, 05:43 PM   #1
Niketa
A Wyrmkin Dreamwalker
 
Niketa's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2013
Posts: 54
BNplayer Hyperlink

I am trying to create a player link for a copy-cat chat message, but I'm having trouble understanding the arguments that it needs.
Basically what the addon is supposed to do is to send a chat message when a player who is logged onto the Battle.net desktop app only logs onto a game. The message mimics the one sent when your Battle.net friends normally log on without the client ("Soandso (W Toonname) has come online.").

I found the following code in Interface\FrameXML\ChatFrame.lua:

lua Code:
  1. playerLink = "|HBNplayer:"..arg2..":"..arg13..":"..arg11..":"..chatGroup..(chatTarget and ":"..chatTarget or "").."|h"

However, I'm having issues trying to figure out what each of the arguments are and how to incorporate it into my code.

lua Code:
  1. local events = CreateFrame("Frame")
  2.       events:RegisterEvent("ADDON_LOADED")
  3.       events:RegisterEvent("PLAYER_LOGIN")
  4.       events:RegisterEvent("BN_TOON_NAME_UPDATED")
  5.       events:RegisterEvent("BN_FRIEND_TOON_ONLINE")
  6.       events:RegisterEvent("BN_FRIEND_ACCOUNT_OFFLINE")
  7.       events:SetScript("OnEvent", function(self, event, ...)
  8.           return self[event] and self[event](self, event, ...)
  9.       end)
  10.  
  11. local Friends = {}
  12.  
  13. -- Get online players.
  14. function events:ADDON_LOADED(event, addon)
  15.     if addon == "FriendsFixes" then
  16.         for x = 1, BNGetNumFriends() do
  17.             local presenceID = BNGetFriendInfo(x)
  18.             Friends[presenceID] = {BNGetFriendInfo(x)}
  19.         end
  20.     end
  21. end
  22.  
  23. function events:PLAYER_LOGIN(event, ...)
  24.     for x = 1, BNGetNumFriends() do
  25.         local presenceID = BNGetFriendInfo(x)
  26.         Friends[presenceID] = {BNGetFriendInfo(x)}
  27.     end
  28. end
  29.  
  30. -- Prevents double login spam from App.
  31. local function FilterBNLoginSpam(self, event, type, ...)
  32.     local presenceID = select(12, ...)
  33.  
  34.     if type == "FRIEND_ONLINE" and presenceID then
  35.         if Friends[presenceID][8] then
  36.             return true
  37.         else
  38.             for x = 1, BNGetNumFriends() do
  39.                 local presenceID = BNGetFriendInfo(x)
  40.                 Friends[presenceID] = {BNGetFriendInfo(x)}
  41.             end
  42.         end
  43.     end
  44. end
  45.  
  46. ChatFrame_AddMessageEventFilter("CHAT_MSG_BN_INLINE_TOAST_ALERT", FilterBNLoginSpam)
  47.  
  48. -- -- Announces login while logged into App.
  49. function events:BN_TOON_NAME_UPDATED(event, ...)
  50.     for x = 1, BNGetNumFriends() do
  51.         local friendPresenceID, friendName, friendBtag, _, friendToonName, friendToonID, friendGame, friendOnline = BNGetFriendInfo(x)
  52.         local friends = Friends[friendPresenceID]
  53.  
  54.         if friends and friends[7] ~= friendGame then
  55.             if friends[7] == "App" then
  56.                 print(BATTLENET_FONT_COLOR_CODE .. friendName .. " (" .. BNet_GetClientEmbeddedTexture(friendGame, 14) .. (friendToonName and friendToonName or "") .. ") has come online.")
  57.             end
  58.             Friends[friendPresenceID] = {BNGetFriendInfo(x)}
  59.         end
  60.     end
  61. end
  62.  
  63. events.BN_FRIEND_TOON_ONLINE = events.BN_TOON_NAME_UPDATED
  64.  
  65. function events:BN_FRIEND_ACCOUNT_OFFLINE(event, ...)
  66.     for x = 1, BNGetNumFriends() do
  67.         local presenceID = BNGetFriendInfo(x)
  68.         Friends[presenceID] = {BNGetFriendInfo(x)}
  69.     end
  70. end

Last edited by Niketa : 05-18-14 at 10:59 PM.
  Reply With Quote
05-19-14, 12:18 AM   #2
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Where the default UI uses "arg1" style names for event arguments, they're just sequentially numbered, with the first argument being arg1 and the 15th argument being arg15, etc. So just look at the list of arguments for the event you're processing, and number them from 1 on up.

For any chat message event, arg2 is the sender's name and arg11 is a line counter uniquely identifying the message (used when reporting, etc.). For a Battle.net chat event, arg13 is the sender's presence ID. You'd have to read back further in the default UI code you're looking at to see what chatGroup and chatTarget are exactly, but I'd guess they are probably identifying the channel and sender.

The code you posted doesn't seem to actually be related to the functionality you described -- did you post the wrong code, maybe? -- but rather than duplicating default UI code to reproduce default UI functionality, I'd just call the default UI's own event handler and let it do all the processing, eg. to mimic a "friend logged in" event for the friend with presenceID 5:

Code:
ChatFrame_MessageEventHandler(ChatFrame1, "CHAT_MSG_BN_INLINE_TOAST_ALERT", "FRIEND_ONLINE", "|Kf5|k00000000000000000000|k", nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, 5)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
05-19-14, 08:28 AM   #3
Niketa
A Wyrmkin Dreamwalker
 
Niketa's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2013
Posts: 54
The code I wrote has a table of friends info and when someone logs on (BN_TOON_NAME_UPDATED) it updates info for that person and if the game has changed and is not "App" it prints a login message.

I had an awful hard time with this as it's not something I usually deal with but the whole process seemed frustrating. So if there is an easier and more efficient way I'm all ears. This is just such a pet peeve for me about the app. Anyway, with the way I'm doing it I don't think it's even possible to get all the arguments since I'm the one making the message right?

Also heading out to work so I'm not at my computer to check but if I'm understanding right the code you posted will do a real login message and the only arg needed is the presence is in 2 places?
  Reply With Quote
05-19-14, 12:52 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Niketa View Post
... the only arg needed is the presence is in 2 places?
No. Look at the code again. The first argument is a string describing what happened (in this case it's "FRIEND_ONLINE") and indicating which global string to use for the actual displayed message, the second argument is an escaped name string for the relevant player (see note below), the 11th argument is a numeric line ID (in this case there isn't a real one since it isn't a real message from the server, but the code expects a number here, so just use 0) and only the 13th argument is the presence ID.

A real event may include other args, but only those ones are actually used in that code path so you can just pass nil values for the rest.

(Note on name strings: Battle.net names are never returned or passed as text, but use a special escape sequence in which the string of zeroes is transformed into the actual name when displayed, but the actual name isn't accessible to addons. The format is "|K" to start the sequence, followed by "f" for the full name or "g" for the first name or "s" for the last name, followed by the presence ID, followed by "|k", followed by a bunch of zeroes that act as placeholders, followed by a final "|k". Extra placeholder zeroes are discarded so it's better to err on the side of too many placeholders than too few. BattleTag friends will only show the BattleTag name regardless of f/g/s, but those flags have meaning for Real ID friends.)

Originally Posted by Niketa View Post
The code I wrote has a table of friends info and when someone logs on (BN_TOON_NAME_UPDATED) it updates info for that person and if the game has changed and is not "App" it prints a login message.
If that's all you want to do, then you're vastly overcomplicating things.

Not tested, but this should probably work, and also do "logout" messages when someone logs out of a game but is still logged into the app:

Code:
local t = {}

local f = CreateFrame("Frame")
f:RegisterEvent("BN_FRIEND_ACCOUNT_OFFLINE")
f:RegisterEvent("BN_FRIEND_TOON_ONLINE")
f:RegisterEvent("BN_TOON_NAME_UPDATED")

f:SetScript("OnEvent", function()
	for i = 1, BNGetNumFriends() do
		local id, name, _, _, _, _, client, online = BNGetFriendInfo(i)
		local prev = t[id]
		if prev and prev ~= client then
			local message = prev == "App" and "FRIEND_ONLINE" or client == "App" and "FRIEND_OFFLINE"
			if message then
				for i = 1, NUM_CHAT_FRAMES do
					ChatFrame_MessageEventHandler(_G["ChatFrame"..i], "CHAT_MSG_BN_INLINE_TOAST_ALERT", message, name, nil, nil, nil, nil, nil, nil, nil, nil, 0, nil, id)
				end
			end
		end
		t[presenceID] = online and client or nil
	end
end)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
05-19-14, 01:36 PM   #5
Niketa
A Wyrmkin Dreamwalker
 
Niketa's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2013
Posts: 54
Ok that makes a lot more sense. I think mainly the name string was what confused me and it all just looked like nonsense at a quick glance. I also figured that there must have been an easier approach, but unfortunately at times I forget that some parts of the default UI are available to use.

I look forward to testing your code when I get home because, believe me, I get really frustrated when it doesn't announce these (I lead raids and it makes it hard to invite people if they have to switch toons).

Anyway, I've also been noticing double messages for when someone logs onto the app. I don't think it was from an addon, I will have to check again later, but I did have a part to try to get rid of the extra message with a chat filter (in the original code). Is a chat filter the best way to do it?

Thank you. I know I still have a million things to learn and I appreciate your thorough explanation.
  Reply With Quote
05-19-14, 05:56 PM   #6
Niketa
A Wyrmkin Dreamwalker
 
Niketa's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2013
Posts: 54
I had to make a couple changes because of some lua errors (arg4 couldn't be nil and NUM_CHAT_FRAMES was not working).

lua Code:
  1. local events = CreateFrame("Frame")
  2.       events:RegisterEvent("BN_TOON_NAME_UPDATED")
  3.       events:RegisterEvent("BN_FRIEND_TOON_ONLINE")
  4.       events:RegisterEvent("BN_FRIEND_ACCOUNT_OFFLINE")
  5.  
  6. local t = {}
  7.  
  8. events:SetScript("OnEvent", function()
  9.     for x = 1, BNGetNumFriends() do
  10.         local id, name, _, _, _, _, client, online = BNGetFriendInfo(x)
  11.         local prev = t[id]
  12.         if prev and prev ~= client then
  13.             local message = prev == "App" and "FRIEND_ONLINE" or client == "App" and "FRIEND_OFFLINE"
  14.             if message then
  15.                 for i = 1, NUM_CHAT_WINDOWS do
  16.                     ChatFrame_MessageEventHandler(_G["ChatFrame"..i], "CHAT_MSG_BN_INLINE_TOAST_ALERT", message, name, nil, 0, nil, nil, nil, nil, nil, nil, 0, nil, id)
  17.                 end
  18.             end
  19.         end
  20.         t[id] = online and client or nil
  21.     end
  22. end)

It appears to be working so far. However, is there a way for it to display the message showing what game/character they log on? Right now this code is working in that it's outputting the message but for some reason it's showing the login like it was an app login.

For example (we'll use "A" as the app texture and "W" as the WoW texture), say my btag is Niketa and I want to log onto a toon named Rainbowcat.

I log onto the app.
Niketa (A Niketa) has come online.

I then log into WoW and onto Rainbowcat.
Niketa (A Niketa) has come online.

However, I would like it to display the message as if I wasn't logged into the app and I logged in from the normal client:

Niketa (W Rainbowcat) has come online.

Also when I first logged in it posted 12 people had "come online". Is there anything in the code that would have caused this or did 12 of my friends all happen to come online at the same time? lol
I just logged out and back in and 7 people "came online".

Last edited by Niketa : 05-19-14 at 05:58 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » BNplayer Hyperlink


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off