Reply
Thread Tools Display Modes
Unread 12-25-13, 10:13 PM   #1
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Chat message colours

Hey all, Happy Christmas!

Just a quick question...

Does anyone know of a simple way to obtain the colour of the most recently shown text in the ChatFrames?

I have a function in my addon which makes a frame 'pulse' when a new message is received, kinda like:

Lua Code:
  1. ChatButton.Pulse = function(self)
  2.   self.fadeStep = ( (self.pulseIntensity * 2) / (self.pulseDuration * GetFramerate()) );
  3.   self.isFading = nil;
  4.   self.pulseTexture:SetTexture(1, 1, 1); -- [color="Red"]to match chatType colour[/color]
  5.   return ( self.pulseIsEnabled and (not self.alpha) ) and self:SetScript("OnUpdate", self.OnUpdate);
  6. end

This doesn't really relate to the question I guess, but the onupdate code is:

Lua Code:
  1. ChatButton.OnUpdate = function(self)
  2.   self.alpha = self.isFading and ( (self.alpha or 0) - self.fadeStep ) or ( (self.alpha or 0) + self.fadeStep );
  3.   if ( (self.alpha >= 0) and (self.alpha <= self.pulseIntensity) ) then
  4.     return self.pulseTexture:SetAlpha(self.alpha);
  5.   elseif self.isFading then
  6.     self.alpha, self.fadeStep, self.isFading = nil, nil, nil;
  7.     return self:SetScript("OnUpdate", nil);
  8.   end
  9.   self.alpha, self.isFading = self.pulseIntensity, true;
  10. end

Thanks in advance for any possible guidance

Aanson
__________________
__________________
Aanson is offline   Reply With Quote
Unread 12-26-13, 03:59 AM   #2
ravagernl
A Pyroguard Emberseer
AddOn Author - Click to view addons
Join Date: Feb 2006
Posts: 1,145
It depends on what messages you want to listen to. If you don't care about what is added, just do a hook on ChatFrame:AddMessage.
ravagernl is offline   Reply With Quote
Unread 12-26-13, 04:41 AM   #3
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,141
If you need to know the actual message type (rather than just what color the message was printed in) you will need to either (a) use chat filters or (b) hook ChatFrame_MessageEventHandler. Both suffer from the same problem, in that both will get you every single chat message, whether or not it's set to show in a specific frame, or any frame, so you'll have to figure that out yourself.

Code:
local eventToCategory = {}

local function SaveLastMessageType(frame, event, ...)
	local category = eventToCategory[event]
	-- This maps eg. "CHAT_MSG_PARTY_LEADER" to "PARTY"
	-- which you can look up in ChatTypeInfo etc.
	
	-- Insert code here to figure out whether this frame
	-- should display this category, and return out if not.
	
	frame.lastMessageType = category
	-- Now you can reference this value in your other scripts.
end

for category, events in pairs(CHAT_CATEGORY_LIST) do
	for i = 1, #events do
		local event = "CHAT_MSG_" .. events[i]
		eventToCategory[event] = category
		ChatFrame_RegisterMessageEventFilter(event, SaveLastMessageType)
	end
end
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 12-30-13, 08:46 AM   #4
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Thanks very much. The event filtering function is just what I'm after.
__________________
__________________
Aanson is offline   Reply With Quote
Unread 02-06-14, 07:36 PM   #5
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Out of interest, see if I was just looking for the colour used for the last message, is there a simple way of going about that?
__________________
__________________
Aanson is offline   Reply With Quote
Unread 02-07-14, 04:13 AM   #6
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,141
Do what ravagernl suggested several posts up:

Code:
local lastR, lastG, lastB
hooksecurefunc(ChatFrame1, "AddMessage", function(self, message, r, g, b, ...)
     lastR, lastG, lastB = r or 1, g or 1, b or 1
end)
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 02-08-14, 01:12 PM   #7
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
That's great to know, thanks.

I need to know the message type (ChatTypeInfo) and the Chat Frame it was posted to.

I can hook the AddMessage function of each ChatFrame to establish the latter.

Cheers
__________________
__________________

Last edited by Aanson : 02-08-14 at 01:13 PM. Reason: Typo
Aanson is offline   Reply With Quote
Unread 02-08-14, 09:54 PM   #8
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,141
If you need that, just use a filter function, as in the code I'd posted previously; you can get the color from ChatTypeInfo, as detailed in the comments in that code. You do not need to hook multiple functions and deal with tracking messages between them.
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 02-09-14, 02:36 PM   #9
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Yeah, I like the idea of simply hooking ChatFrame_MessageEventHandler too. I think I may be able to accomplish everything with that one hook. I'll put something together and find out.
__________________
__________________

Last edited by Aanson : 02-09-14 at 03:18 PM.
Aanson is offline   Reply With Quote
Unread 02-10-14, 01:45 PM   #10
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,141
Originally Posted by Aanson View Post
Yeah, I like the idea of simply hooking ChatFrame_MessageEventHandler too. I think I may be able to accomplish everything with that one hook. I'll put something together and find out.
Don't hook CF_MEH. Just use the "filter" system that Blizzard put into the game for exactly this purpose. >_<
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addonTurn any code into an addonMore addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please don’t PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 02-11-14, 01:05 AM   #11
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by Phanx View Post
Don't hook CF_MEH. Just use the "filter" system that Blizzard put into the game for exactly this purpose. >_<
I implemented a function using event filters very much like the one suggested in your first post. It worked well, but like you'd said in that post, I still needed to get round the issue of working out which chat frames (if any) the message would be displayed on.

I should have said all this in my initial post, but (although I know that event filtering can be used for other things) the feature I'm adding doesn't need to filter chat messages (in-fact, it doesn't even need to know the content of the message). It's simply an alert feature for when a particular type of message is received. A sound will be played and the chat button will 'pulse' the colour of the chat message. It also auto-undocks the chat window (this is all dependent on user settings).

When I say auto-undock, I'm not referring to undocking a ChatFrame from GENERAL_CHAT_DOCK. It's a feature of my chat module which essentially allows the user to show/hide all chat frames within GENERAL_CHAT_DOCK with a hotkey.

In order to work properly, the function requires:

1. A guarantee that the message will actually be displayed.

2. The event (firstly so that I can get the message event category via CHAT_CATEGORY_LIST which I can then compare to user preferences and secondly, so that I can get the r, g, b values for the message).

3. The chat frame(s) on which the message will be displayed.

After a good bit of experimentation, I have eventually settled on just hooking each chat frame's 'OnEvent' handler. To avoid unnecessary processing (to prevent the code from being read for config/system events), the first line of the hooked function is:

Lua Code:
  1. if ((strsub(event, 1, 8) ~= "CHAT_MSG") or (not self.isDocked)) then return; end

I've found that this works well, because due to the system already implemented in Bliz's ChatFrame.lua, each particular event will only fire for chat frames which are registered to receive them.

I know that if I added a filter, I could retrieve the channel name (arg9) and work out which frames receive that channel, but I'm hoping that that won't be necessary.

The obvious downside to hooking OnEvent is that my function will bypass not only the user-created filters, but also MessageEventHandler which will result in false positives. I'm going to be testing it a lot to see what kind of impact this has.

Just so you know, I don't think for a second that this is the perfect way to handle what I'm attempting to achieve so any suggestions which encompass all of the function's requirements above are always welcome.
__________________
__________________

Last edited by Aanson : 02-11-14 at 01:15 AM.
Aanson is offline   Reply With Quote
Unread 02-12-14, 10:06 AM   #12
Lombra
A Chromatic Dragonspawn
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 195
Chat filter functions receives the [chat]frame as the first argument and also MessageEventHandler is called as a result of OnEvent, so I don't believe you gain anything by hooking OnEvent directly.
__________________
Grab your sword and fight the Horde!
Lombra is online now   Reply With Quote
Unread 02-14-14, 03:57 AM   #13
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 128
What if AddMessage is called like this:
Code:
:AddMessage("|cffff0000Hello.|r")
That hook won't know about that red. Also, what if the message has multiple colors in it? Which is "right"?
pelf is offline   Reply With Quote
Unread 02-14-14, 05:02 PM   #14
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by Lombra View Post
Chat filter functions receives the [chat]frame as the first argument and also MessageEventHandler is called as a result of OnEvent, so I don't believe you gain anything by hooking OnEvent directly.
MessageEventFilters have nothing to do with frames, so the chat frame isn't it's first argument (event is). The filter doesn't need to know which frame (if any) a message will be displayed on. It just provides the ability to return out of CF_MEH early before it starts calling AddMessage to appropriate chat frames.
__________________
__________________
Aanson is offline   Reply With Quote
Unread 02-14-14, 05:04 PM   #15
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by pelf View Post
What if AddMessage is called like this:
Code:
:AddMessage("|cffff0000Hello.|r")
That hook won't know about that red. Also, what if the message has multiple colors in it? Which is "right"?
What's "right" is whatever colour has been chosen for any given message type. Eg for vanilla, guild chat is green, party blue, whisper pink etc etc. The function I've written provides a visual representation of what type of message has been received, so it doesn't matter if a message has 1 or 10 colours in it.

The only relevant colour is the one which has been chosen by the user to represent the chat type being displayed. Your example would default to Channel1 which would not be monitored.
__________________
__________________

Last edited by Aanson : 02-14-14 at 06:27 PM.
Aanson is offline   Reply With Quote
Unread 02-14-14, 06:07 PM   #16
Lombra
A Chromatic Dragonspawn
 
Lombra's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2006
Posts: 195
Originally Posted by Aanson View Post
MessageEventFilters have nothing to do with frames, so the chat frame isn't it's first argument (event is). The filter doesn't need to know which frame (if any) a message will be displayed on. It just provides the ability to return out of CF_MEH early before it starts calling AddMessage to appropriate chat frames.
http://wow.go-hero.net/framexml/1768...Frame.lua#2840
__________________
Grab your sword and fight the Horde!
Lombra is online now   Reply With Quote
Unread 02-14-14, 06:25 PM   #17
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
But that points to CF_MEH which is where 'self' is coming from. I know that MessageEventHandler is passed with chat frame as it's 1st arg. Filters don't. If you check out ChatFrame_AddMessageEventFilter (event, filter) line 3193 of ChatFrame.lua, you'll see what I'm talking about.
__________________
__________________
Aanson is offline   Reply With Quote
Unread 02-14-14, 06:40 PM   #18
pelf
Sentient Plasmoid
 
pelf's Avatar
Premium Member
Join Date: May 2008
Posts: 128
Originally Posted by Aanson View Post
The only relevant colour is the one which has been chosen by the user to represent the chat type being displayed. Your example would default to Channel1 which would not be monitored.
Well, if all that's actually needed is what channel the last message came through, isn't there a much easier way to do that? I also wouldn't immediately expect that someone would refer to channels as "colors".
pelf is offline   Reply With Quote
Unread 02-14-14, 06:44 PM   #19
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
I'm pretty sure that I've found a good way of getting everything I need now, using Ravagernl's suggestion.

Lua Code:
  1. local frame;
  2. for i = 1, NUM_CHAT_FRAMES do
  3.   frame = _G["ChatFrame"..i];
  4.   frame:HookScript("OnEvent", function(self, event, ...)
  5.     self.lastEvent = (self.isDocked and MONITORED_EVENTS[event]) and event;
  6.   end);
  7.   hooksecurefunc(frame, "AddMessage", function(self, message, r, g, b, ...)
  8.     if (not self.lastEvent) then return; end
  9.     -- do my thing...
  10.   end);
  11. end


That way I have a guarantee that the message will actually be displayed. It should be reliable because self.lastEvent will always be obtained immediately before AddMessage gets called.

Cheers all
__________________
__________________

Last edited by Aanson : 02-14-14 at 06:56 PM.
Aanson is offline   Reply With Quote
Unread 02-14-14, 06:47 PM   #20
Aanson
A Flamescale Wyrmkin
Join Date: Aug 2009
Posts: 123
Originally Posted by pelf View Post
Well, if all that's actually needed is what channel the last message came through, isn't there a much easier way to do that? I also wouldn't immediately expect that someone would refer to channels as "colors".
I think there's been some confusion. Blizzard set up channel colouring precisely so that people would associate colours with channels, so I'm not really sure what you mean. The channel the message is displayed on isn't all I need either. You may want to read prev comments.

Anyhoo, I've sorted it now.
__________________
__________________

Last edited by Aanson : 02-14-14 at 06:53 PM.
Aanson is offline   Reply With Quote
Reply

Go BackWoWInterface » Developer Discussions » General Authoring Discussion » Chat message colours

Thread Tools
Display Modes

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