Repository navigation
Hunter Testing Methodology
This page documents the testing methods used to verify Hunter mechanics and damage formulas in WoW Forever.
The goal is not simply to find a formula that can explain a few observed hits.
A strong formula should continue to predict the correct results when its inputs are deliberately changed.
The general testing process is:
- establish a proposed formula
- calculate the expected damage range
- reproduce the attack in game
- compare the combat-log result against the predicted range
- change one variable at a time
- verify that the formula predicts the resulting change
- reject or revise the formula if a clean result falls outside the expected range
A formula that fits existing data is plausible.
A formula that correctly predicts new data is much stronger.
Whenever possible, record and hold constant:
- Hunter level
- target level
- target
- weapon damage
- weapon speed
- ammunition
- RAP
- MAP
- talents
- buffs
- target debuffs
- ability rank
Change only the variable being investigated.
For example, an RAP coefficient test should ideally be:
Same Weapon + Same Target + Same Modifiers + Different RAP
A normalization test should instead be:
Same RAP + Same Target + Different Weapon Speed
This helps isolate which part of the formula caused the observed change.
Common Hunter damage events include:
| Event | Typical Damage |
|---|---|
RANGE_DAMAGE |
Auto Shot and ranged weapon attacks |
SPELL_DAMAGE |
Direct ability damage |
SPELL_PERIODIC_DAMAGE |
Periodic damage ticks |
SWING_DAMAGE |
White melee swings |
The event type itself can also provide useful information about how an ability is implemented.
Forever's advanced combat log includes an:
originalDamage
field near the end of damage events.
For testing:
amount = final damage actually dealt
originalDamage = raw/original damage reported by the combat log
When checking an underlying damage formula, originalDamage is generally the more useful value because the final amount may already include target mitigation.
This allows the server's raw result to be compared directly against the proposed formula.
Note:
originalDamageappears near the end of the advanced combat-log damage payload.
For unusual effects involving custom reductions, absorbs, or other server-side mechanics, compare both originalDamage and amount before drawing conclusions.
Weapon-based attacks produce a damage range, not one fixed value.
The game can round the lower and upper boundaries outward.
For example:
Calculated Range = 10.5 β 21.2
can produce:
Observed Range = 10 β 22
For testing purposes:
Minimum Observable Damage = floor(Calculated Minimum)
Maximum Observable Damage = ceil(Calculated Maximum)
This rounding behavior must be included before deciding that an observed hit falls outside the predicted formula.
One of the strongest ways to test a formula is to calculate its complete possible damage range and look for a result the formula cannot produce.
For example:
Calculated Range = 10.5 β 21.2
After rounding:
Valid Results = 10 β 22
Observed hits such as:
10, 14, 18, 22
are consistent with the formula.
A clean result of:
9
or:
23
is not.
If an originalDamage result falls outside the predicted range, then at least one assumption is wrong.
Possible causes include:
- incorrect AP coefficient
- incorrect normalization
- incorrect weapon-damage contribution
- incorrect ammunition behavior
- missing damage modifier
- unexpected server-side mechanic
- incorrect test inputs
A single impossible result can disprove a proposed formula even if many previous hits appeared to fit it.
Different formulas can sometimes predict overlapping damage ranges.
For example:
Formula A
100 β 120
Formula B
103 β 123
Hits of:
108, 112, 116
do not distinguish between the two formulas.
A hit of:
121
immediately rules out Formula A.
For this reason, results near the predicted minimum and maximum are often more useful than average damage.
Tests should also be designed so competing formulas produce ranges that are as different as possible.
To determine an unknown AP coefficient, test the same ability at two substantially different Attack Power values.
Keep all other variables constant.
For a fixed or nearly fixed-damage ability:
Coefficient = Damage Increase / AP Increase
Example:
At 300 RAP:
100 damage
At 500 RAP:
120 damage
Damage difference:
20
RAP difference:
200
Therefore:
20 / 200 = 0.10
or:
10% RAP
Larger AP differences are preferable because they reduce the effect of rounding and make competing coefficients easier to distinguish.
For a weapon-based ability, calculate both ends of the expected damage range.
Minimum Damage = Minimum Weapon Damage + Other Formula Components
Maximum Damage = Maximum Weapon Damage + Other Formula Components
Then apply the game's rounding behavior:
floor(Minimum)
ceil(Maximum)
Compare clean originalDamage results against that predicted range.
If even one valid result falls outside the range, the proposed formula or one of its assumptions needs to be revised.
To determine whether an ability uses actual weapon speed or normalized AP scaling, test weapons with substantially different speeds.
Actual-speed scaling:
AP / 14 Γ Weapon Speed
Normalized ranged scaling:
AP / 14 Γ 2.8
If changing weapon speed changes the AP contribution according to actual weapon speed, the ability uses actual-speed scaling.
If the AP contribution remains consistent with 2.8, the ability is normalized.
The strongest test uses weapon speeds far enough apart that the competing formulas produce different or non-overlapping expected damage ranges.
This method is particularly useful for testing abilities such as Sniper Shot.
Ammunition can be isolated by changing only the equipped ammo while keeping the following constant:
- weapon
- RAP
- target
- talents
- buffs
Calculate the predicted damage range under the proposed ammunition formula and compare it against originalDamage.
If an observed result falls outside that range, the ammunition assumption is invalid or another part of the formula is wrong.
This method has been especially useful during Hunter testing because an ammunition model can appear correct across many hits before a single out-of-range result exposes the problem.
Periodic damage is often easier to test because weapon-damage variance is absent.
To determine a per-tick AP coefficient:
Per-Tick Coefficient = Tick Damage Increase / AP Increase
Example:
3 additional damage / 100 RAP = 3% RAP per tick
To determine whether a periodic effect snapshots or dynamically updates:
- apply the effect
- record one or more ticks
- change AP without refreshing the effect
- record later ticks
If later ticks change, the effect dynamically recalculates from the Hunter's current stats.
If the ticks remain unchanged, the relevant stat was likely snapshotted when the effect was applied.
This method was used to establish the dynamic behavior of Hunter periodic damage.
To identify both a damage modifier and its stacking behavior, use four states whenever possible:
- no modifier
- Modifier A only
- Modifier B only
- both modifiers
For two 5% modifiers:
Base Γ 1.10
Base Γ 1.05 Γ 1.05
or:
Base Γ 1.1025
The difference is small, so large damage values or larger modifiers make the result easier to distinguish.
Current working assumption:
Direct damage modifiers stack multiplicatively
This still needs verification.
Critical-damage testing should be separated from Crit chance.
Current working model:
Base Physical Crit = 2.00Γ
with critical-damage bonuses added to that multiplier.
For example:
Mortal Shots = 2.00 + 0.30 = 2.30Γ
A Dwarf with Mortal Shots is currently modeled as:
2.00 + 0.30 + 0.02 = 2.32Γ
This additive behavior still needs verification.
One random Crit should not be divided by one unrelated normal weapon hit.
The two attacks may have rolled different base weapon damage.
Instead, use:
- fixed-damage abilities where possible
- calculated minimum and maximum normal ranges
- calculated minimum and maximum Crit ranges
- or enough observations to establish both ranges
If the observed Crit range exceeds or falls below the predicted boundaries, the Crit multiplier or another modifier assumption needs to be revised.
When multiple modifiers may affect the same attack, test them independently before testing them together.
A useful sequence is:
Base
Base + Modifier A
Base + Modifier B
Base + Modifier A + Modifier B
This allows the individual value of each modifier to be established before testing whether they combine additively, multiplicatively, or through another grouping.
For Crit damage, the same approach should be used when testing combinations such as:
- Mortal Shots + Dwarf racial
- Predator's Edge + Tauren racial
When investigating an unknown ability, the following order usually produces the cleanest result:
- identify the combat-log event type
- determine whether the damage is weapon-based or fixed
- determine whether ammunition contributes
- determine whether AP contributes
- establish the AP coefficient
- determine actual vs normalized weapon speed
- establish the complete damage range
- test Crit behavior
- test direct damage modifiers
- test modifier stacking
Testing the underlying formula before adding talents and buffs prevents modifiers from hiding mistakes in the base equation.
A formula becomes increasingly well supported when:
- its predicted minimum matches observed behavior
- its predicted maximum matches observed behavior
- no clean result falls outside the rounded expected range
- changing AP produces the predicted shift
- changing weapon speed produces the predicted shift
- changing ammunition produces the predicted shift
- applicable modifiers produce the predicted shift
- competing formulas can be ruled out
The goal is not merely to find a formula that can explain the current observations.
The stronger test is whether the formula correctly predicts new results after its inputs are deliberately changed.
A useful test report should include enough information for someone else to reproduce it.
At minimum:
- Hunter level
- target level
- RAP
- MAP if relevant
- weapon damage
- weapon speed
- ammunition
- ability rank
- relevant talents
- active buffs
- target or creature type
- combat-log event
- observed
originalDamagevalues
Example test:
Hunter Level: 30
Target Level: 30
RAP: 500
Ranged Weapon: 65β87
Weapon Speed: 2.4
Ammo: 9.5 DPS
Relevant Talents: None
Relevant Buffs: None
Event: RANGE_DAMAGE
Observed originalDamage: 112, 118, 115, 121...
The observed results can then be compared directly against the predicted rounded damage range.