Abilities - WoWAnalyzer/WoWAnalyzer GitHub Wiki

Every spec has an abilities configuration. This is a class the extends the Abilities class in Parser/Core/Modules/Abilities (further called CoreAbilities) and implements the spellbook() method to provide a list of all abilities available to your spec.

Example: Holy Paladin's abilities

What you should include

You should include all spells available to players. This including spells you'd rarely use such as taunts for healers or DPS. This will provide support for all abilities in various modules that rely on it such as the timeline (which wouldn't otherwise show the casts), and cast efficiency.

How to configure it

spellbook() : array

The spellbook method gets called once on initialization and is then stored in an array for the rest of the analysis. Like in methods of other modules you have full access to other modules through the dependency injection system or the CombatLogParser. Generally you'll only need info about the combatant from this.selectedCombatant.

This method should return an array of all available spells. Each entry of the array must be an options object for the Ability class.

Ability config options

Each entry of the spellbook array must be an config object for a new Ability instance. A complete list of all available properties can be found here in the Ability class source code.

Options:

spell : object|array (required)

This is usually a spell object from the SPELLS import, but may also be an array in case the spell has multiple spell ids. This can NOT be an id.

category : string (required)

The name of the category to place this spell in, you should usually use the Abilities.SPELL_CATEGORIES enum for these values.

cooldown : number|func

The cooldown of a spell at the time of the call. If the cooldown is always static this should be a number, otherwise this should be a function. Parameters provided: hastePercentage, selectedCombatant

charges : number

The amount of charges the spell has by default. Reminder: only 1 charge will recharge at a time, so a spell having multiple charges will only have the amount of charges as extra possible casts during a fight.

gcd : null|object (default null)

Whether the spell is on the Global Cooldown (GCD). You should set this property for all abilities. Set it to null for abilities not on the GCD to make your intent obvious. Please leave a comment if something is different from expectations.

Set this property to an object if the spell is on the GCD. This causes the abilities to be shown properly in the timeline and the AlwaysBeCasting module can calculate a correct downtime/active time. The object can have the following props:

  • base - number|func The base GCD duration of the ability. Set this if the ability scales with Haste.
  • minimum - number|func The minimum GCD duration of the ability. The defaults to 50% the duration of base and should usually be omitted.
  • static - number|func The static GCD duration of the ability. Set this if the ability does NOT scale with Haste and is static. On rare occasions the GCD may be reduced (e.g. by "attack speed" increases), set this to a function instead. Example: combatant => 1000 * (1 - (combatant.hasBuff(SPELLS.ADRENALINE_RUSH.id) ? 0.2 : 0))

Debugging:

  • If the timeline shows a few large overlaps you might have marked a spell as being on the GCD wrongly.
  • If the timeline shows a bunch of small overlaps the base global cooldown duration might be non-default, the GCD might be different per spell, or the player might have a Haste buff applied that isn't accounted for in the StatTracker or Haste modules.

enabled : bool (default true)

Whether the spell is enabled (available to the player). This should only be used for hiding spells that are unavailable, for example due to talents.

castEfficiency : object

This takes another config property in which you can configure cast efficiency specific settings such as:

castEfficiency.suggestion : bool (default false)

If this is set to true, this spell will trigger a Cast Efficiency suggestion when the efficiency is below the set threshold (with one of the props below, or the default 80%).

castEfficiency.recommendedEfficiency : number (default 0.8)

The custom recommended cast efficiency. Default is 80% (0.8).

castEfficiency.averageIssueEfficiency : number (default recommendedEfficiency - 0.05)

Should only be set if you really want to configure this manually. By default this is 5% below the recommend efficiency.

castEfficiency.majorIssueEfficiency : number (default recommendedEfficiency - 0.15)

Should only be set if you really want to configure this manually. By default this is 15% below the recommend efficiency.

castEfficiency.extraSuggestion : string|node

Extra suggestion text for after the Cast Efficiency suggestion. Use this for example to explain why casting the spell more often is important.

castEfficiency.importance : string

If set, the suggestion will get this static importance value. Use this ISSUE_IMPORTANCE enum from Parser/Core/ISSUE_IMPORTANCE for this. An example usage of this would be to set the importance of defensive spells to minor.

castEfficiency.casts : func

DEPRECATED A function to get the amount of casts done of a spell. Parameters provided: castCount, parser

castEfficiency.maxCasts : func

DEPRECATED A function to get the max amount of casts for a spell. Parameters provided: cooldown, fightDuration, getAbility, parser

isDefensive : bool (default false)

Whether the spell should be shown as a defensive at some places. The death log module uses this property to determine if the spell should be shown for death events and whether it was on cooldown or available.

isUndetectable : bool (default false)

Whether having access to the spell is undetectable in the combat log. This makes it so the spell is hidden when there are 0 casts in the fight. This should only be used for spells that can't be detected if a player has access to them, like racials.

timelineSortIndex : number

You can use this property to determine the position of the ability on the timeline. The lower the number the higher on the timeline it will be displayed.

damageSpellIds : number[]

You can use this property to fabricate casts for abilities that were pre-cast. The provided array should include IDs for the damage portion(s) of the spell. This should be used for abilities that are commonly used or cast before the boss is actually damaged.

How to configure the spell cooldown durations properly

To achieve proper spell cooldown durations you need to set the correct cooldown value for all your spells, and ensure all Haste buffs are accounted for properly.

To help you figure out the issue, we print console messages whenever an issue occurs. You can open your console in most browsers with the F12 key. You will find issues such as the following:

03:33.857 SpellUsable Battle Cry 1719 was cast while already marked as on cooldown. It probably either has multiple charges, can be reset early, cooldown can be reduced, the configured CD is invalid, the Haste is too low, the combatlog records multiple casts per player cast (e.g. ticks of a channel) or this is a latency issue. fight time: 213857 time passed: 32952 cooldown remaining: 17048 expectedDuration: 50000

The error message explains what might be going on. By looking at the cooldown remaining you can usually make a good guess as to the cause:

  • if the cooldown remaining is <150ms and it doesn't happen very often it might be lag (and you can't fix it)
  • if the cooldown remaining is <200ms regularly or 200ms-500ms irregularly/grouped together, it may be a missing Haste buff
  • if the cooldown remaining is large, it's usually a misconfigured cooldown duration or the spell has multiple charges but wasn't configured as having any. Another cause might be that the spell cooldown is reduced by other spell interactions, or reset completely.

The recommended approach to fixing it is to check if all your spec specific Haste buffs are accounted for in the StatTracker and Haste modules. Don't forget traits, tier sets and other items. If all that's ok make sure the configured cooldown durations and available charges are right, and that the spells don't have some sort of cooldown reduction.

It might also help to open the timeline and look at the specific timeline. Hover the ability to see the cooldown shows in-game, and the cooldown bars to see the adjusted estimated cooldown (it won't be the actual in-game value so long as it is misconfigured).

If you still don't know what the cause for the cooldown inaccuracy is you can click the spell to open the Wowhead page. See the Modified by tab for most spells that affected the spell in one way shape or form. Go over all icons to read the effects. This list usually doesn't include cooldown reductions triggered by other spells, so you might also have to go over the artifact traits in-game and check your spellbook.

A note about random cooldown reductions/resets

The combat log does not have any events for cooldown reductions or resets, so unfortunately effects like Convergence of Fates can not be accounted for very well. To fix errors triggered by spells affected by this, we recommend adding a SpellUsable module to your spec like the following:

import SPELLS from 'common/SPELLS';
import ITEMS from 'common/ITEMS';
import CoreSpellUsable from 'Parser/Core/Modules/SpellUsable';
import Combatants from 'Parser/Core/Modules/Combatants';

class SpellUsable extends CoreSpellUsable {
  hasConvergenceOfFates = false;
  constructor(...args) {
    super(...args);
    this.hasConvergenceOfFates = this.selectedCombatant.hasTrinket(ITEMS.CONVERGENCE_OF_FATES.id);
  }

  beginCooldown(spellId, ...args) {
    if (this.hasConvergenceOfFates && spellId === SPELLS.BATTLE_CRY.id) {
      if (this.isOnCooldown(spellId)) {
        this.endCooldown(spellId);
      }
    }

    super.beginCooldown(spellId, ...args);
  }
}

export default SpellUsable;

Warning: This will result in questionable accuracy for the affected spell since the cooldown might have ended much earlier. It might be better to instead unset the cooldown of affected spells if the player has Convergence of Fates equipped and mention it in the spec description.