Decorative background for title

Intro to Expressions

This article aims to explain and go through the expression language used on SWTOR Logs. Please join us on Discord if you have any questions, as we're happy to help and provide answers if you have any queries.

What are expressions?

Expressions are built using the WCL Expression Language and are intended for experts and programmers who need to build more 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!

The way to think about expressions is that every fight is broken up into a series of events. Those events are damage events, healing events, casts, buffs, debuffs etc. All of these events have three components. An event has a source, an ability and a target.

Take for example this event from a log:

Velynn casts Shadow Bolt on Gruul the Dragonkiller.

Velynn is the source of this event, the ability is Shadow Bolt and the target is Gruul the Dragonslayer.

You can also be both the source and the target of an event:

Velynn gains Blessing of the Silver Crescent from Velynn.

Here Velynn is both the source and the target. The ability is Blessing of the Silver Crescent from the Icon of the Silver Crescent trinket.

Expressions are queries that filter through all these events to get the information you want to see. A query expression is built through various logical operators and strings to filter through the data.

Filter Expression

Every log report has a Filter Expression you can type in. This is where your queries should go if you write them from scratch or copy paste from someone else.

SWTOR Logs uses an SQL-like language for constructing expressions. When creating an expression, you can use various operators, such as the ones listed below.

Logical Operators

A logical operator is a symbol or word used to connect two or more 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. In other words, for A AND B, if A turns out to be false, then B will not be evaluated, so construct your queries accordingly.

Comparison Operators

Comparison operators are used to compare The following comparison operators are supported:

<, >, <=, >=, =, !=
< means 'Less than'
It will filter out all the data that doesn't match. It returns true if the value on the left is less than the value on the right, otherwise it returns false.
> means 'Greater than'
It returns true if the value on the left is greater than the value on the right, otherwise it returns false.
<= means 'Less than or equal to'
It returns true if the value on the left is less than or equal to the value on the right, otherwise it returns false.
>= means 'Greater than or equal to'
It returns true if the value on the left is greater than or equal to the value on the right, otherwise it returns false.
= means 'Equal to'
It returns true if the value on the left is equal to the value on the right, otherwise it returns false.
!= means 'Not equal to'
It returns true if the value on the left is not equal to the value on the right, otherwise it returns false.

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.

Arithmetic Operators

The following arithmetic operators are supported:

+, -, *, /, %

+ is addition

- is subtraction or negation

* is multiplication

/ is division

% is mod

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 ("The Nine", "Painsmith Raznal", "Kel'Thuzad")

returns true if A is = to any of the three strings.

Case Statements

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

Numbers

All numbers are Numbers. No floating point numbers/decimals are allowed.

Strings

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.

Identifiers

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:

source.name = "A"

Function Calls

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.

Built-in Identifiers

Every expression is evaluated on all of the events within the specified time range. The following built-in identifiers are supported:

encounterID

EncounterIDs can be used to look at a specific encounter or to exclude encounters. If you want to look at a whole raid night except for one fight, you can use encounterID to exclude this fight from the overview. Trash fights have a value of 0.

For example:

encounterID != 730
730 is the encounterID for Al'ar. Writing this in the Filter Expressions will exclude the Al'ar encounter.

You can find encounterIDs either on the DungeonEncounterID Wowpedia page or you can find it at the top of the Summary/Events view in a report, as shown in the image below.

encounterSize
The raid size of the encounter. 10-man vs. 25-man, etc.
encounterDifficulty
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
How the encounter ended. Possible values are "wipe" and "kill".
encounterDuration
How long the encounter lasted in milliseconds.
encounterBossHealthPercentage
The percentage health of the boss at the end of the pull. A number between 0 and 100.
encounterFightPercentage
How far into the fight you were (corresponds to the colored bars that show up in the wipes display). A number between 0 and 100.
encounterPhase

The phase an event belongs to. Phases are numbered starting from 1. If a fight has no phases, this number will be 0.

encounterStartTime
The start time of the fight relative to the beginning of the report.
encounterEndTime
The end time of the fight relative to the beginning of the report.
timestamp
The timestamp of the event in milliseconds relative to the start of the fight.
type
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, resourcechange, drain, resurrect, encounterstart, encounterend, dungeonstart, dungeonend, dungeonencounterstart, dungeonencounterend, towerstart, towerend, mapchange, zonechange, worldmarkerplaced, worldmarkerremoved, taunt, modifythreat, calculateddamage, calculatedheal

PLEASE NOTE: Note that Warcraft Logs does not consider a full absorb to be a miss. It will be represented with a damage event.

inCategory

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
The raw damage for a damage event. This includes absorbs and overkill damage.
effectiveDamage
The effective damage for a damage event. This excludes absorbs and overkill, and it represents how much damage the actor actually took.
absorbedDamage
The amount absorbed for a damage event.
blocked
The amount blocked for a damage event.
overkill
The amount of overkill for a damage event.
rawHealing
The raw healing for a healing/absorb event. This includes absorbs and overheal.
effectiveHealing
The effective healing for a healing/absorb event. This excludes overheal but still includes absorbed healing (e.g., Veil of Darkness on Sylvanas Windrunner)
absorbedHealing
The amount absorbed for a healing event. For non-absorb heals, it represents the amount absorbed (e.g., Veil of Darkness on Sylvanas Windrunner), but for absorb abilities it is equivalent to effectiveHealing.
isCritical

True or False - checks whether or not a damage or heal event crit.

isTick

True or False - checks whether or not a damage or heal event is periodic, i.e., a DoT or HoT.

isUnpairedCalculation

True or False - checks whether an ability ghosted or not. i.e., it will display as "true" if a prepares event has ghosted.

isGlancing
True or False - checks whether or not a melee damage event is a glancing blow
isMultistrike
True or False - checks whether or not a damage or heal event was a multistrike.
missType
For a miss, indicates what happened.

Possible values are:

miss, dodge, parry, immune, deflect, reflect, misfire, evade, resist.
</Description>

stack
The stack count for buff and debuff stack events.
extraAttacks
The number of extra attacks for an extra attacks event.
source
The source of the event. A special Environment actor is returned if no source exists.
target
The target of the event. A special Environment actor is returned if no target exists.
ability
The primary ability for the event.
supportedActor
To get back to the original buffed player in cases of Augmentation Evoker augmented damage events
stoppedAbility
For steals, breaks and dispels, represents the spell that was dispelled. For interrupts, it represents the spell that was interrupted.
resources
Returns a resources object that can be used to obtain information like Hit Points, Spell Power, map positions, etc.
feign

True or false - Returns true if a death event is actually a hunter feign.

killer
Will match death events if the killing blow that caused the death came from this actor.
killingAbility
Will match death events if the killing blow that caused the death was from this ability.
absorbedAttacker
Will match absorbed events if the attacker whose blow was absorbed is this actor
absorbedAttackerAbility
Will match absorbed events if the attack that was absorbed came from this ability.
absorbedHealer
Will match heal absorbed events if the healer whose heal was absorbed is this actor.
absorbedHealerAbility
Will match absorbed events if the healer whose heal was absorbed came from this ability.

Actor Fields

Actors have the following subfields:

name
The name of the actor. For example, you can specify source.name or target.name.
id
The ID of the actor. For NPCs this matches the ID you see in a Wowhead URL.
Which instance of the actor you're looking at. This is 1 for players. For NPCs, it's the specific instance of the mob.
instance
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
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 adds on a fight would be group 2.
type
The type of the mob. There are three mob types in WCL: player, NPC and pet.
class
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
The spec of the player, e.g., destruction or arms.
role
The role of the player. Possible values are tank, melee, ranged and healer. For NPCs, the class value is returned.
disposition
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
The disposition for this specific event only. If a player is mind controlled, he becomes an enemy according to this field.
marker
A number representing the raid marker set on this actor. 0 if no raid marker is set.
owner
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
The timestamp of when this actor (and instance!) was first seen.
lastSeen
The timestamp of when this actor (and instance!) was last seen.

Ability Fields

Abilities have the following subfields:

name
The name of the ability. For example, you can specify ability.name.
id
The ID of the ability. This matches the ID you see on a Wowhead URL.
type

The school of the ability. The value matches the Number of the raw event, with bits from 1 up to 64. The list for WoW parameters can be found on Wowpedia.

Resources Fields

Resources have the following subfields:

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
The current hit points of the resource actor.
maxHitPoints
The maximum hit points of the resource actor.
hpPercent
Equivalent to hitPoints / maxHitPoints.
attackPower
The AP of the resource actor.
spellPower
The SP of the resource actor.
x

The X position in game 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
The Y position in game of the resource actor. WCL stores this position as the original position multiplied by 100.

Range Testing

With range testing, you can define arbitrary range boundaries and test if an event is inside (or not inside) that range.

Example:

IN RANGE FROM type = "applybuff" AND ability.name = "Swarm of Darkness" TO type = "removebuff" AND ability.name = "Swarm of Darkness" END
This example expression shows the ranges when Swarm of Darkness is up on Lords of Dread. This would allow you to specifically check healing done during swarm if you wanted to.

Details:

  1. The WHEN clause is just an initial condition that has to be matched before you even check the range boundaries. IN RANGE conditions can not be nested, so this lets you specify conditions if needed.

  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. 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 n-th 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.

Contact Us

As always, we love to hear your feedback. Please join us on Discord to share any feedback and suggestions, or to ask any questions.

Follow our Twitter for updates!

If you have any support questions, please reach out to our support team at [email protected].

Advertisements
Remove Ads