mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-03-15 13:35:08 +00:00
fix(Core/Spells): restore binary spell detection for CC resist via spell resistance (#25016)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com>
This commit is contained in:
@@ -3224,7 +3224,7 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
|
||||
continue;
|
||||
[[fallthrough]]; /// @todo: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
|
||||
default:
|
||||
if (!(spellInfo->Effects[j].CalcValue() &&
|
||||
if (!(spellInfo->Effects[j].CalcValue() ||
|
||||
((spellInfo->Effects[j].Effect == SPELL_EFFECT_INTERRUPT_CAST || spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH)) &&
|
||||
!spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES))))
|
||||
continue;
|
||||
|
||||
@@ -121,6 +121,26 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestSpellEntryHelper& WithEffectBasePoints(uint8 effIndex, int32 basePoints)
|
||||
{
|
||||
if (effIndex < MAX_SPELL_EFFECTS)
|
||||
_entry.EffectBasePoints[effIndex] = basePoints;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestSpellEntryHelper& WithEffectDieSides(uint8 effIndex, int32 dieSides)
|
||||
{
|
||||
if (effIndex < MAX_SPELL_EFFECTS)
|
||||
_entry.EffectDieSides[effIndex] = dieSides;
|
||||
return *this;
|
||||
}
|
||||
|
||||
TestSpellEntryHelper& WithAttributes(uint32 attr)
|
||||
{
|
||||
_entry.Attributes = attr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpellEntry const* Get() const
|
||||
{
|
||||
return &_entry;
|
||||
@@ -207,6 +227,24 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpellInfoBuilder& WithEffectBasePoints(uint8 effIndex, int32 basePoints)
|
||||
{
|
||||
_entryHelper.WithEffectBasePoints(effIndex, basePoints);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpellInfoBuilder& WithEffectDieSides(uint8 effIndex, int32 dieSides)
|
||||
{
|
||||
_entryHelper.WithEffectDieSides(effIndex, dieSides);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SpellInfoBuilder& WithAttributes(uint32 attr)
|
||||
{
|
||||
_entryHelper.WithAttributes(attr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Builds and returns a SpellInfo pointer
|
||||
// Note: Caller is responsible for lifetime management
|
||||
SpellInfo* Build()
|
||||
|
||||
153
src/test/server/game/Spells/BinarySpellDetectionTest.cpp
Normal file
153
src/test/server/game/Spells/BinarySpellDetectionTest.cpp
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This file is part of the AzerothCore Project. See AUTHORS file for Copyright information
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SpellInfoTestHelper.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
/**
|
||||
* @brief Tests for the binary spell detection condition used in
|
||||
* SpellMgr::LoadSpellInfoCustomAttributes.
|
||||
*
|
||||
* The condition determines whether a non-damage aura effect should mark
|
||||
* a spell as binary (fully resistable via spell resistance).
|
||||
*
|
||||
* Correct logic: CalcValue() || ((INTERRUPT_CAST || DONT_BREAK_STEALTH) && !NO_IMMUNITIES)
|
||||
*
|
||||
* A spell should be marked binary if:
|
||||
* - Its effect has a non-zero CalcValue (e.g. Fear, Polymorph, Frost Nova), OR
|
||||
* - It is an interrupt/stealth spell without the NO_IMMUNITIES attribute
|
||||
*/
|
||||
|
||||
namespace
|
||||
{
|
||||
// Replicates the binary detection condition from SpellMgr.cpp
|
||||
// Returns true if the effect should mark the spell as binary
|
||||
bool ShouldMarkBinary(SpellInfo const* spellInfo, uint8 effIndex)
|
||||
{
|
||||
return spellInfo->Effects[effIndex].CalcValue() ||
|
||||
((spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_INTERRUPT_CAST ||
|
||||
spellInfo->HasAttribute(SPELL_ATTR0_CU_DONT_BREAK_STEALTH)) &&
|
||||
!spellInfo->HasAttribute(SPELL_ATTR0_NO_IMMUNITIES));
|
||||
}
|
||||
}
|
||||
|
||||
class BinarySpellDetectionTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override {}
|
||||
};
|
||||
|
||||
// CC aura with non-zero CalcValue should be binary (e.g. Fear, Polymorph)
|
||||
TEST_F(BinarySpellDetectionTest, AuraWithCalcValue_IsBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_FEAR)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 1) // CalcValue = 0 + 1 = 1
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_SHADOW)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_TRUE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
|
||||
// Aura with zero CalcValue and no special attributes should NOT be binary
|
||||
TEST_F(BinarySpellDetectionTest, AuraWithZeroCalcValue_NotBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_FEAR)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 0) // CalcValue = 0
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_SHADOW)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_FALSE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
|
||||
// INTERRUPT_CAST effect without NO_IMMUNITIES should be binary
|
||||
TEST_F(BinarySpellDetectionTest, InterruptCast_IsBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_INTERRUPT_CAST)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 0) // CalcValue = 0
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_SHADOW)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_TRUE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
|
||||
// INTERRUPT_CAST with NO_IMMUNITIES should NOT be binary
|
||||
TEST_F(BinarySpellDetectionTest, InterruptCastWithNoImmunities_NotBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_INTERRUPT_CAST)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 0)
|
||||
.WithAttributes(SPELL_ATTR0_NO_IMMUNITIES)
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_SHADOW)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_FALSE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
|
||||
// Fear-like spell: APPLY_AURA MOD_FEAR with BasePoints=-1, DieSides=1
|
||||
// CalcValue = -1 + 1 = 0, but second effect has value
|
||||
TEST_F(BinarySpellDetectionTest, FearLikeSpell_SecondEffectHasValue_IsBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_FEAR)
|
||||
.WithEffectBasePoints(0, -1)
|
||||
.WithEffectDieSides(0, 1) // CalcValue = -1 + 1 = 0
|
||||
.WithEffect(1, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_INCREASE_SPEED)
|
||||
.WithEffectBasePoints(1, 24)
|
||||
.WithEffectDieSides(1, 1) // CalcValue = 24 + 1 = 25
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_SHADOW)
|
||||
.BuildUnique();
|
||||
|
||||
// Effect 0 has CalcValue 0, should not mark binary
|
||||
EXPECT_FALSE(ShouldMarkBinary(spell.get(), 0));
|
||||
// Effect 1 has CalcValue 25, should mark binary
|
||||
EXPECT_TRUE(ShouldMarkBinary(spell.get(), 1));
|
||||
}
|
||||
|
||||
// Polymorph-like: APPLY_AURA MOD_CONFUSE with positive BasePoints
|
||||
TEST_F(BinarySpellDetectionTest, PolymorphLikeSpell_IsBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_CONFUSE)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 1) // CalcValue = 1
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_ARCANE)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_TRUE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
|
||||
// Frost Nova-like: APPLY_AURA MOD_ROOT with positive BasePoints
|
||||
TEST_F(BinarySpellDetectionTest, FrostNovaLikeSpell_IsBinary)
|
||||
{
|
||||
auto spell = SpellInfoBuilder()
|
||||
.WithEffect(0, SPELL_EFFECT_APPLY_AURA, SPELL_AURA_MOD_ROOT)
|
||||
.WithEffectBasePoints(0, 0)
|
||||
.WithEffectDieSides(0, 1) // CalcValue = 1
|
||||
.WithSchoolMask(SPELL_SCHOOL_MASK_FROST)
|
||||
.BuildUnique();
|
||||
|
||||
EXPECT_TRUE(ShouldMarkBinary(spell.get(), 0));
|
||||
}
|
||||
Reference in New Issue
Block a user