The Complete Guide to Pins
This document will explain in detail how pins work, what they can be used for, and provide many examples to help you unlock the full potential of pins. Let's start by talking briefly about the structure of pages in Warcraft Logs (WCL)WCL provides three views of data: the Analytical View, the Events View and the Combat Replay view. The Analytical View and Events View contain a query bar such as the following:
Underneath the query bar is a graph that shows the results of the query specified in the query bar:
Below the graph in Analytical View is a table that also matches the results of the query bar. In the Events View, instead of a table, the actual raw events from the combat log are shown.
What is a Pin?
A pin is an additional query that is executed along with the original query. Pins allow you to modify the original query in a variety of ways. There are four types of pins: decorator pins, badge pins, filter pins, and summary pins. We'll get into what these types mean in more detail in a bit.
Pins can be built using either queries or expressions. Queries work in a manner similar to the main query bar in that you fill out some fields in a user interface in order to select your results. Expressions are built using the WCL Expression Language and are intended for experts and programmers who need to build extremely complex queries that can't be handled by the query UI. Expression Pins can still be shared with others, however, so you don't have to be an expert to use them!
Adding a Pin
Pins are added in one of two ways. You can create a pin by clicking the + sign anywhere you see it in the Analytical View tables. When you add pins using this technique, the pin query will match exactly the query that corresponds to the row of the table. So for example, in the table shown above for Damage Done By All Sources To Garrosh Hellscream, clicking the + sign on the row for Kihrawr will create a new pin that represents the query Damage Done By Kihrawr to Garrosh Hellscream.
You can also click the Add Pin button in the Query Bar to build the pin by hand:
When you click the Add Pin button, you will see the following user interface:
Let's start by focusing on the tabs at the top. These represent four ways to put a new pin into the UI. You can build a pin by creating a new query, by writing a new expression, by pasting an exported pin string, or by adding a saved pin from your personal bookmarks.
Query Pins are built in a fashion similar to the main query bar. Start by selecting what types of events the pin should match. If no types are selected, then all event types will be matched.
If only one type is selected, then additional options will be shown that let you refine your query even further for that event type. For most of the event types, the first additional option will be a dropdown that lets you focus in on friendlies or enemies. This menu is similar to the second menu in the main query bar, e.g., for damage it lets you pick whether you're interested in Damage to Enemies (i.e., Damage Done), Damage to Friendlies (i.e., Damage Taken) or Friendly Fire.
Event Type Options
When only Damage is checked, the following additional options are shown:
Damage events in World of Warcraft are either for direct damage or periodic (i.e., DoT) damage. You can specify which types you want to see using the checkboxes for Direct and Periodic. If you aren't interested in misses, then you can deselect that checkbox. Otherwise misses will be included.
When a damage event hits, it will either be a normal hit or a critical hit. To focus on one or the other, you can use the checkboxes for Normal and Critical.
Damage in World of Warcraft can be either physical or magical (or both). To only look at a specific damage type, e.g., Physical damage, you can use the Physical and Magical checkboxes.
When only Healing is checked, the following additional options are shown:
Healing events in World of Warcraft are either absorbs, direct healing or periodic (i.e., HoT) healing. You can specify which types you want to see using the checkboxes for Direct, Periodic and Absorbs.
When a heal lands, it will either be a normal heal or a critical heal. To focus on one or the other, you can use the checkboxes for Normal and Critical.
When only Buffs/Debuffs is checked, the following additional options are shown:
Use the Buffs and Debuffs checkboxes to focus in on only buffs or debuffs. The remaining checkboxes are for all the various event types that can match. Buffs and debuffs can either be applied, refreshed, removed or have a stack added or removed. If you only want to see initial applications for example, you could check Apply and deselect all the other checkboxes.
The last option in Buffs/Debuffs creates a totally different kind of match. Instead of matching the buff/debuff events themselves, you can choose to match all events that occur on a source or target while a buff/debuff is either present or absent on that actor. This allows you to create some very powerful pin queries.
[The Resource Options are not yet implemented. This section will be filled in once they are.]
The other event types have the standard hostility dropdown that matches the main query bar. At this time they don't have any other additional options though. If that changes, then this document will be updated accordingly.
Sources, Targets And Abilities
Events in World of Warcraft can have a source (the player or NPC carrying out the action), a target (the player or NPC being targeted by the action), and an ability (the action itself). Once you have chosen the event types that you're interested in, you can pick which sources, targets and abilities you care about. The UI for picking sources, targets and abilities is shown below:
The Actors list allows you to specify players/NPCs that can be either the source or the target of an event. As you can see, each option has a textfield to type in a name or ID, and an arrow with a dropdown menu that you can use if you just want to pick an actor or ability the same way that you pick one from the main query bar.
In terms of the query being constructed, the Actors, Sources, Targets and Abilities fields are connected by a logical AND. In other words, if you specify a source and a target, the event will only be matched if both the source and the target match. Within a specific field, e.g., Sources, multiple entries are connected by a logical OR. In other words, if you specify three sources, the event will be matched if any of the sources match.
Let's look first at picking an item from the menu. Suppose I want to select Damage Done To Garrosh Hellscream By Kihrawr as my query. I would first start by filling out the damage type and options as follows:
Next, I would go to the dropdown menu for the sources and select Kihrawr.
Once the actor is picked, it gets committed to the appropriate list (in this case sources). The result shows up as a colored box like so:
Clicking the X in the colored box will undo the addition and get rid of the chosen player, NPC or ability. The other way you can add an actor is by typing the name directly into the textfield. As you type, an autocomplete popup will appear that allows you to pick and commit the result.
When multiple matches exist for an ability, you can either pick a specific option or you can select All Matches to just commit all of them. This is useful when an ability has multiple spell IDs. For example, let's take a look at a mage's Living Bomb ability.
As you can see, there are two Living Bomb abilities that do damage. WCL will include the spell ID to help you differentiate the two in case you're looking for a specific one. If you select All Matches, then both results get committed.
Note that all of the menus and autocompletion respond to the query that you are building. If you build up a pin that is about Damage To Enemies, then the abilities list will automatically include only abilities that were actually used to damage enemies. The more you narrow your query, the better results you will get from the autocomplete and from the menus.
Sometimes you will want to build a query for actors or abilities that are not involved in a fight. You can always hit Enter in the textfield without selecting a result, in which case a name match will be created instead. Putting a name in quotes is also a signal to WCL that you want to match by name, and it won't attempt to autocomplete if you do that. Note that name matches are discouraged when constructing reusable queries, since you can't share them with with users from another locale, but if you're just making a personal query that you don't intend to share, then it's fine.
You can also enter a spell ID or enemy ID in the textfields. This is useful if the ability or enemy didn't occur in the fight you happen to be looking at, but you'd still like it to be part of the query. For example, when building a re-usable tank cooldown pin, you might want to enter tank abilities for every class and not only the classes that were involved in the current fight.
You can chain multiple queries together in a single pin using the logical connectors AND and OR. Queries connected using OR will result in a match if any of the queries matches. Queries connected using AND require that all of the connected queries match the event. To commit your current query and begin a new one chained to the previous one by a connector, you can click on one of the connector buttons (AND/OR):
Warcraft Logs uses an SQL-like language for constructing expressions
You can use the logical operator keywords AND, OR, or NOT to connect multiple conditions together. A AND B means that both A and B must be true. A OR B means that either A or B can be true. NOT A is true when A is false. The AND and OR operators do short-circuit evaluation, so construct your queries accordingly. In other words, for A AND B, if A turns out to be false, then B will not be evaluated.
The following comparison operators are supported:
<, >, <=, >=, =, !=
In addition, the BETWEEN construct can be used to ask if a number or string is between two other values (inclusive). For example:
A between 5 and 20
is true if A is >= 5 and A <= 20.
The following arithmetic operators are supported:
+, -, *, /, %
+ is addition, - is subtraction or negation, * is multiplication, / is division, and % is mod.
Using IN and NOT IN
You can ask if an object is a member of a set (or not a member of a set) using the IN and NOT IN keywords. For example:
A in ("Immerseus", "Congealed Sha", "Sha Puddle")
returns true if A is = to any of the three strings.
You can use case statements. Their syntax matches SQL usage, i.e., you can use either a simple case or a full case statement.
CASE WHEN source.name = "Foo" THEN a WHEN effectiveDamage > 1000 THEN b ELSE c END
The full case statement above has conditions specified with a WHEN statement. If the condition is true (going in order) then the expression under that WHEN block is returned. The ELSE statement holds a default value to return if none of the WHEN conditions are satisfied.
The simple case statement specifies a case value that can then be compared with when values. This is useful when you are always testing equality.
CASE source.name WHEN "Foo" THEN a WHEN "Goo" THEN b ELSE c END
All numbers are Numbers. No floating point numbers are allowed.
Strings can be represented using either single or double quotes, i.e., both "Kihra" and 'Kihra' are valid strings. All string comparisons are case-insensitive, so "Kihra" and "KIHRA" are equivalent.
Some event fields are just simple identifiers, e.g., type
Certain fields have their own subfields. Access to subfields uses a "." notation. For example, you can query for the name of the source actor in an event by typing:
Functions look like objects except they have arguments attached in a parentheses-enclosed comma-separated list. Specific functions below document how many arguments they take and what those arguments should look like.
Every expression is evaluated on all of the events within the specified time range. The following built-in identifiers are supported:
encounterID - Number - The boss ID of the encounter. For example, Garrosh has an ID of 1623. You can use the rankings URLs to see what the IDs are for the various bosses. Trash fights have a value of 0.
encounterSize - Number - The raid size of the encounter. 10-man vs. 25-man, etc.
encounterDifficulty - Number - The difficulty of the encounter. 1 = LFR, 2 = Flex, 3 = Normal, 4 = Heroic, 5 = Mythic, 10 = Dungeon (Mythic+, CMs, FFXIV), 100 = FF/WildStar raids.
encounterEnd - String - How the encounter ended. Possible values are "wipe" and "kill".
encounterDuration - Number - How long the encounter lasted in milliseconds.
encounterBossHealthPercentage - Number - The percentage health of the boss at the end of the pull. A number between 0 and 100.
encounterPhase - Number - The phase an event belongs to. Phases are numbered starting from 1. If a fight has no phases, this number will be 0.
timestamp - Number - The timestamp of the event in milliseconds relative to the start of the fight.
type - String - The type of the event. Warcraft Logs supports the following event types:
begincast, cast, miss, damage, heal, absorbed, healabsorbed, applybuff, applydebuff, applybuffstack, applydebuffstack, refreshbuff, refreshdebuff, removebuff, removedebuff, removebuffstack, removedebuffstack, summon, create, death, destroy, extraattacks, aurabroken, dispel, interrupt, steal, leech, energize, drain, resurrect, encounterstart, encounterend
IMPORTANT: Note that Warcraft Logs does not consider a full absorb to be a miss. It will be represented with a damage event.
inCategory - String -> Boolean - The inCategory function can be used to take advantage of WCL's smart categorization. For example if you want to look at healing events and also implicitly include absorbs, you can use inCategory("healing") = true instead of type = "heal" (which would not catch absorb events). The following categories are supported (and more or less match the Query Pin UI):
damage, healing, auras, dispels, casts, deaths, resources, summons, other
rawDamage - Number - The raw damage for a damage event. This includes absorbs and overkill damage.
effectiveDamage - Number - The effective damage for a damage event. This excludes absorbs and overkill, and it represents how much damage the actor actually took.
absorbedDamage - Number - The amount absorbed for a damage event.
blocked - Number - The amount blocked for a damage event.
overkill - Number - The amount of overkill for a damage event.
rawHealing - Number - The raw healing for a healing/absorb event. This includes absorbs and overheal.
effectiveHealing - Number - The effective healing for a healing/absorb event. This excludes overheal but still includes absorbed healing (e.g., Malkorok or Tortos). absorbedHealing - Number - The amount absorbed for a healing event. For non-absorb heals, it represents the amount absorbed (e.g., on Malkorok or Tortos), but for absorb abilities it is equivalent to effectiveHealing.
isCritical - Boolean - Whether or not a damage or heal event crit.
isTick - Boolean - Whether or not a damage or heal event is periodic, i.e., a DoT or HoT.
isGlancing - Boolean - Whether or not a melee damage event is a glancing blow.
isMultistrike - Boolean - Whether or not a damage or heal event was a multistrike.
missType - String - For a miss, indicates what happened. Possible values are miss, dodge, parry, immune, deflect, reflect, misfire, evade, resist.
stack - Number - The stack count for buff and debuff stack events.
extraAttacks - Number - The number of extra attacks for an extra attacks event.
source - Actor - The source of the event. A special Environment actor is returned if no source exists.
target - Actor - The target of the event. A special Environment actor is returned if no target exists.
ability - Ability - The primary ability for the event.
stoppedAbility - Ability - For steals, breaks and dispels, represents the spell that was dispelled. For interrupts, it represents the spell that was interrupted.
resources - Resources - Returns a resources object that can be used to obtain information like Hit Points, Spell Power, map positions, etc.
feign - Boolean - Returns true if a death event is actually a hunter feign.
killer - Actor - Will match death events if the killing blow that caused the death came from this actor.
killingAbility - Ability - Will match death events if the killing blow that caused the death was from this ability.
absorbedAttacker - Actor - Will match absorbed events if the attacker whose blow was absorbed is this actor.
absorbedAttackerAbility - Ability - Will match absorbed events if the attack that was absorbed came from this ability.
absorbedHealer - Actor - Will match heal absorbed events if the healer whose heal was absorbed is this actor.
absorbedHealerAbility - Ability - Will match absorbed events if the healer whose heal was absorbed came from this ability.More to fill in here.
Actors have the following subfields:
name - String - The name of the actor. For example, you can specify source.name or target.name.
id - Number - The ID of the actor. For NPCs this matches the ID you see on wowhead.com.
instance - Number - Which instance of the actor you're looking at. This is 1 for players. For NPCs, it's the specific instance of the mob.
instanceGroup - Number - Which instance group the actor belongs to. This is 0 for players and for ungrouped NPCs. For NPCs, it's the group they belong to, e.g., the 2nd spawns of Burning Pitch on Krosus woould be group 2.
type - String - The type of the mob. There are three mob types in WCL: player, NPC and pet.
class - String - The class of the player, e.g., warlock or rogue. For NPCs will return boss for boss mobs and NPC for regular mobs. Pets return pet.
spec - String - The spec of the player, e.g., destruction or arms.
role - String - The role of the player. Possible values are tank, melee, ranged and healer. For NPCs, the class value is returned.
disposition - String - Whether the mob is a friendly or enemy. This disposition is locked, and you can use it to just ask generally if a unit was friendly for most of the fight or an enemy for most of the fight.
rawDisposition - String - The disposition for this specific event only. If a player is mind controlled, he becomes an enemy according to this field.
marker - Number - A number representing the raid marker set on this actor. 0 if no raid marker is set.
owner - Actor - The owner of the pet. If the actor has no owner or is not a pet, then the owner is considered to be the actor itself.
firstSeen - Number - The timestamp of when this actor (and instance!) was first seen.
lastSeen - Number - The timestamp of when this actor (and instance!) was last seen.
Abilities have the following subfields:
name - String - The name of the ability. For example, you can specify ability.name.
id - Number - The ID of the ability. This matches the ID you see on wowhead.com.
type - Number - The school of the ability. The value matches the Number of the raw event, with bits from 1 up to 64.
Resources have the following subfields:actor - Actor - The actor whose resources are attached to the event. This can be either the source or the target or null if no resources are attached.
hitPoints - Number - The current hit points of the resource actor.
maxHitPoints - Number - The maximum hit points of the resource actor.
hpPercent - Float - Equivalent to hitPoints / maxHitPoints.
attackPower - Number - The AP of the resource actor.
spellPower - Number - The SP of the resource actor.
x - Number - The X position of the resource actor. WCL stores this position as the original position multiplied by 100. For example an X position of 32.56 is represented by WCL as 3256.
y - Number - The Y position of the resource actor. WCL stores this position as the original position multiplied by 100.
Fill in the rest of the resource fields
[NOT] IN RANGE [WHEN <condition>] [FROM <condition>] [TO <condition>] [GROUP BY <expression> [AND <expression>] [ON <expression>]] END
With range testing you can define arbitrary range boundaries and then test to see if an event is inside that range (or not inside that range). Here is an example that shows how to check if Sundering Blow is present on sources attacking General Nazgrim. [Note this isn't the best example, since there is an easier way to test for auras (see above)]
IN RANGE FROM type = "applydebuff" AND ability.name = "sundering blow" TO type = "removedebuff" AND ability.name = "sundering blow" GROUP BY target ON source END
(1) The WHEN clause is just an initial condition that has to be matched before you even check the range boundaries. I decided not to allow IN RANGE conditions to be nested, so you just get one... that meant I needed to let you specify conditions using WHEN.
(2) The FROM clause is a condition that if matched will cause you to begin a new range. If omitted, FROM will be the beginning of the fight.
(3) The TO clause is a condition that if matched will cause you to end a range. If omitted, TO will be the end of the fight.
(4) GROUP BY is how you link the FROM and TO together. For example with buffs and debuffs you typically would pair on the target of both events. If you want to pair on the source of the FROM and the target of the TO, that's allowed by adding an optional AND to specify something different for the TO.
(5) The ON clause is a way to further filter the events by requiring that the expression in the ON for the event you're testing matches the GROUP BY for the from/to boundaries. So in the above example you are looking at players doing damage, so they are the source of the events (but that has to match up with the targets for Sundering Blow). If omitted, the expression in GROUP BY will be used.
Match Against Indices
MATCHED <condition> IN <tuple expression> END
With the MATCHED expression, you can test for the nth time something happened, for example the second time a player gets a specific debuff. The first part is the condition whose matches you want to count and the second part is a tuple of indices (starting from 1) of which matches you want to include.
MATCHED type = "applydebuff" and ability.name = "Dark Herald" IN (1,3) END
The above example will match events for the first and third Dark Herald debuffs that go out during the fight.
Copying and Pasting Pins
You can hit the Copy Pin button at any time to get a copy of the pin before committing it. A dialog will come up with a textfield in which the entire pin string is selected. Simply copy using Ctrl+C (Windows) or Cmd-C (Mac).
To paste an exported pin, you can select the From Paste tab and paste that string into the text field shown.
When creating a pin, you can see a preview of how it will look once it's created. You can use the preview to double check that you have everything correct before committing the pin.
Notice the controls on the right. After creating a pin, you can turn the pin on in the displayed graph. The results will be shown with the pin's color as lines or bands. You can click the colored square to change the color of the pin.
Note that eventually you will be able to click the controls in the Pin Preview itself to set up the defaults you want for the pin, i.e., to turn the graphing on and set up the color, but for now you can only do this after the pin has been created.
There are four types of pins that you can create. The UI for selecting the pin type is shown below:
A decorator pin is used to add new matches to your original query. You can imagine a decorator pin as connecting to the original query on your query bar via a logical OR. The events matched by a decorator pin will get added to the raw events view (if they didn't match the original query already). In addition, you can show the matched events on the graph as well. Analytical View tables are unaffected by decorator pins.
For example, suppose that you are looking at Damage Taken by one of your tanks during Garrosh's Annihilate, and you want to see what cooldowns they used. You might start with the following query:
You could create a pin to see if Kaetzchen used his Survival Instincts cooldown at all.
After adding the pin, the raw events view will change and acquire any new events matched by the decorator pin. In addition those results are badged by the pin color, so you can scan down the rightmost side of the events view in order to quickly see where Kaetzchen used the cooldown.
Clicking the Off link in the pin will turn the pin on in the graph as well, and this lets you actually see everywhere Survival Instincts was used as a plot band.
As you can see, auras will show up as plot bands by default showing you the range of time for which the aura was up on the specified actors. You can put as many buffs/debuffs on the graph as you'd like, and you can use logical OR connectors to build composite queries to represent a whole range of cooldowns (for example, if you just want to know if any tank CD was used and don't really care about distinguishing each one individually on the graph).
A badge pin is used to badge matches without adding any new results to the view. It operates just like a decorator except that it will never change your result set. It will only badge existing results.
Looking at the previous example, we wanted to know if Kaetzchen used Survival Instincts during Annihilates. The decorator pin worked out well, but it also showed uses of Survival Instinct outside of Annihilates, and it also cluttered up the events view with aura applications and removals. We could have used a badge pin instead to achieve even better results.
We make use of the powerful aura presence test. This allows us to still match Damage Taken by Annihilate events, but now we want to badge those Damage Taken events that have Kaetzchen as the target and where Survival Instincts was present on Kaetzchen. The results now show us a pin color badge that indicates which Annihilates were eaten with a cooldown up. The aura gains/fades aren't added to the view.
When showing a pin involving aura presence, we no longer see a range on the graph. Instead we get lines representing the actual Annihilate events that were eaten with Survival Instincts up.
Badges are especially useful in the Deaths pane. For example. you can check to see if a hit was taken without Weakened Blows up. In the Paragons of the Klaaxi kill below, the first death was due to physical damage from Hisek.
Dubalicious died to Fire physical damage, so we can add a Badge pin to find out if that damage was taken without Weakened Blows being present on the boss. Let's see what that pin will look like. We can make a generic pin that will look for Weakened Blows being missing on any hostile source.
After creating the Badge pin, we do in fact see that Hisek did not have Weakened Blows up. Dub was still a goner, but this clues us in that somebody wasn't maintaining a debuff that they were supposed to, and we can now investigate that further.
A filter pin is used to remove results from a view. It is the most powerful of the pin types, as it can be used to actually change the displayed graphs and tables in analytical view to narrow their results. If you want to see Damage Done only when specific buffs or debuffs are up, or Healing Done only to targets with a certain debuff, then filtering pins are the best way to view that data.
Let's start with a relatively simple example. Suppose we're looking at dispels on Sha of Pride:
That shows all the dispels people did on the fight. Now suppose we want to filter those results to only show dispels that happened while the dispelling player did not have Gift of the Titans. We can do that with a filtering pin, and the graph/table will both update accordingly. This will show us who gained Pride by dispelling:
Applying the pin now filters the set of dispels to a smaller amount, only those done by players who did not have Gift of the Titans.
Another very powerful filter example to consider is who damaged General Nazgrim while Defensive Stance is up. This is another example of where we want to see only a subset of Damage Done to General Nazgrim, so a filtering pin is appropriate. This is a very complicated pin to construct, so we'll show it in steps. First let's start with a good baseline query, i.e., Damage Done to General Nazgrim.
Nazgrim only gains rage from direct damage, and pets don't give him rage. The first step in constructing our filtering pin is to make a Damage To Enemies filter that includes only Direct damage and that does not include source pets.
Next we can create a new query connected via a logical AND. We want to require that Defensive Stance be present on Nazgrim, so we do that next:
Finally, we don't want to incorrectly penalize the tanks. Tanks are allowed to hit Nazgrim if they have the Sundering Blow debuff. This means we want to only include damage done by players that don't have the Sundering Blow debuff. Again, we use logical AND to add a third query to this pin, namely that Sundering Blow be absent on the source.
The final result is shown here. Note that some direct damage doesn't give Nazgrim rage, but you can eyeball that accordingly (e.g., cloak procs and trinket procs like Multistrike).
Filters are smart about not applying to irrelevant views. For example if you make a Healing filter, and go view Damage, the Healing filter will not apply in the Damage pane. This allows you to create persistent filtering pins in certain views and not have them disrupt your other browsing.
A summary pin displays matching results as a total in the Summary pane. These pins can be used when you want to quickly total how many ticks of damage someone took, or how many times someone got a buff or debuff. For example, on the Garrosh Hellscream fight, we can construct a Summary pin that will count how many ticks players took from Empowered Whirling Corruption. We can create a pin for Damage Done To Friendlies and exclude target pets.
Notice that when you pick a Summary pin type, you get a few additional options. You can either sum on the number of events matched, or you can sum on amount (which for damage/healing events is the amount of actual damage done/healed). In this case we sum on matches on the targets of the damage taken events, and we end up with a new panel in our Summary pane that shows us these total amounts.
You can use Summary pins to quickly and easily view totals on hits from avoidable abilities, potion use, healthstone use, dispels, interrupts, etc.