AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
SpellProcChanceTest.cpp File Reference

Unit tests for proc chance calculations. More...

#include "ProcChanceTestHelper.h"
#include "ProcEventInfoHelper.h"
#include "gtest/gtest.h"

Go to the source code of this file.

Classes

class  SpellProcChanceTest
 

Functions

 TEST_F (SpellProcChanceTest, BaseChance_UsedWhenNoPPM)
 
 TEST_F (SpellProcChanceTest, BaseChance_100Percent)
 
 TEST_F (SpellProcChanceTest, BaseChance_Zero)
 
 TEST_F (SpellProcChanceTest, PPM_OverridesBaseChance_WithDamageInfo)
 
 TEST_F (SpellProcChanceTest, PPM_NotApplied_WithoutDamageOrHealInfo)
 
 TEST_F (SpellProcChanceTest, PPM_Applied_WithHealInfo)
 
 TEST_F (SpellProcChanceTest, PPM_HealInfo_ZeroBaseChance_WouldBeZeroWithoutFix)
 
 TEST_F (SpellProcChanceTest, PPM_WithWeaponSpeedVariation)
 
 TEST_F (SpellProcChanceTest, ChanceModifier_PositiveModifier)
 
 TEST_F (SpellProcChanceTest, ChanceModifier_NegativeModifier)
 
 TEST_F (SpellProcChanceTest, ChanceModifier_AppliedAfterPPM)
 
 TEST_F (SpellProcChanceTest, PPMModifier_IncreasesEffectivePPM)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_NoReductionAtLevel60)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_NoReductionBelowLevel60)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_ReductionAtLevel70)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_ReductionAtLevel80)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_MinimumAtLevel90)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_NotAppliedWithoutAttribute)
 
 TEST_F (SpellProcChanceTest, Level60Reduction_AppliedAfterPPM)
 
 TEST_F (SpellProcChanceTest, ApplyLevel60Reduction_DirectTest)
 
 TEST_F (SpellProcChanceTest, Combined_PPM_ChanceModifier_LevelReduction)
 

Detailed Description

Unit tests for proc chance calculations.

Tests CalcProcChance() behavior including:

  • Base chance from SpellProcEntry
  • PPM override when DamageInfo is present
  • Chance modifiers (SPELLMOD_CHANCE_OF_SUCCESS)
  • Level 60+ reduction (PROC_ATTR_REDUCE_PROC_60)

Definition in file SpellProcChanceTest.cpp.

Function Documentation

◆ TEST_F() [1/21]

TEST_F ( SpellProcChanceTest  ,
ApplyLevel60Reduction_DirectTest   
)
314{
315 // Level 60: no reduction
316 EXPECT_NEAR(ProcChanceTestHelper::ApplyLevel60Reduction(30.0f, 60), 30.0f, 0.01f);
317
318 // Level 70: 33.33% reduction
319 EXPECT_NEAR(ProcChanceTestHelper::ApplyLevel60Reduction(30.0f, 70), 20.0f, 0.5f);
320
321 // Level 80: 66.67% reduction
322 EXPECT_NEAR(ProcChanceTestHelper::ApplyLevel60Reduction(30.0f, 80), 10.0f, 0.5f);
323
324 // Level 90: 100% reduction
325 EXPECT_NEAR(ProcChanceTestHelper::ApplyLevel60Reduction(30.0f, 90), 0.0f, 0.1f);
326
327 // Level 100: capped at 0% (no negative chance)
328 EXPECT_GE(ProcChanceTestHelper::ApplyLevel60Reduction(30.0f, 100), 0.0f);
329}
static float ApplyLevel60Reduction(float baseChance, uint32 actorLevel)
Calculate level 60+ reduction Implements PROC_ATTR_REDUCE_PROC_60: 3.333% reduction per level above 6...
Definition ProcChanceTestHelper.h:63

References ProcChanceTestHelper::ApplyLevel60Reduction().

◆ TEST_F() [2/21]

TEST_F ( SpellProcChanceTest  ,
BaseChance_100Percent   
)
57{
58 auto procEntry = SpellProcEntryBuilder()
59 .WithChance(100.0f)
60 .Build();
61
62 float result = ProcChanceTestHelper::SimulateCalcProcChance(procEntry);
63 EXPECT_NEAR(result, 100.0f, 0.01f);
64}
static float SimulateCalcProcChance(SpellProcEntry const &procEntry, uint32 actorLevel=80, uint32 weaponSpeed=2500, float chanceModifier=0.0f, float ppmModifier=0.0f, bool hasDamageInfo=true, bool hasHealInfo=false)
Simulate CalcProcChance() from SpellAuras.cpp.
Definition ProcChanceTestHelper.h:85
Builder class for creating SpellProcEntry test instances.
Definition ProcEventInfoHelper.h:141
SpellProcEntry Build() const
Definition ProcEventInfoHelper.h:226
SpellProcEntryBuilder & WithChance(float chance)
Definition ProcEventInfoHelper.h:208

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [3/21]

TEST_F ( SpellProcChanceTest  ,
BaseChance_UsedWhenNoPPM   
)
46{
47 auto procEntry = SpellProcEntryBuilder()
48 .WithChance(25.0f)
50 .Build();
51
52 float result = ProcChanceTestHelper::SimulateCalcProcChance(procEntry);
53 EXPECT_NEAR(result, 25.0f, 0.01f);
54}
SpellProcEntryBuilder & WithProcsPerMinute(float ppm)
Definition ProcEventInfoHelper.h:202

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [4/21]

TEST_F ( SpellProcChanceTest  ,
BaseChance_Zero   
)
67{
68 auto procEntry = SpellProcEntryBuilder()
69 .WithChance(0.0f)
70 .Build();
71
72 float result = ProcChanceTestHelper::SimulateCalcProcChance(procEntry);
73 EXPECT_NEAR(result, 0.0f, 0.01f);
74}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [5/21]

TEST_F ( SpellProcChanceTest  ,
ChanceModifier_AppliedAfterPPM   
)
184{
185 auto procEntry = SpellProcEntryBuilder()
186 .WithProcsPerMinute(6.0f)
187 .Build();
188
189 // PPM gives 25%, +5% modifier = 30%
191 procEntry, 80, 2500, 5.0f, 0.0f, true);
192 EXPECT_NEAR(result, 30.0f, 0.01f);
193}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [6/21]

TEST_F ( SpellProcChanceTest  ,
ChanceModifier_NegativeModifier   
)
172{
173 auto procEntry = SpellProcEntryBuilder()
174 .WithChance(30.0f)
175 .Build();
176
177 // -10% modifier
179 procEntry, 80, 2500, -10.0f, 0.0f, false);
180 EXPECT_NEAR(result, 20.0f, 0.01f);
181}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [7/21]

TEST_F ( SpellProcChanceTest  ,
ChanceModifier_PositiveModifier   
)
160{
161 auto procEntry = SpellProcEntryBuilder()
162 .WithChance(20.0f)
163 .Build();
164
165 // +10% modifier
167 procEntry, 80, 2500, 10.0f, 0.0f, false);
168 EXPECT_NEAR(result, 30.0f, 0.01f);
169}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [8/21]

TEST_F ( SpellProcChanceTest  ,
Combined_PPM_ChanceModifier_LevelReduction   
)
336{
337 // PPM: 6 at 2500ms = 25%
338 // Chance modifier: +5% = 30%
339 // Level 70 reduction: 30% * (1 - 0.333) = 20%
340 auto procEntry = SpellProcEntryBuilder()
341 .WithProcsPerMinute(6.0f)
343 .Build();
344
346 procEntry, 70, 2500, 5.0f, 0.0f, true);
347 EXPECT_NEAR(result, 20.0f, 1.0f);
348}
@ PROC_ATTR_REDUCE_PROC_60
Definition SpellMgr.h:281
SpellProcEntryBuilder & WithAttributesMask(uint32 attributesMask)
Definition ProcEventInfoHelper.h:190

References SpellProcEntryBuilder::Build(), PROC_ATTR_REDUCE_PROC_60, ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [9/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_AppliedAfterPPM   
)
295{
296 // PPM calculation gives 25%, then level reduction applied
297 // Level 80 = 20 levels above 60, reduction = 66.67%
298 // 25% * (1 - 0.667) = 8.33%
299 auto procEntry = SpellProcEntryBuilder()
300 .WithProcsPerMinute(6.0f)
302 .Build();
303
305 procEntry, 80, 2500, 0.0f, 0.0f, true);
306 EXPECT_NEAR(result, 8.33f, 0.5f);
307}

References SpellProcEntryBuilder::Build(), PROC_ATTR_REDUCE_PROC_60, ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [10/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_MinimumAtLevel90   
)
267{
268 // Level 90 = 30 levels above 60
269 // Reduction = 30/30 = 100%
270 // 30% * (1 - 1.0) = 0%
271 auto procEntry = SpellProcEntryBuilder()
272 .WithChance(30.0f)
274 .Build();
275
277 procEntry, 90, 2500, 0.0f, 0.0f, false);
278 EXPECT_NEAR(result, 0.0f, 0.1f);
279}

References SpellProcEntryBuilder::Build(), PROC_ATTR_REDUCE_PROC_60, ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [11/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_NoReductionAtLevel60   
)

◆ TEST_F() [12/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_NoReductionBelowLevel60   
)

◆ TEST_F() [13/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_NotAppliedWithoutAttribute   
)
282{
283 auto procEntry = SpellProcEntryBuilder()
284 .WithChance(30.0f)
285 .WithAttributesMask(0) // No PROC_ATTR_REDUCE_PROC_60
286 .Build();
287
288 // At level 80, without the attribute, no reduction should occur
290 procEntry, 80, 2500, 0.0f, 0.0f, false);
291 EXPECT_NEAR(result, 30.0f, 0.01f);
292}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [14/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_ReductionAtLevel70   
)
237{
238 // Level 70 = 10 levels above 60
239 // Reduction = 10/30 = 33.33%
240 // 30% * (1 - 0.333) = 20%
241 auto procEntry = SpellProcEntryBuilder()
242 .WithChance(30.0f)
244 .Build();
245
247 procEntry, 70, 2500, 0.0f, 0.0f, false);
248 EXPECT_NEAR(result, 20.0f, 0.5f);
249}

References SpellProcEntryBuilder::Build(), PROC_ATTR_REDUCE_PROC_60, ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [15/21]

TEST_F ( SpellProcChanceTest  ,
Level60Reduction_ReductionAtLevel80   
)
252{
253 // Level 80 = 20 levels above 60
254 // Reduction = 20/30 = 66.67%
255 // 30% * (1 - 0.667) = 10%
256 auto procEntry = SpellProcEntryBuilder()
257 .WithChance(30.0f)
259 .Build();
260
262 procEntry, 80, 2500, 0.0f, 0.0f, false);
263 EXPECT_NEAR(result, 10.0f, 0.5f);
264}

References SpellProcEntryBuilder::Build(), PROC_ATTR_REDUCE_PROC_60, ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithAttributesMask(), and SpellProcEntryBuilder::WithChance().

◆ TEST_F() [16/21]

TEST_F ( SpellProcChanceTest  ,
PPM_Applied_WithHealInfo   
)
108{
109 auto procEntry = SpellProcEntryBuilder()
110 .WithChance(0.0f)
111 .WithProcsPerMinute(3.5f)
112 .Build();
113
114 // With HealInfo (no DamageInfo), PPM should still calculate
115 // 3000ms cast time * 3.5 PPM / 600 = 17.5%
117 procEntry, 80, 3000, 0.0f, 0.0f, false, true);
118 EXPECT_NEAR(result, 17.5f, 0.01f);
119}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [17/21]

TEST_F ( SpellProcChanceTest  ,
PPM_HealInfo_ZeroBaseChance_WouldBeZeroWithoutFix   
)
122{
123 // Reproduces the Omen of Clarity healing bug:
124 // PPM=3.5, Chance=0, and only HealInfo present (no DamageInfo)
125 // Without the fix, chance would be 0% because PPM branch was skipped
126 auto procEntry = SpellProcEntryBuilder()
127 .WithChance(0.0f)
128 .WithProcsPerMinute(3.5f)
129 .Build();
130
131 // Instant cast uses 1500ms minimum
133 procEntry, 80, 1500, 0.0f, 0.0f, false, true);
134 EXPECT_NEAR(result, 8.75f, 0.01f);
135 EXPECT_GT(result, 0.0f) << "PPM with HealInfo must produce non-zero chance";
136}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [18/21]

TEST_F ( SpellProcChanceTest  ,
PPM_NotApplied_WithoutDamageOrHealInfo   
)
95{
96 auto procEntry = SpellProcEntryBuilder()
97 .WithChance(50.0f)
99 .Build();
100
101 // Without DamageInfo or HealInfo, base chance is used
103 procEntry, 80, 2500, 0.0f, 0.0f, false, false);
104 EXPECT_NEAR(result, 50.0f, 0.01f);
105}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [19/21]

TEST_F ( SpellProcChanceTest  ,
PPM_OverridesBaseChance_WithDamageInfo   
)
81{
82 auto procEntry = SpellProcEntryBuilder()
83 .WithChance(50.0f) // This should be ignored
85 .Build();
86
87 // With DamageInfo, PPM takes precedence
88 // 2500ms * 6 PPM / 600 = 25%
90 procEntry, 80, 2500, 0.0f, 0.0f, true);
91 EXPECT_NEAR(result, 25.0f, 0.01f);
92}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), SpellProcEntryBuilder::WithChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [20/21]

TEST_F ( SpellProcChanceTest  ,
PPM_WithWeaponSpeedVariation   
)
139{
140 auto procEntry = SpellProcEntryBuilder()
141 .WithProcsPerMinute(6.0f)
142 .Build();
143
144 // Fast weapon: 1400ms
146 procEntry, 80, 1400, 0.0f, 0.0f, true);
147 EXPECT_NEAR(fastResult, 14.0f, 0.01f);
148
149 // Slow weapon: 3300ms
151 procEntry, 80, 3300, 0.0f, 0.0f, true);
152 EXPECT_NEAR(slowResult, 33.0f, 0.01f);
153}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithProcsPerMinute().

◆ TEST_F() [21/21]

TEST_F ( SpellProcChanceTest  ,
PPMModifier_IncreasesEffectivePPM   
)
196{
197 auto procEntry = SpellProcEntryBuilder()
198 .WithProcsPerMinute(6.0f)
199 .Build();
200
201 // 6 PPM + 2 PPM modifier = 8 effective PPM
202 // 2500 * 8 / 600 = 33.33%
204 procEntry, 80, 2500, 0.0f, 2.0f, true);
205 EXPECT_NEAR(result, 33.33f, 0.01f);
206}

References SpellProcEntryBuilder::Build(), ProcChanceTestHelper::SimulateCalcProcChance(), and SpellProcEntryBuilder::WithProcsPerMinute().