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

Tests for the CC break-on-damage proc mechanism. More...

#include "AuraStub.h"
#include "ProcChanceTestHelper.h"
#include "ProcEventInfoHelper.h"
#include "SpellMgr.h"
#include "WorldMock.h"
#include "gtest/gtest.h"

Go to the source code of this file.

Classes

class  BreakableCCProcTest
 

Functions

static bool SimulateBreakableCCProc (AuraEffectStub *effect, int32_t damage)
 Simulates HandleBreakableCCAuraProc logic.
 
static int32_t SimulateCCThreshold (uint8_t casterLevel)
 Simulates CalculateAmount for CC auras.
 
 TEST_F (BreakableCCProcTest, SmallDamage_ReducesThreshold_AuraSurvives)
 
 TEST_F (BreakableCCProcTest, ExactThresholdDamage_RemovesAura)
 
 TEST_F (BreakableCCProcTest, ExceedThresholdDamage_RemovesAura)
 
 TEST_F (BreakableCCProcTest, MultipleDamageHits_AccumulateUntilBreak)
 
 TEST_F (BreakableCCProcTest, MultipleDamageHits_OvershootBreak)
 
 TEST_F (BreakableCCProcTest, OneDamage_ReducesThreshold)
 
 TEST_F (BreakableCCProcTest, Level80Threshold_IsReasonable)
 
 TEST_F (BreakableCCProcTest, LowerLevelCaster_LowerThreshold)
 
 TEST_F (BreakableCCProcTest, Level80Fear_BreaksOnModerateDamage)
 
 TEST_F (BreakableCCProcTest, Level80Fear_SurvivesSmallDots)
 
 TEST_F (BreakableCCProcTest, FearProcEntry_MatchesTakenMeleeDamage)
 
 TEST_F (BreakableCCProcTest, FearProcEntry_MatchesTakenSpellDamage)
 
 TEST_F (BreakableCCProcTest, FearProcEntry_DoesNotMatchHealEvent)
 
 TEST_F (BreakableCCProcTest, FearProcChance_Is100Percent)
 
 TEST_F (BreakableCCProcTest, GlyphOfFear_IncreasesThreshold)
 

Detailed Description

Tests for the CC break-on-damage proc mechanism.

CC auras (Fear, Polymorph, Stun, Root, Transform) have a damage threshold set in CalculateAmount. When damage is taken, HandleBreakableCCAuraProc subtracts the damage from the threshold and removes the aura when it reaches zero.

The threshold is calculated as: BaseHealth(casterLevel, CLASS_WARRIOR) / 4.75

This gives level 80 a threshold of ~2648 HP (12588 / 4.75).

Definition in file BreakableCCProcTest.cpp.

Function Documentation

◆ SimulateBreakableCCProc()

static bool SimulateBreakableCCProc ( AuraEffectStub effect,
int32_t  damage 
)
static

Simulates HandleBreakableCCAuraProc logic.

Mirrors AuraEffect::HandleBreakableCCAuraProc from SpellAuraEffects.cpp: damageLeft = GetAmount() - damage if (damageLeft <= 0) remove aura else SetAmount(damageLeft)

Parameters
effectThe CC aura effect stub (amount = damage threshold)
damageDamage dealt to the CC'd target
Returns
true if the aura should be removed (threshold exceeded)
55{
56 int32_t damageLeft = effect->GetAmount() - damage;
57 if (damageLeft <= 0)
58 return true; // aura removed
59 effect->SetAmount(damageLeft);
60 return false; // aura survives, threshold reduced
61}
int32_t GetAmount() const
Definition AuraStub.h:42
void SetAmount(int32_t amount)
Definition AuraStub.h:48

References AuraEffectStub::GetAmount(), and AuraEffectStub::SetAmount().

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

◆ SimulateCCThreshold()

static int32_t SimulateCCThreshold ( uint8_t  casterLevel)
static

Simulates CalculateAmount for CC auras.

Mirrors AuraEffect::CalculateAmount from SpellAuraEffects.cpp for MOD_FEAR/MOD_CONFUSE/MOD_STUN/MOD_ROOT/TRANSFORM: amount = BaseHealth(casterLevel, CLASS_WARRIOR) / 4.75

Uses known Warrior base health values from CreatureBaseStats DBC.

73{
74 // Warrior base health at key levels (EXPANSION_WRATH_OF_THE_LICH_KING)
75 // From creature_classlevelstats for CLASS_WARRIOR
76 struct LevelHealth { uint8_t level; int32_t health; };
77 static constexpr LevelHealth table[] = {
78 {1, 60}, {10, 424}, {20, 1128}, {30, 2078}, {40, 3228},
79 {50, 4978}, {60, 7361}, {70, 9940}, {80, 12588},
80 };
81
82 int32_t baseHealth = 12588; // default to level 80
83 for (auto const& entry : table)
84 {
85 if (entry.level == casterLevel)
86 {
87 baseHealth = entry.health;
88 break;
89 }
90 }
91
92 return static_cast<int32_t>(baseHealth / 4.75f);
93}

Referenced by TEST_F(), TEST_F(), TEST_F(), TEST_F(), and TEST_F().

◆ TEST_F() [1/15]

TEST_F ( BreakableCCProcTest  ,
ExactThresholdDamage_RemovesAura   
)
145{
146 auto effect = CreateCCEffect(1000);
147
148 bool removed = SimulateBreakableCCProc(&effect, 1000);
149
150 EXPECT_TRUE(removed);
151}
static bool SimulateBreakableCCProc(AuraEffectStub *effect, int32_t damage)
Simulates HandleBreakableCCAuraProc logic.
Definition BreakableCCProcTest.cpp:54

References SimulateBreakableCCProc().

◆ TEST_F() [2/15]

TEST_F ( BreakableCCProcTest  ,
ExceedThresholdDamage_RemovesAura   
)
154{
155 auto effect = CreateCCEffect(1000);
156
157 bool removed = SimulateBreakableCCProc(&effect, 5000);
158
159 EXPECT_TRUE(removed);
160}

References SimulateBreakableCCProc().

◆ TEST_F() [3/15]

TEST_F ( BreakableCCProcTest  ,
FearProcChance_Is100Percent   
)
344{
345 auto procEntry = SpellProcEntryBuilder()
346 .WithChance(100.0f)
347 .Build();
348
349 // Fear has 100% proc chance from DBC - every damage event triggers
350 float chance = ProcChanceTestHelper::SimulateCalcProcChance(procEntry);
351 EXPECT_FLOAT_EQ(chance, 100.0f);
352}
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() [4/15]

TEST_F ( BreakableCCProcTest  ,
FearProcEntry_DoesNotMatchHealEvent   
)
317{
318 auto procEntry = SpellProcEntryBuilder()
329 .WithChance(100.0f)
330 .Build();
331
332 // Heal should NOT trigger Fear's proc
333 auto healEvent = ProcEventInfoBuilder()
338 .Build();
339
340 EXPECT_FALSE(sSpellMgr->CanSpellTriggerProcOnEvent(procEntry, healEvent));
341}
@ PROC_HIT_NORMAL
Definition SpellMgr.h:257
#define sSpellMgr
Definition SpellMgr.h:836
@ PROC_SPELL_TYPE_HEAL
Definition SpellMgr.h:240
@ PROC_SPELL_TYPE_DAMAGE
Definition SpellMgr.h:239
@ PROC_SPELL_PHASE_HIT
Definition SpellMgr.h:249
@ PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK
Definition SpellMgr.h:120
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
Definition SpellMgr.h:135
@ PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS
Definition SpellMgr.h:123
@ PROC_FLAG_TAKEN_PERIODIC
Definition SpellMgr.h:138
@ PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG
Definition SpellMgr.h:129
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS
Definition SpellMgr.h:132
@ PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK
Definition SpellMgr.h:114
@ PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS
Definition SpellMgr.h:117
Builder class for creating ProcEventInfo test instances.
Definition ProcEventInfoHelper.h:31
ProcEventInfoBuilder & WithSpellPhaseMask(uint32 spellPhaseMask)
Definition ProcEventInfoHelper.h:69
ProcEventInfoBuilder & WithTypeMask(uint32 typeMask)
Definition ProcEventInfoHelper.h:57
ProcEventInfoBuilder & WithHitMask(uint32 hitMask)
Definition ProcEventInfoHelper.h:75
ProcEventInfo Build()
Definition ProcEventInfoHelper.h:111
ProcEventInfoBuilder & WithSpellTypeMask(uint32 spellTypeMask)
Definition ProcEventInfoHelper.h:63
SpellProcEntryBuilder & WithSpellTypeMask(uint32 spellTypeMask)
Definition ProcEventInfoHelper.h:172
SpellProcEntryBuilder & WithProcFlags(uint32 procFlags)
Definition ProcEventInfoHelper.h:166
SpellProcEntryBuilder & WithSpellPhaseMask(uint32 spellPhaseMask)
Definition ProcEventInfoHelper.h:178

References ProcEventInfoBuilder::Build(), SpellProcEntryBuilder::Build(), PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK, PROC_FLAG_TAKEN_PERIODIC, PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS, PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS, PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS, PROC_HIT_NORMAL, PROC_SPELL_PHASE_HIT, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_TYPE_HEAL, sSpellMgr, SpellProcEntryBuilder::WithChance(), ProcEventInfoBuilder::WithHitMask(), SpellProcEntryBuilder::WithProcFlags(), ProcEventInfoBuilder::WithSpellPhaseMask(), SpellProcEntryBuilder::WithSpellPhaseMask(), ProcEventInfoBuilder::WithSpellTypeMask(), SpellProcEntryBuilder::WithSpellTypeMask(), and ProcEventInfoBuilder::WithTypeMask().

◆ TEST_F() [5/15]

TEST_F ( BreakableCCProcTest  ,
FearProcEntry_MatchesTakenMeleeDamage   
)
262{
263 // Fear's auto-generated proc entry from DBC ProcFlags
264 auto procEntry = SpellProcEntryBuilder()
275 .WithChance(100.0f)
276 .Build();
277
278 // Melee auto attack should trigger
279 auto meleeEvent = ProcEventInfoBuilder()
284 .Build();
285
286 EXPECT_TRUE(sSpellMgr->CanSpellTriggerProcOnEvent(procEntry, meleeEvent));
287}

References ProcEventInfoBuilder::Build(), SpellProcEntryBuilder::Build(), PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK, PROC_FLAG_TAKEN_PERIODIC, PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS, PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS, PROC_HIT_NORMAL, PROC_SPELL_PHASE_HIT, PROC_SPELL_TYPE_DAMAGE, sSpellMgr, SpellProcEntryBuilder::WithChance(), ProcEventInfoBuilder::WithHitMask(), SpellProcEntryBuilder::WithProcFlags(), ProcEventInfoBuilder::WithSpellPhaseMask(), SpellProcEntryBuilder::WithSpellPhaseMask(), ProcEventInfoBuilder::WithSpellTypeMask(), SpellProcEntryBuilder::WithSpellTypeMask(), and ProcEventInfoBuilder::WithTypeMask().

◆ TEST_F() [6/15]

TEST_F ( BreakableCCProcTest  ,
FearProcEntry_MatchesTakenSpellDamage   
)

References ProcEventInfoBuilder::Build(), SpellProcEntryBuilder::Build(), PROC_FLAG_TAKEN_MELEE_AUTO_ATTACK, PROC_FLAG_TAKEN_PERIODIC, PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS, PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS, PROC_HIT_NORMAL, PROC_SPELL_PHASE_HIT, PROC_SPELL_TYPE_DAMAGE, sSpellMgr, SpellProcEntryBuilder::WithChance(), ProcEventInfoBuilder::WithHitMask(), SpellProcEntryBuilder::WithProcFlags(), ProcEventInfoBuilder::WithSpellPhaseMask(), SpellProcEntryBuilder::WithSpellPhaseMask(), ProcEventInfoBuilder::WithSpellTypeMask(), SpellProcEntryBuilder::WithSpellTypeMask(), and ProcEventInfoBuilder::WithTypeMask().

◆ TEST_F() [7/15]

TEST_F ( BreakableCCProcTest  ,
GlyphOfFear_IncreasesThreshold   
)
359{
360 // Glyph of Fear adds +100% to the damage threshold (MiscValue 7801)
361 int32_t baseThreshold = SimulateCCThreshold(80); // ~2650
362 int32_t glyphedThreshold = baseThreshold + (baseThreshold * 100 / 100); // +100%
363
364 auto effect = CreateCCEffect(glyphedThreshold);
365
366 // Should survive hits that would normally break it
367 EXPECT_FALSE(SimulateBreakableCCProc(&effect, 3000));
368 EXPECT_GT(effect.GetAmount(), 0);
369}
static int32_t SimulateCCThreshold(uint8_t casterLevel)
Simulates CalculateAmount for CC auras.
Definition BreakableCCProcTest.cpp:72

References SimulateBreakableCCProc(), and SimulateCCThreshold().

◆ TEST_F() [8/15]

TEST_F ( BreakableCCProcTest  ,
Level80Fear_BreaksOnModerateDamage   
)
221{
222 // Simulate a level 80 warlock's Fear
223 int32_t threshold = SimulateCCThreshold(80); // ~2650
224 auto effect = CreateCCEffect(threshold);
225
226 // A 3000 damage hit should break it
227 EXPECT_TRUE(SimulateBreakableCCProc(&effect, 3000));
228}

References SimulateBreakableCCProc(), and SimulateCCThreshold().

◆ TEST_F() [9/15]

TEST_F ( BreakableCCProcTest  ,
Level80Fear_SurvivesSmallDots   
)
231{
232 // Simulate a level 80 warlock's Fear
233 int32_t threshold = SimulateCCThreshold(80); // ~2650
234 auto effect = CreateCCEffect(threshold);
235
236 // Small DoT ticks of 200 each - Fear should survive multiple ticks
237 for (int i = 0; i < 10; ++i)
238 {
239 bool removed = SimulateBreakableCCProc(&effect, 200);
240 if (i < 12) // Should survive at least 12 ticks (200*13 = 2600 < 2650)
241 {
242 // We expect it to survive for ~13 ticks
243 if (!removed)
244 continue;
245 }
246 if (removed)
247 {
248 // Should break around tick 13-14
249 EXPECT_GE(i, 12);
250 return;
251 }
252 }
253 // If we get here, verify remaining threshold
254 EXPECT_GT(effect.GetAmount(), 0);
255}

References SimulateBreakableCCProc(), and SimulateCCThreshold().

◆ TEST_F() [10/15]

TEST_F ( BreakableCCProcTest  ,
Level80Threshold_IsReasonable   
)
203{
204 int32_t threshold = SimulateCCThreshold(80);
205
206 // Level 80 warrior base health = 12588
207 // Threshold = 12588 / 4.75 ≈ 2650
208 EXPECT_GT(threshold, 2600);
209 EXPECT_LT(threshold, 2700);
210}

References SimulateCCThreshold().

◆ TEST_F() [11/15]

TEST_F ( BreakableCCProcTest  ,
LowerLevelCaster_LowerThreshold   
)
213{
214 int32_t threshold60 = SimulateCCThreshold(60);
215 int32_t threshold80 = SimulateCCThreshold(80);
216
217 EXPECT_LT(threshold60, threshold80);
218}

References SimulateCCThreshold().

◆ TEST_F() [12/15]

TEST_F ( BreakableCCProcTest  ,
MultipleDamageHits_AccumulateUntilBreak   
)
163{
164 auto effect = CreateCCEffect(1000);
165
166 // First hit: 400 damage, 600 remaining
167 EXPECT_FALSE(SimulateBreakableCCProc(&effect, 400));
168 EXPECT_EQ(effect.GetAmount(), 600);
169
170 // Second hit: 300 damage, 300 remaining
171 EXPECT_FALSE(SimulateBreakableCCProc(&effect, 300));
172 EXPECT_EQ(effect.GetAmount(), 300);
173
174 // Third hit: 300 damage, exactly 0 remaining -> remove
175 EXPECT_TRUE(SimulateBreakableCCProc(&effect, 300));
176}

References SimulateBreakableCCProc().

◆ TEST_F() [13/15]

TEST_F ( BreakableCCProcTest  ,
MultipleDamageHits_OvershootBreak   
)
179{
180 auto effect = CreateCCEffect(500);
181
182 // First hit: 200 damage
183 EXPECT_FALSE(SimulateBreakableCCProc(&effect, 200));
184 EXPECT_EQ(effect.GetAmount(), 300);
185
186 // Second hit: 400 damage, exceeds remaining 300
187 EXPECT_TRUE(SimulateBreakableCCProc(&effect, 400));
188}

References SimulateBreakableCCProc().

◆ TEST_F() [14/15]

TEST_F ( BreakableCCProcTest  ,
OneDamage_ReducesThreshold   
)
191{
192 auto effect = CreateCCEffect(1000);
193
194 EXPECT_FALSE(SimulateBreakableCCProc(&effect, 1));
195 EXPECT_EQ(effect.GetAmount(), 999);
196}

References SimulateBreakableCCProc().

◆ TEST_F() [15/15]

TEST_F ( BreakableCCProcTest  ,
SmallDamage_ReducesThreshold_AuraSurvives   
)
135{
136 auto effect = CreateCCEffect(1000);
137
138 bool removed = SimulateBreakableCCProc(&effect, 100);
139
140 EXPECT_FALSE(removed);
141 EXPECT_EQ(effect.GetAmount(), 900);
142}

References SimulateBreakableCCProc().