World-of-warcraft – Where do base healing/damage amounts come from

world of warcraft

In World of Warcraft, the damage or healing done by a spell varies with your level.

For example, Greater Healing Wave for a level 84 Shaman does 8778-10028 healing:

enter image description here

What i cannot figure out is where Wowhead is getting these numbers from.

There's a javascript slider, that you can adjust and see the base range for all the available levels:

Level  Minimum  Maximum
=====  =======  =======
68     4085     4667
69     4357     4977
70     4639     5299
71     4931     5633
72     5233     5977
73     5546     6334
74     5869     6703
75     6202     7084
76     6546     7478
77     6902     7884
78     7269     8303
79     7647     8735
80     8037     9181
81     8219     9389
82     8404     9600
83     8590     9812
84     8778    10028
85     8969    10245

Where is Wowhead getting these numbers from?

The values defy logic, as you can see when they're plotted:

enter image description here

i'm trying to maintain the HealPoints addon; and i cannot find these values documented anywhere.


Edit: The values do not come from any API. e.g.:

GetSpellInfo("Greater Healing Wave")
  • name: Greater Healing Wave
  • rank:
  • icon: Interface\Icons\Spell_Nature_HealingWaveLesser
  • powerCost: 5201
  • isFunnel: false
  • powerType: 0
  • castingTime: 2500
  • minRange: 0
  • maxRange: 40

Update: Graph of Paladin's Holy Light base healed amounts, by level:

enter image description here

Perhaps the numbers are a function of base mana, which is non-linear? Or intelligence?

Best Answer

The numbers are likely based on tiered formulas (i.e. from level 1-60, one formula, from level 60-70, another, etc). Considering you are managing an addon, I'd recommend the approach that Wowhead takes. Wowhead doesn't calculate these values on the fly. They save the values on the server-side and reuse them.

Considering Wowhead is a reliable source for in-game data, I'd recommend simply scraping your values from Wowhead and using those.


UPDATED

To expand on the tables in the link, I dug into the Wowhead code just deep enough to determine how some of these values are used for Greater Healing Wave. Note that all of the data and functions used are visible in the $WH JavaScript object.

The link has 2 JSON objects:

  1. The $WH.g_convertScalingSpell.SD object lists scaling values for different distribution types. Each element is an array with 15 values.
  2. The $WH.g_convertScalingSpell.SV object lists scaling values for different levels. Each element is an array with 12 values.

The function where the magic happens is the $WH.g_convertScalingSpell function. Basically, it accepts a level and a scaling type, then uses the tables to match up the two and calculate the final value. A quick glance at the $WH object shows there are a couple more g_convert functions for different values.

While I can't speak on behalf of what all of the values of the scaling tables represent, I can expose the formula used in the $WH.g_convertScalingSpell function.

a = $WH.g_convertScalingSpell.SD[ distribution_type ]
b = $WH.g_convertScalingSpell.SV[ level ]
c = b[a[3] - 1] * (min(level, a[14]) + (a[13] * max(0, level - a[14]))) / level

Then, using c, an object is built out with multiple min, max, and avg values. Only the first min and max values are visible in Greater Healing Wave's tooltip. The value i displayed below is evaluated at 0, 1, and 2. If you are only interested in the first object that is built, you can omit the i entirely, as it's value is 0.

avg = a[4 + i] * c * (a[1] > 0 ? cast / a[1] : 1)
min = round(avg) - floor(avg * a[7 + i] / 2)
max = round(avg) + floor(avg * a[7 + i] / 2)

And if you are curious, the cast value (casting time in milliseconds) comes from this formula, and is only rounded after calculations, prior to displaying the value to the user:

cast = min(a[1], a[1] > 0 && level > 1 ? a[0] + (((level - 1) * (a[1] - a[0])) / (a[2] - 1)) : a[0])

When applying this, you have to know the desired distribution type. This is found in an HTML comment in the tooltip's markup, starting with a question mark. So, to show the example of Greater Healing Wave, the HTML comment is <!--?77472:68:85:85:355:0:1000-->. While I do not know what all of the values are, I know the first few are spellId, minLevel, maxLevel, defaultLevel, and distScale.

Let's do the math:

a = $WH.g_convertScalingSpell.SD[355]
  = [3000, 3000, 20, 7, 9.564, 0, 0, 0.133, 0, 0, 0, 0, 0, 1, 0]

b = $WH.g_convertScalingSpell.SV[85]
  = [1125.23, 1029.49, 1125.23, 1125.23, 945.189, 1125.23, 1004.49, 937.33, 962.336, 0, 986.626, 443]

c = b[a[3] - 1] * (min(level, a[14]) + (a[13] * max(0, level - a[14]))) / level
  = b[7    - 1] * (min(85,    0    ) + (1     * max(0, 85    - 0    ))) / 85
  = b[6]        * (min(85,    0    ) + (1     * max(0, 85           ))) / 85
  = 1004.49 * (min(85, 0) + (1 * max(0, 85))) / 85
  = 1004.49 * (0 + (1 * 85)) / 85
  = 1004.49 * 85 / 85
  = 1004.49

And then the spell values:

cast = min(a[1], a[1] > 0 && level > 1 ? a[0] + (((level - 1) * (a[1] - a[0])) / (a[2] - 1)) : a[0])
     = min(3000, 3000 > 0 && 85    > 1 ? 3000 + (((85    - 1) * (3000 - 3000)) / (20   - 1)) : 3000)
     = min(3000, true && true ? 3000 + ((84 * 0) / (19)) : 3000)
     = min(3000, true ? 3000 + (0 / 19) : 3000)
     = min(3000, 3000 + 0)
     = 3000

avg = a[4 + i] * c * (a[1] > 0 ? cast / a[1] : 1)
    = a[4 + 0] * c * (a[1] > 0 ? 3000 / a[1] : 1)
    = 9.564    * c * (3000 > 0 ? 3000 / 3000 : 1)
    = 9.564    * c * (true ? 1 : 1)
    = 9.564 * 1004.49
    = 9606.942360000001

min = round(avg)        - floor(avg               * a[7 + i] / 2)
    = round(8964.62412) - floor(9606.942360000001 * a[7 + 0] / 2)
    = 9607              - floor(9606.942360000001 * 0.133    / 2)
    = 9607              - floor(1277.7233338800002           / 2)
    = 9607              - floor(638.8616669400001               )
    = 9607 - 638
    = 8969

max = round(avg)        + floor(avg               * a[7 + i] / 2)
    = 9607 + 638
    = 10245

Hope this helps!