#0 - Feb. 5, 2008, 3:36 p.m.
With the release of patch 2.4.0, we’ve made some enormous changes to the existing combat log. While this will result in some hard work now, it should be easier to maintain your AddOns in the future.
The feature we’re most proud of is the ability to filter your combat log. The combat log stores the last five minutes worth of raw combat events. Filters can be setup on multiple criteria, affiliation, ownership, etc. Any events that match the current filter are passed through the client via the COMBAT_LOG_EVENT message. The combat log filter is global. However, AddOns which want to parse all events the moment they happen can register for the COMBAT_LOG_EVENT_UNFILTERED message. This should allow all existing AddOns to still respond to combat events without a complicated middle-manager AddOn.
While the default combat log will only be setting 1-2 filters at a time, the WoW client supports many simultaneous filters. It’s possible to setup multiple filters to filter very specific source-target-event combinations. If a combat log event passes any of the filters, the COMBAT_LOG_EVENT event fires. This allows AddOns to define extremely specific settings we chose not expose in the base UI.
The new combat log will be coming with two text formats. One is the familiar, grammatically correct sentences with substitutions. The other is a terse format, containing the source, target, spell, action and result. There will be a number of ways to manipulate the formatting, from unit name coloring to coloring the damage numbers by their magic school. The settings used for these formats are stored in the Blizzard_CombatLog_Filters variable.
The result of the new terse format is that it’s very easy to write AddOns to modify or extend the format which ships with 2.4.0. In the formatting section, you can read up on a quick demonstration of how to convert the combat log to a “Nurfed” style combat log. While you can do a lot by just adjusting the settings within WoW, it’s also possible to provide an AddOn that changes the strings used to generate the Combat Log messages. This allows for more extensive formatting changes without re-writing the entire parsing engine. See the Formatting Section for an example.
The whole combat log also supports a new coloring model, based on context. While by default, entire lines are a single color, highlighting the most important details. The combat log also supports coloring just unit names, spells, actions and damage numbers. Spells and damage can also be colored by school. However, there are several features not exposed in the base UI that AddOns can use right away. These are event-specific coloring, unit coloring with greater granularity and the ability to customize the list of highlighted events.
There are several other formatting related features. You can enable timestamps which show the time that spell or attack happened. You can show or hide square braces, change formatting without refreshing the combat log and disable the display of raid icons. These features were too niche to go into the base UI, but can be easily exposed for power users. By now you’ve already thought of some features of your own and are ready to get to coding. So let’s jump straight to some examples.
Formatting & Coloring
One of the major combat log formats we considered while redoing the combat log was the Nurfed Combat Log format. This combat log format was very concise, made heavy use of color-coding and was one of the final candidates for the combat log. We eventually axed it on the basis of being too overwhelming for new users. However, we left in all of the options to convert the current combat log into the Nurfed combat log.
Combat Log Settings -> Colors
Me -> Green
My Pet -> Dark Green
Friends -> Blue
Enemies -> Red
Neutral -> Yellow
Unit Names -> Checked
Spell Names -> Checked
Spell Color-by-School -> Checked
Damage Number -> Checked
Damage Color-by-School -> Checked
Damage School -> Checked
Entire Line -> Unchecked
All Highlighting Options-> Unchecked
Verbose -> Unchecked
Braces -> Checked
Timestamps -> Checked
However, some people may want it even more terse than that. For this, we present:
Hyper Condensed Mode
To get rid of the word “Fire” and “Frost” type:
/script TEXT_MODE_A_STRING_VALUE_SCHOOL = “”;
That will remove the Fire from “55 Fire”. However, let’s go even farther:
(Critical) (Crushing) (Blocked) (Resisted)
All of these are really long. Let’s compress them:
TEXT_MODE_A_STRING_RESULT_RESISTED = "R";
TEXT_MODE_A_STRING_RESULT_BLOCKED = "B";
TEXT_MODE_A_STRING_RESULT_ABSORBED = "A";
TEXT_MODE_A_STRING_RESULT_CRITICAL = "C";
TEXT_MODE_A_STRING_RESULT_GLANCING = "G";
TEXT_MODE_A_STRING_RESULT_CRUSHING = "Cr";
Now we get
[You] [Fireball] Hit [Spider] 64. (C) (5 R)
Filters consistent of 3 parts:
Source & Target can be one of two types:
If it is a string, then that string is assumed to be the GUID of the unit in question. If it’s a number, it is assumed to be a bitfield assembled from the following criteria:
COMBATLOG_OBJECT_AFFILIATION_MINE = 0x00000001;
COMBATLOG_OBJECT_AFFILIATION_PARTY = 0x00000002;
COMBATLOG_OBJECT_AFFILIATION_RAID = 0x00000004;
COMBATLOG_OBJECT_AFFILIATION_OUTSIDER = 0x00000008;
COMBATLOG_OBJECT_AFFILIATION_MASK = 0x0000000F;
COMBATLOG_OBJECT_REACTION_FRIENDLY = 0x00000010;
COMBATLOG_OBJECT_REACTION_NEUTRAL = 0x00000020;
COMBATLOG_OBJECT_REACTION_HOSTILE = 0x00000040;
COMBATLOG_OBJECT_REACTION_MASK = 0x000000F0;
COMBATLOG_OBJECT_CONTROL_PLAYER = 0x00000100;
COMBATLOG_OBJECT_CONTROL_NPC = 0x00000200;
COMBATLOG_OBJECT_CONTROL_MASK = 0x00000300;
-- Unit type
COMBATLOG_OBJECT_TYPE_PLAYER = 0x00000400;
COMBATLOG_OBJECT_TYPE_NPC = 0x00000800;
COMBATLOG_OBJECT_TYPE_PET = 0x00001000;
COMBATLOG_OBJECT_TYPE_GUARDIAN = 0x00002000;
COMBATLOG_OBJECT_TYPE_OBJECT = 0x00004000;
COMBATLOG_OBJECT_TYPE_MASK = 0x0000FC00;
-- Special cases (non-exclusive)
COMBATLOG_OBJECT_TARGET = 0x00010000;
COMBATLOG_OBJECT_FOCUS = 0x00020000;
COMBATLOG_OBJECT_MAINTANK = 0x00040000;
COMBATLOG_OBJECT_MAINASSIST = 0x00080000;
COMBATLOG_OBJECT_RAIDTARGET1 = 0x00100000;
COMBATLOG_OBJECT_RAIDTARGET2 = 0x00200000;
COMBATLOG_OBJECT_RAIDTARGET3 = 0x00400000;
COMBATLOG_OBJECT_RAIDTARGET4 = 0x00800000;
COMBATLOG_OBJECT_RAIDTARGET5 = 0x01000000;
COMBATLOG_OBJECT_RAIDTARGET6 = 0x02000000;
COMBATLOG_OBJECT_RAIDTARGET7 = 0x04000000;
COMBATLOG_OBJECT_RAIDTARGET8 = 0x08000000;
COMBATLOG_OBJECT_NONE = 0x80000000;
COMBATLOG_OBJECT_SPECIAL_MASK = 0xFFFF0000;
A unit can only be one of the following four categories:
Here’s a quick explanation of how these flags are broken down:
A unit’s affiliation is the unit’s relationship relative to YOU. Either it is owned by you, your party, your raid or someone else.
This is the unit’s faction reaction, relative to you. Anything that hates you is Hostile, anything that is friendly with you is Friendly, everything else is Neutral.
This is who owns this object. It can only be controlled by a player or the server.
This is the way the unit is currently being controlled. Units directly controlled by their owner are players. Units controlled by the server are NPCs. Pets are controlled by another player or unit. Guardians are automatons that are not controlled, but automatically defend their master. Objects are everything else, such as Traps.
The result is that these bits can tell you what kind of unit that combat log object was.
A player who is dueling you is 0x0548.
(A hostile outsider who is both owned by a player and controlled as a player)
A player who was mind controlled that attacks you is 0x1148.
(A hostile outsiders who is owned by a player, but controlled as a pet)
The default filters are constructed by summing certain bit combinations together:
COMBATLOG_FILTER_MINE = bit.bor (
This means that everything colored mine by default must be affiliated with me, friendly, controlled by a player and be a player.
Any unit that matches at least one bit in each of the four exclusive categories will pass the filter test. Filters can have more than one bit set in a category.
COMBATLOG_FILTER_FRIENDLY_UNITS = bit.bor(
This will allow messages relating to any unit who has a friendly reaction with you, the player. (Another way to do this is to use the “_MASK” suffixed globals, rather than specifying all bits, but I did it this way to make the point clear).