aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2017-01-23 18:33:34 -0300
committerShauren <shauren.trinity@gmail.com>2019-06-15 18:41:09 +0200
commit2b0c73960b431acb25ddfba916017fbfe84f065b (patch)
treefe8d0d7bee4094346af0e63f6f20d6ae663a6da6 /src
parent6135ee1ad7052992093ad392347f4ef2c2ef4cf6 (diff)
Core/Spell: unified handling of SPELL_ATTR5_USABLE_WHILE_* attributes
Allowed mechanic mask is calculated on startup and auras checked against those mechanics Closes #18798 (cherrypicked from 3544577e48f3cf4fe4eae670facb3e5f77608e68) (cherrypicked from 53eb6ec61628147046f1e8996e05921a00726c11)
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Spells/Spell.cpp109
-rw-r--r--src/server/game/Spells/Spell.h1
-rw-r--r--src/server/game/Spells/SpellInfo.cpp34
-rw-r--r--src/server/game/Spells/SpellInfo.h3
4 files changed, 117 insertions, 30 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 778d4d1be6b..066ffe84c9d 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -5800,8 +5800,16 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const
if (m_spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CASTER_AURAS))
return SPELL_CAST_OK;
+ // these attributes only show the spell as usable on the client when it has related aura applied
+ // still they need to be checked against certain mechanics
+
+ // SPELL_ATTR5_USABLE_WHILE_STUNNED by default only MECHANIC_STUN (ie no sleep, knockout, freeze, etc.)
bool usableWhileStunned = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED);
+
+ // SPELL_ATTR5_USABLE_WHILE_FEARED by default only fear (ie no horror)
bool usableWhileFeared = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED);
+
+ // SPELL_ATTR5_USABLE_WHILE_CONFUSED by default only disorient (ie no polymorph)
bool usableWhileConfused = m_spellInfo->HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED);
// Check whether the cast should be prevented by any state you might have.
@@ -5821,39 +5829,57 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const
}
*/
- if (unitflag & UNIT_FLAG_STUNNED)
+ // spell has attribute usable while having a cc state, check if caster has allowed mechanic auras, another mechanic types must prevent cast spell
+ auto mechanicCheck = [&](AuraType type) -> SpellCastResult
{
- // spell is usable while stunned, check if caster has allowed stun auras, another stun types must prevent cast spell
- if (usableWhileStunned)
+ bool foundNotMechanic = false;
+ Unit::AuraEffectList const& auras = m_caster->GetAuraEffectsByType(type);
+ for (AuraEffect const* aurEff : auras)
{
- static uint32 const allowedStunMask =
- 1 << MECHANIC_STUN
- | 1 << MECHANIC_SLEEP;
-
- bool foundNotStun = false;
- Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN);
- for (AuraEffect const* stunEff : stunAuras)
+ uint32 const mechanicMask = aurEff->GetSpellInfo()->GetAllEffectsMechanicMask();
+ if (mechanicMask && !(mechanicMask & GetSpellInfo()->GetAllowedMechanicMask()))
{
- uint32 const stunMechanicMask = stunEff->GetSpellInfo()->GetAllEffectsMechanicMask();
- if (stunMechanicMask && !(stunMechanicMask & allowedStunMask))
- {
- foundNotStun = true;
+ foundNotMechanic = true;
- // fill up aura mechanic info to send client proper error message
- if (param1)
- {
- *param1 = stunEff->GetSpellInfo()->GetEffect(stunEff->GetEffIndex())->Mechanic;
- if (!*param1)
- *param1 = stunEff->GetSpellInfo()->Mechanic;
- }
- break;
+ // fill up aura mechanic info to send client proper error message
+ if (param1)
+ {
+ *param1 = aurEff->GetSpellInfo()->GetEffect(aurEff->GetEffIndex())->Mechanic;
+ if (!*param1)
+ *param1 = aurEff->GetSpellInfo()->Mechanic;
}
+
+ break;
}
+ }
- if (foundNotStun)
- result = SPELL_FAILED_STUNNED;
+ if (foundNotMechanic)
+ {
+ switch (type)
+ {
+ case SPELL_AURA_MOD_STUN:
+ return SPELL_FAILED_STUNNED;
+ case SPELL_AURA_MOD_FEAR:
+ return SPELL_FAILED_FLEEING;
+ case SPELL_AURA_MOD_CONFUSE:
+ return SPELL_FAILED_CONFUSED;
+ default:
+ ABORT();
+ return SPELL_FAILED_NOT_KNOWN;
+ }
+ }
+
+ return SPELL_CAST_OK;
+ };
+
+ if (unitflag & UNIT_FLAG_STUNNED)
+ {
+ if (usableWhileStunned)
+ {
+ SpellCastResult mechanicResult = mechanicCheck(SPELL_AURA_MOD_STUN);
+ if (mechanicResult != SPELL_CAST_OK)
+ result = mechanicResult;
}
- // Not usable while stunned, however spell might provide some immunity that allows to cast it anyway
else if (!CheckSpellCancelsStun(param1))
result = SPELL_FAILED_STUNNED;
}
@@ -5861,11 +5887,29 @@ SpellCastResult Spell::CheckCasterAuras(uint32* param1) const
result = SPELL_FAILED_SILENCED;
else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_PACIFY && !CheckSpellCancelsPacify(param1))
result = SPELL_FAILED_PACIFIED;
- else if (unitflag & UNIT_FLAG_FLEEING && !usableWhileFeared && !CheckSpellCancelsFear(param1))
- result = SPELL_FAILED_FLEEING;
- else if (unitflag & UNIT_FLAG_CONFUSED && !usableWhileConfused && !CheckSpellCancelsConfuse(param1))
- result = SPELL_FAILED_CONFUSED;
- else if (m_caster->HasUnitFlag2(UNIT_FLAG2_NO_ACTIONS) && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS)
+ else if (unitflag & UNIT_FLAG_FLEEING)
+ {
+ if (usableWhileFeared)
+ {
+ SpellCastResult mechanicResult = mechanicCheck(SPELL_AURA_MOD_FEAR);
+ if (mechanicResult != SPELL_CAST_OK)
+ result = mechanicResult;
+ }
+ else if (!CheckSpellCancelsFear(param1))
+ result = SPELL_FAILED_FLEEING;
+ }
+ else if (unitflag & UNIT_FLAG_CONFUSED)
+ {
+ if (usableWhileConfused)
+ {
+ SpellCastResult mechanicResult = mechanicCheck(SPELL_AURA_MOD_CONFUSE);
+ if (mechanicResult != SPELL_CAST_OK)
+ result = mechanicResult;
+ }
+ else if (!CheckSpellCancelsConfuse(param1))
+ result = SPELL_FAILED_CONFUSED;
+ }
+ else if (m_caster->HasUnitFlag2(UNIT_FLAG2_NO_ACTIONS) && m_spellInfo->PreventionType & SPELL_PREVENTION_TYPE_NO_ACTIONS && !CheckSpellCancelsNoActions(param1))
result = SPELL_FAILED_NO_ACTIONS;
// Attr must make flag drop spell totally immune from all effects
@@ -5935,6 +5979,11 @@ bool Spell::CheckSpellCancelsConfuse(uint32* param1) const
return CheckSpellCancelsAuraEffect(SPELL_AURA_MOD_CONFUSE, param1);
}
+bool Spell::CheckSpellCancelsNoActions(uint32* param1) const
+{
+ return CheckSpellCancelsAuraEffect(SPELL_AURA_MOD_NO_ACTIONS, param1);
+}
+
SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules()
{
bool isRatedBattleground = false; // NYI
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 74b3eee8691..259af5c2885 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -551,6 +551,7 @@ class TC_GAME_API Spell
bool CheckSpellCancelsPacify(uint32* param1) const;
bool CheckSpellCancelsFear(uint32* param1) const;
bool CheckSpellCancelsConfuse(uint32* param1) const;
+ bool CheckSpellCancelsNoActions(uint32* param1) const;
int32 CalculateDamage(uint8 i, Unit const* target, float* var = nullptr) const;
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index f264e72c52a..bbd597b9096 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -1203,6 +1203,8 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const&
_spellSpecific = SPELL_SPECIFIC_NORMAL;
_auraState = AURA_STATE_NONE;
+
+ _allowedMechanicMask = 0;
}
SpellInfo::~SpellInfo()
@@ -3370,6 +3372,8 @@ void SpellInfo::_LoadImmunityInfo()
immuneInfo.AuraTypeImmune.shrink_to_fit();
immuneInfo.SpellEffectImmune.shrink_to_fit();
+
+ _allowedMechanicMask |= immuneInfo.MechanicImmuneMask;
};
for (auto const& effects : _effects)
@@ -3382,6 +3386,31 @@ void SpellInfo::_LoadImmunityInfo()
loadImmunityInfoFn(const_cast<SpellEffectInfo*>(effect));
}
}
+
+ if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_STUNNED))
+ {
+ switch (Id)
+ {
+ case 22812: // Barkskin
+ _allowedMechanicMask |=
+ (1 << MECHANIC_STUN) |
+ (1 << MECHANIC_FREEZE) |
+ (1 << MECHANIC_KNOCKOUT) |
+ (1 << MECHANIC_SLEEP);
+ break;
+ case 49039: // Lichborne, don't allow normal stuns
+ break;
+ default:
+ _allowedMechanicMask |= (1 << MECHANIC_STUN);
+ break;
+ }
+ }
+
+ if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_CONFUSED))
+ _allowedMechanicMask |= (1 << MECHANIC_DISORIENTED);
+
+ if (HasAttribute(SPELL_ATTR5_USABLE_WHILE_FEARED))
+ _allowedMechanicMask |= (1 << MECHANIC_FEAR);
}
void SpellInfo::ApplyAllSpellImmunitiesTo(Unit* target, SpellEffectInfo const* effect, bool apply) const
@@ -3582,6 +3611,11 @@ bool SpellInfo::SpellCancelsAuraEffect(AuraEffect const* aurEff) const
return false;
}
+uint32 SpellInfo::GetAllowedMechanicMask() const
+{
+ return _allowedMechanicMask;
+}
+
float SpellInfo::GetMinRange(bool positive) const
{
if (!RangeEntry)
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 97fa181fb36..ff053e0550b 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -668,6 +668,8 @@ class TC_GAME_API SpellInfo
bool CanSpellProvideImmunityAgainstAura(SpellInfo const* auraSpellInfo) const;
bool SpellCancelsAuraEffect(AuraEffect const* aurEff) const;
+ uint32 GetAllowedMechanicMask() const;
+
private:
// loading helpers
void _InitializeExplicitTargetMask();
@@ -691,6 +693,7 @@ class TC_GAME_API SpellInfo
AuraStateType _auraState;
SpellDiminishInfo _diminishInfo;
+ uint32 _allowedMechanicMask;
};
#endif // _SPELLINFO_H