Core/Spells: add correct checking for dispeling errors. Fixes spammable cleanse.
This commit is contained in:
@@ -4113,6 +4113,45 @@ Aura* Unit::GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID, uint64 itemC
|
|||||||
return aurApp ? aurApp->GetBase() : NULL;
|
return aurApp ? aurApp->GetBase() : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Unit::GetDispellableAuraList(Unit* caster, uint32 dispelMask, DispelChargesList& dispelList)
|
||||||
|
{
|
||||||
|
// we should not be able to dispel diseases if the target is affected by unholy blight
|
||||||
|
if (dispelMask & (1 << DISPEL_DISEASE) && HasAura(50536))
|
||||||
|
dispelMask &= ~(1 << DISPEL_DISEASE);
|
||||||
|
|
||||||
|
AuraMap const& auras = GetOwnedAuras();
|
||||||
|
for (AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
||||||
|
{
|
||||||
|
Aura* aura = itr->second;
|
||||||
|
AuraApplication * aurApp = aura->GetApplicationOfTarget(GetGUID());
|
||||||
|
if (!aurApp)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// don't try to remove passive auras
|
||||||
|
if (aura->IsPassive())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (aura->GetSpellInfo()->GetDispelMask() & dispelMask)
|
||||||
|
{
|
||||||
|
if (aura->GetSpellInfo()->Dispel == DISPEL_MAGIC)
|
||||||
|
{
|
||||||
|
// do not remove positive auras if friendly target
|
||||||
|
// negative auras if non-friendly target
|
||||||
|
if (aurApp->IsPositive() == IsFriendlyTo(caster))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
|
||||||
|
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
|
||||||
|
// Polymorph instead of 1 / (5 + 1) -> 16%.
|
||||||
|
bool dispel_charges = aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES;
|
||||||
|
uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
|
||||||
|
if (charges > 0)
|
||||||
|
dispelList.push_back(std::make_pair(aura, charges));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const
|
bool Unit::HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster) const
|
||||||
{
|
{
|
||||||
for (AuraApplicationMap::const_iterator itr = m_appliedAuras.lower_bound(spellId); itr != m_appliedAuras.upper_bound(spellId); ++itr)
|
for (AuraApplicationMap::const_iterator itr = m_appliedAuras.lower_bound(spellId); itr != m_appliedAuras.upper_bound(spellId); ++itr)
|
||||||
|
|||||||
@@ -341,6 +341,7 @@ class Transport;
|
|||||||
class Vehicle;
|
class Vehicle;
|
||||||
|
|
||||||
typedef std::list<Unit*> UnitList;
|
typedef std::list<Unit*> UnitList;
|
||||||
|
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
|
||||||
|
|
||||||
struct SpellImmune
|
struct SpellImmune
|
||||||
{
|
{
|
||||||
@@ -1814,6 +1815,8 @@ class Unit : public WorldObject
|
|||||||
AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0, AuraApplication * except = NULL) const;
|
AuraApplication * GetAuraApplicationOfRankedSpell(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0, AuraApplication * except = NULL) const;
|
||||||
Aura* GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;
|
Aura* GetAuraOfRankedSpell(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;
|
||||||
|
|
||||||
|
void GetDispellableAuraList(Unit* caster, uint32 dispelMask, DispelChargesList& dispelList);
|
||||||
|
|
||||||
bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const;
|
bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster = 0) const;
|
||||||
uint32 GetAuraCount(uint32 spellId) const;
|
uint32 GetAuraCount(uint32 spellId) const;
|
||||||
bool HasAura(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;
|
bool HasAura(uint32 spellId, uint64 casterGUID = 0, uint64 itemCasterGUID = 0, uint8 reqEffMask = 0) const;
|
||||||
|
|||||||
@@ -4938,6 +4938,24 @@ SpellCastResult Spell::CheckCast(bool strict)
|
|||||||
if (castResult != SPELL_CAST_OK)
|
if (castResult != SPELL_CAST_OK)
|
||||||
return castResult;
|
return castResult;
|
||||||
|
|
||||||
|
bool hasDispellableAura = false;
|
||||||
|
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
|
||||||
|
if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DISPEL)
|
||||||
|
if (Unit* target = m_targets.GetUnitTarget())
|
||||||
|
{
|
||||||
|
DispelChargesList dispelList;
|
||||||
|
uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue));
|
||||||
|
target->GetDispellableAuraList(m_caster, dispelMask, dispelList);
|
||||||
|
if (!dispelList.empty())
|
||||||
|
{
|
||||||
|
hasDispellableAura = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasDispellableAura)
|
||||||
|
return SPELL_FAILED_NOTHING_TO_DISPEL;
|
||||||
|
|
||||||
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
|
for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
|
||||||
{
|
{
|
||||||
// for effects of spells that have only one target
|
// for effects of spells that have only one target
|
||||||
|
|||||||
@@ -2536,7 +2536,6 @@ void Spell::EffectLearnSpell(SpellEffIndex effIndex)
|
|||||||
}
|
}
|
||||||
|
|
||||||
typedef std::list< std::pair<uint32, uint64> > DispelList;
|
typedef std::list< std::pair<uint32, uint64> > DispelList;
|
||||||
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
|
|
||||||
void Spell::EffectDispel(SpellEffIndex effIndex)
|
void Spell::EffectDispel(SpellEffIndex effIndex)
|
||||||
{
|
{
|
||||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||||
@@ -2545,48 +2544,12 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
|
|||||||
if (!unitTarget)
|
if (!unitTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DispelChargesList dispel_list;
|
|
||||||
|
|
||||||
// Create dispel mask by dispel type
|
// Create dispel mask by dispel type
|
||||||
uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue;
|
uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue;
|
||||||
uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type));
|
uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type));
|
||||||
|
|
||||||
// we should not be able to dispel diseases if the target is affected by unholy blight
|
DispelChargesList dispel_list;
|
||||||
if (dispelMask & (1 << DISPEL_DISEASE) && unitTarget->HasAura(50536))
|
unitTarget->GetDispellableAuraList(m_caster, dispelMask, dispel_list);
|
||||||
dispelMask &= ~(1 << DISPEL_DISEASE);
|
|
||||||
|
|
||||||
Unit::AuraMap const& auras = unitTarget->GetOwnedAuras();
|
|
||||||
for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
|
|
||||||
{
|
|
||||||
Aura* aura = itr->second;
|
|
||||||
AuraApplication * aurApp = aura->GetApplicationOfTarget(unitTarget->GetGUID());
|
|
||||||
if (!aurApp)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// don't try to remove passive auras
|
|
||||||
if (aura->IsPassive())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (aura->GetSpellInfo()->GetDispelMask() & dispelMask)
|
|
||||||
{
|
|
||||||
if (aura->GetSpellInfo()->Dispel == DISPEL_MAGIC)
|
|
||||||
{
|
|
||||||
// do not remove positive auras if friendly target
|
|
||||||
// negative auras if non-friendly target
|
|
||||||
if (aurApp->IsPositive() == unitTarget->IsFriendlyTo(m_caster))
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
|
|
||||||
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) -> 50% chance to dispell
|
|
||||||
// Polymorph instead of 1 / (5 + 1) -> 16%.
|
|
||||||
bool dispel_charges = aura->GetSpellInfo()->AttributesEx7 & SPELL_ATTR7_DISPEL_CHARGES;
|
|
||||||
uint8 charges = dispel_charges ? aura->GetCharges() : aura->GetStackAmount();
|
|
||||||
if (charges > 0)
|
|
||||||
dispel_list.push_back(std::make_pair(aura, charges));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dispel_list.empty())
|
if (dispel_list.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user