aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellEffects.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server/game/Spells/SpellEffects.cpp')
-rw-r--r--src/server/game/Spells/SpellEffects.cpp184
1 files changed, 90 insertions, 94 deletions
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 0937d916868..c220e3eba01 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -2410,83 +2410,81 @@ void Spell::EffectDispel(SpellEffIndex effIndex)
uint32 dispel_type = m_spellInfo->Effects[effIndex].MiscValue;
uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(dispel_type));
- DispelChargesList dispel_list;
- unitTarget->GetDispellableAuraList(m_caster, dispelMask, dispel_list);
- if (dispel_list.empty())
+ DispelChargesList dispelList;
+ unitTarget->GetDispellableAuraList(m_caster, dispelMask, dispelList, targetMissInfo == SPELL_MISS_REFLECT);
+ if (dispelList.empty())
return;
+ size_t remaining = dispelList.size();
+
// Ok if exist some buffs for dispel try dispel it
uint32 failCount = 0;
- DispelChargesList success_list;
- WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
+ DispelChargesList successList;
+ successList.reserve(damage);
+
+ WorldPacket dataFail(SMSG_DISPEL_FAILED, 8 + 8 + 4 + 4 + damage * 4);
// dispel N = damage buffs (or while exist buffs for dispel)
- for (int32 count = 0; count < damage && !dispel_list.empty();)
+ for (int32 count = 0; count < damage && remaining > 0;)
{
// Random select buff for dispel
- DispelChargesList::iterator itr = dispel_list.begin();
- std::advance(itr, urand(0, dispel_list.size() - 1));
+ auto itr = dispelList.begin();
+ std::advance(itr, urand(0, remaining - 1));
- int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
- // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
- if (!chance)
+ if (itr->RollDispel())
{
- dispel_list.erase(itr);
- continue;
+ auto successItr = std::find_if(successList.begin(), successList.end(), [&itr](DispelableAura& dispelAura) -> bool
+ {
+ if (dispelAura.GetAura()->GetId() == itr->GetAura()->GetId())
+ return true;
+
+ return false;
+ });
+
+ if (successItr == successList.end())
+ successList.emplace_back(itr->GetAura(), 0, 1);
+ else
+ successItr->IncrementCharges();
+
+ if (!itr->DecrementCharge())
+ {
+ --remaining;
+ std::swap(*itr, dispelList[remaining]);
+ }
}
else
{
- if (roll_chance_i(chance))
+ if (!failCount)
{
- bool alreadyListed = false;
- for (DispelChargesList::iterator successItr = success_list.begin(); successItr != success_list.end(); ++successItr)
- {
- if (successItr->first->GetId() == itr->first->GetId())
- {
- ++successItr->second;
- alreadyListed = true;
- }
- }
- if (!alreadyListed)
- success_list.push_back(std::make_pair(itr->first, 1));
- --itr->second;
- if (itr->second <= 0)
- dispel_list.erase(itr);
+ // Failed to dispell
+ dataFail << uint64(m_caster->GetGUID()); // Caster GUID
+ dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
+ dataFail << uint32(m_spellInfo->Id); // dispel spell id
}
- else
- {
- if (!failCount)
- {
- // Failed to dispell
- dataFail << uint64(m_caster->GetGUID()); // Caster GUID
- dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
- dataFail << uint32(m_spellInfo->Id); // dispel spell id
- }
- ++failCount;
- dataFail << uint32(itr->first->GetId()); // Spell Id
- }
- ++count;
+ ++failCount;
+ dataFail << uint32(itr->GetAura()->GetId()); // Spell Id
}
+ ++count;
}
if (failCount)
m_caster->SendMessageToSet(&dataFail, true);
- if (success_list.empty())
+ if (successList.empty())
return;
- WorldPacket dataSuccess(SMSG_SPELLDISPELLOG, 8+8+4+1+4+success_list.size()*5);
+ WorldPacket dataSuccess(SMSG_SPELLDISPELLOG, 8 + 8 + 4 + 1 + 4 + successList.size() * 5);
// Send packet header
dataSuccess << unitTarget->GetPackGUID(); // Victim GUID
dataSuccess << m_caster->GetPackGUID(); // Caster GUID
dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
dataSuccess << uint8(0); // not used
- dataSuccess << uint32(success_list.size()); // count
- for (DispelChargesList::iterator itr = success_list.begin(); itr != success_list.end(); ++itr)
+ dataSuccess << uint32(successList.size()); // count
+ for (DispelChargesList::iterator itr = successList.begin(); itr != successList.end(); ++itr)
{
// Send dispelled spell info
- dataSuccess << uint32(itr->first->GetId()); // Spell Id
- dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed
- unitTarget->RemoveAurasDueToSpellByDispel(itr->first->GetId(), m_spellInfo->Id, itr->first->GetCasterGUID(), m_caster, itr->second);
+ dataSuccess << uint32(itr->GetAura()->GetId()); // Spell Id
+ dataSuccess << uint8(0); // 0 - dispelled !=0 cleansed
+ unitTarget->RemoveAurasDueToSpellByDispel(itr->GetAura()->GetId(), m_spellInfo->Id, itr->GetAura()->GetCasterGUID(), m_caster, itr->GetDispelCharges());
}
m_caster->SendMessageToSet(&dataSuccess, true);
@@ -4866,14 +4864,11 @@ void Spell::EffectDispelMechanic(SpellEffIndex effIndex)
continue;
if (roll_chance_i(aura->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster))))
if ((aura->GetSpellInfo()->GetAllEffectsMechanicMask() & (1 << mechanic)))
- dispel_list.push_back(std::make_pair(aura->GetId(), aura->GetCasterGUID()));
+ dispel_list.emplace_back(aura->GetId(), aura->GetCasterGUID());
}
- while (!dispel_list.empty())
- {
- unitTarget->RemoveAura(dispel_list.front().first, dispel_list.front().second, 0, AURA_REMOVE_BY_ENEMY_SPELL);
- dispel_list.pop_front();
- }
+ for (auto itr = dispel_list.begin(); itr != dispel_list.end(); ++itr)
+ unitTarget->RemoveAura(itr->first, itr->second, 0, AURA_REMOVE_BY_ENEMY_SPELL);
}
void Spell::EffectResurrectPet(SpellEffIndex /*effIndex*/)
@@ -5259,7 +5254,7 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
if (!unitTarget || unitTarget == m_caster) // can't steal from self
return;
- DispelChargesList steal_list;
+ DispelChargesList stealList;
// Create dispel mask by dispel type
uint32 dispelMask = SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[effIndex].MiscValue));
@@ -5267,7 +5262,7 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
for (Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
Aura* aura = itr->second;
- AuraApplication * aurApp = aura->GetApplicationOfTarget(unitTarget->GetGUID());
+ AuraApplication const* aurApp = aura->GetApplicationOfTarget(unitTarget->GetGUID());
if (!aurApp)
continue;
@@ -5277,75 +5272,76 @@ void Spell::EffectStealBeneficialBuff(SpellEffIndex effIndex)
if (!aurApp->IsPositive() || aura->IsPassive() || aura->GetSpellInfo()->HasAttribute(SPELL_ATTR4_NOT_STEALABLE))
continue;
+ // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
+ int32 chance = aura->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
+ if (!chance)
+ 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 dispelCharges = aura->GetSpellInfo()->HasAttribute(SPELL_ATTR7_DISPEL_CHARGES);
uint8 charges = dispelCharges ? aura->GetCharges() : aura->GetStackAmount();
if (charges > 0)
- steal_list.push_back(std::make_pair(aura, charges));
+ stealList.emplace_back(aura, chance, charges);
}
}
- if (steal_list.empty())
+ if (stealList.empty())
return;
+ size_t remaining = stealList.size();
+
// Ok if exist some buffs for dispel try dispel it
uint32 failCount = 0;
- DispelList success_list;
- WorldPacket dataFail(SMSG_DISPEL_FAILED, 8+8+4+4+damage*4);
+ DispelList successList;
+ successList.reserve(damage);
+
+ WorldPacket dataFail(SMSG_DISPEL_FAILED, 8 + 8 + 4 + 4 + damage * 4);
// dispel N = damage buffs (or while exist buffs for dispel)
- for (int32 count = 0; count < damage && !steal_list.empty();)
+ for (int32 count = 0; count < damage && remaining > 0;)
{
// Random select buff for dispel
- DispelChargesList::iterator itr = steal_list.begin();
- std::advance(itr, urand(0, steal_list.size() - 1));
+ DispelChargesList::iterator itr = stealList.begin();
+ std::advance(itr, urand(0, remaining - 1));
- int32 chance = itr->first->CalcDispelChance(unitTarget, !unitTarget->IsFriendlyTo(m_caster));
- // 2.4.3 Patch Notes: "Dispel effects will no longer attempt to remove effects that have 100% dispel resistance."
- if (!chance)
+ if (itr->RollDispel())
{
- steal_list.erase(itr);
- continue;
+ successList.emplace_back(itr->GetAura()->GetId(), itr->GetAura()->GetCasterGUID());
+ if (!itr->DecrementCharge())
+ {
+ --remaining;
+ std::swap(*itr, stealList[remaining]);
+ }
}
else
{
- if (roll_chance_i(chance))
- {
- success_list.push_back(std::make_pair(itr->first->GetId(), itr->first->GetCasterGUID()));
- --itr->second;
- if (itr->second <= 0)
- steal_list.erase(itr);
- }
- else
+ if (!failCount)
{
- if (!failCount)
- {
- // Failed to dispell
- dataFail << uint64(m_caster->GetGUID()); // Caster GUID
- dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
- dataFail << uint32(m_spellInfo->Id); // dispel spell id
- }
- ++failCount;
- dataFail << uint32(itr->first->GetId()); // Spell Id
+ // Failed to dispell
+ dataFail << uint64(m_caster->GetGUID()); // Caster GUID
+ dataFail << uint64(unitTarget->GetGUID()); // Victim GUID
+ dataFail << uint32(m_spellInfo->Id); // dispel spell id
}
- ++count;
+ ++failCount;
+ dataFail << uint32(itr->GetAura()->GetId()); // Spell Id
}
+ ++count;
}
if (failCount)
m_caster->SendMessageToSet(&dataFail, true);
- if (success_list.empty())
+ if (successList.empty())
return;
- WorldPacket dataSuccess(SMSG_SPELLSTEALLOG, 8+8+4+1+4+damage*5);
- dataSuccess << unitTarget->GetPackGUID(); // Victim GUID
- dataSuccess << m_caster->GetPackGUID(); // Caster GUID
- dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
- dataSuccess << uint8(0); // not used
- dataSuccess << uint32(success_list.size()); // count
- for (DispelList::iterator itr = success_list.begin(); itr!=success_list.end(); ++itr)
+ WorldPacket dataSuccess(SMSG_SPELLSTEALLOG, 8 + 8 + 4 + 1 + 4 + damage * 5);
+ dataSuccess << unitTarget->GetPackGUID(); // Victim GUID
+ dataSuccess << m_caster->GetPackGUID(); // Caster GUID
+ dataSuccess << uint32(m_spellInfo->Id); // dispel spell id
+ dataSuccess << uint8(0); // not used
+ dataSuccess << uint32(successList.size()); // count
+ for (auto itr = successList.begin(); itr != successList.end(); ++itr)
{
dataSuccess << uint32(itr->first); // Spell Id
dataSuccess << uint8(0); // 0 - steals !=0 transfers