Hunter Testing Methodology - classic-hunter/forever-hunter GitHub Wiki

๐Ÿ”ฌ 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.


Summary

The general testing process is:

  1. establish a proposed formula
  2. calculate the expected damage range
  3. reproduce the attack in game
  4. compare the combat-log result against the predicted range
  5. change one variable at a time
  6. verify that the formula predicts the resulting change
  7. 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.


๐Ÿงช Controlling the Test

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.


๐Ÿ“œ Reading the Combat Log

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.


Finding Raw Damage

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: originalDamage appears 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.


๐ŸŽฒ Damage Ranges and Rounding

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.


โŒ Falsifying a 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.


Overlapping Formula Ranges

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.


๐Ÿ“ˆ Testing Attack Power Scaling

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.


๐Ÿน Testing Weapon-Based Abilities

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.


๐ŸŽฏ Testing Normalized vs Actual Weapon Speed

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.


๐Ÿน Testing Ammunition

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.


๐Ÿ Testing Periodic Effects

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


Testing Dynamic Scaling

To determine whether a periodic effect snapshots or dynamically updates:

  1. apply the effect
  2. record one or more ticks
  3. change AP without refreshing the effect
  4. 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.


๐Ÿ“ˆ Testing Damage Modifiers

To identify both a damage modifier and its stacking behavior, use four states whenever possible:

  1. no modifier
  2. Modifier A only
  3. Modifier B only
  4. both modifiers

For two 5% modifiers:

Additive Prediction

Base ร— 1.10

Multiplicative Prediction

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.


๐Ÿ’ฅ Testing Critical Damage

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.


Weapon Damage Variance

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.


๐Ÿ”„ Testing Modifier Stacking

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

๐Ÿ”Ž Testing a New Ability

When investigating an unknown ability, the following order usually produces the cleanest result:

  1. identify the combat-log event type
  2. determine whether the damage is weapon-based or fixed
  3. determine whether ammunition contributes
  4. determine whether AP contributes
  5. establish the AP coefficient
  6. determine actual vs normalized weapon speed
  7. establish the complete damage range
  8. test Crit behavior
  9. test direct damage modifiers
  10. test modifier stacking

Testing the underlying formula before adding talents and buffs prevents modifiers from hiding mistakes in the base equation.


โœ… Verification Standard

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.


Reporting a Test

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 originalDamage values

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.


Related Pages