diff options
author | QAston <none@none> | 2009-03-23 01:54:50 +0100 |
---|---|---|
committer | QAston <none@none> | 2009-03-23 01:54:50 +0100 |
commit | ce71c0e798ed3f47dd6356c34766e16d951a8ca5 (patch) | |
tree | e97b28ddaf1d66f8aba22c1143a580ca6f8e4f55 /src | |
parent | b5eed3626ddc9dbc14dece208782c9a698bab7ae (diff) |
*Update dispel code and fix crash related to it. Thanks to megamage.
--HG--
branch : trunk
Diffstat (limited to 'src')
-rw-r--r-- | src/game/SpellAuras.cpp | 15 | ||||
-rw-r--r-- | src/game/SpellAuras.h | 2 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 69 | ||||
-rw-r--r-- | src/game/SpellMgr.cpp | 15 | ||||
-rw-r--r-- | src/game/SpellMgr.h | 16 | ||||
-rw-r--r-- | src/game/Unit.cpp | 38 |
6 files changed, 76 insertions, 79 deletions
diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index 9313b7e6fd4..4f7ba18beb4 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -5245,21 +5245,6 @@ void Aura::HandleShapeshiftBoosts(bool apply) m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ } -bool Aura::GetDispelChance(Spell* spell) -{ - // we assume that aura dispel chance is 100% on start - // need formula for level difference based chance - int32 miss_chance = 100; - // Apply dispel mod from aura caster - if (Unit *caster = GetCaster()) - { - if ( Player* modOwner = caster->GetSpellModOwner() ) - modOwner->ApplySpellMod(GetId(), SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, spell); - } - // Try dispel - return roll_chance_i(miss_chance); -} - void Aura::HandleAuraEmpathy(bool apply, bool Real) { if(m_target->GetTypeId() != TYPEID_UNIT) diff --git a/src/game/SpellAuras.h b/src/game/SpellAuras.h index 7266f30f713..48611018f94 100644 --- a/src/game/SpellAuras.h +++ b/src/game/SpellAuras.h @@ -318,8 +318,6 @@ class TRINITY_DLL_SPEC Aura void HandleAuraAllowOnlyAbility(bool apply, bool Real); void HandleShapeshiftBoosts(bool apply); - bool GetDispelChance(Spell* spell); - // Allow Apply Aura Handler to modify and access m_AuraDRGroup void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 66cc9f56d3e..9c1e6c36daf 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -3464,8 +3464,9 @@ void Spell::EffectDispel(uint32 i) if(!unitTarget) return; - // Fill possible dispel list - std::vector <Aura *> dispel_list; + //std::vector <DispelEntry> dispel_list; + DispelSet dispel_list; + DispelEntry entry; // Create dispel mask by dispel type uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; @@ -3489,43 +3490,36 @@ void Spell::EffectDispel(uint32 i) if(positive == unitTarget->IsFriendlyTo(m_caster)) continue; } - // Add every aura stack to dispel list - for(uint32 stack_amount = 0; stack_amount < aur->GetStackAmount(); ++stack_amount) - dispel_list.push_back(aur); + entry.casterGuid = itr->second->GetCasterGUID(); + entry.spellId = itr->second->GetId(); + entry.caster = itr->second->GetCaster(); + entry.stackAmount = itr->second->GetStackAmount(); + dispel_list.insert (entry); } } // Ok if exist some buffs for dispel try dispel it - if (!dispel_list.empty()) + if (uint32 list_size = dispel_list.size()) { std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid) std::list < uint32 > fail_list; // spell_id - int32 list_size = dispel_list.size(); + // dispel N = damage buffs (or while exist buffs for dispel) for (int32 count=0; count < damage && list_size > 0; ++count) { // Random select buff for dispel - Aura *aur = dispel_list[urand(0, list_size-1)]; + DispelSet::iterator itr=dispel_list.begin(); + for (uint32 i=urand(0, list_size-1);i!=0;--i) + itr++; - SpellEntry const* spellInfo = aur->GetSpellProto(); - // Base dispel chance - // TODO: possible chance depend from spell level?? - if (aur->GetDispelChance(this)) - success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID())); - else - fail_list.push_back(aur->GetId()); - // Remove buff from list for prevent doubles - for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); ) + if (GetDispelChance(this, itr->caster, itr->spellId)) { - Aura *dispelled = *j; - if (dispelled->GetId() == aur->GetId() && dispelled->GetCasterGUID() == aur->GetCasterGUID()) - { - j = dispel_list.erase(j); - --list_size; - break; - } - else - ++j; + entry.stackAmount-=1; + if (!itr->stackAmount) + dispel_list.erase(itr); + success_list.push_back(std::pair<uint32,uint64>(itr->spellId,itr->casterGuid)); } + else + fail_list.push_back(itr->spellId); } // Send success log and really remove auras if (!success_list.empty()) @@ -6024,21 +6018,26 @@ void Spell::EffectDispelMechanic(uint32 i) uint32 mechanic = m_spellInfo->EffectMiscValue[i]; - std::deque <Aura *> dispel_list; + DispelSet dispel_list; + DispelEntry entry; Unit::AuraMap& Auras = unitTarget->GetAuras(); - for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter++) + for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); iter++) { - if (!iter->second->GetDispelChance(this)) - continue; SpellEntry const *spell = iter->second->GetSpellProto(); - if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) - dispel_list.push_back(iter->second); + if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & (1<<(mechanic-1))) + { + entry.casterGuid = iter->second->GetCasterGUID(); + entry.spellId = iter->second->GetId(); + entry.caster = iter->second->GetCaster(); + dispel_list.insert (entry); + } } - for(;!dispel_list.empty();) + for(DispelSet::iterator itr = dispel_list.begin(); itr != dispel_list.end();++itr) { - unitTarget->RemoveAurasDueToSpell(dispel_list.front()->GetId()); - dispel_list.pop_front(); + entry = *itr; + if (GetDispelChance(this, entry.caster, entry.spellId)) + unitTarget->RemoveAurasByCasterSpell(entry.spellId, entry.casterGuid); } } diff --git a/src/game/SpellMgr.cpp b/src/game/SpellMgr.cpp index e42e5dc4488..c9f804bdc18 100644 --- a/src/game/SpellMgr.cpp +++ b/src/game/SpellMgr.cpp @@ -236,6 +236,21 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo) return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); } +bool GetDispelChance(Spell* spell, Unit* caster, uint32 spellId) +{ + // we assume that aura dispel chance is 100% on start + // need formula for level difference based chance + int32 miss_chance = 100; + // Apply dispel mod from aura caster + if (caster) + { + if ( Player* modOwner = caster->GetSpellModOwner() ) + modOwner->ApplySpellMod(spellId, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, spell); + } + // Try dispel + return roll_chance_i(miss_chance); +} + uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell) { SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex); diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index e55ff3c89d2..190059f81c4 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -152,6 +152,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId); inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); } uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); +bool GetDispelChance(Spell* spell, Unit* caster, uint32 spellId); inline float GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); } inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); } inline float GetSpellMinRangeForFriend(SpellRangeEntry const *range) { return (range ? range->minRangeFriend : 0); } @@ -161,6 +162,21 @@ inline uint32 GetSpellRecoveryTime(SpellEntry const *spellInfo) { return spellIn int32 GetSpellDuration(SpellEntry const *spellInfo); int32 GetSpellMaxDuration(SpellEntry const *spellInfo); +struct DispelEntry +{ + uint64 casterGuid; + uint32 spellId; + Unit * caster; + uint8 stackAmount; + + bool operator < (const DispelEntry & _Right) const + { + return (spellId != _Right.spellId ? spellId < _Right.spellId : casterGuid < _Right.casterGuid); + } +}; + +typedef std::set < DispelEntry > DispelSet; + inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect) { for(int i= 0; i < 3; ++i) diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 720bcc55a0d..4fdb5b06d94 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -505,37 +505,22 @@ void Unit::RemoveAuraTypeByCaster(AuraType auraType, uint64 casterGUID) void Unit::RemoveSpellsCausingAuraWithDispel(AuraType auraType, Spell * spell) { if (auraType >= TOTAL_AURAS) return; + DispelEntry entry; + DispelSet dispel_list; AuraList::iterator iter, next; for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next) { - next = iter; - ++next; - - if (*iter) - { - if (!(*iter)->GetDispelChance( spell)) - continue; - RemoveAurasDueToSpell((*iter)->GetId()); - if (!m_modAuras[auraType].empty()) - next = m_modAuras[auraType].begin(); - else - return; - } - } - - std::deque <Aura *> dispel_list; - - AuraList const& dispelAuras = GetAurasByType(auraType); - for(AuraList::const_iterator itr = dispelAuras.begin(); itr != dispelAuras.end(); ++itr) - { - if (!(*iter)->GetDispelChance( spell)) - continue; - dispel_list.push_back(*iter); + entry.casterGuid = (*iter)->GetCasterGUID(); + entry.spellId = (*iter)->GetId(); + entry.caster = (*iter)->GetCaster(); + dispel_list.insert (entry); } - for(;!dispel_list.empty();) + + for(DispelSet::iterator itr = dispel_list.begin(); itr != dispel_list.end();++itr) { - RemoveAurasDueToSpell(dispel_list.front()->GetId()); - dispel_list.pop_front(); + entry = *itr; + if (GetDispelChance(spell, entry.caster, entry.spellId)) + RemoveAurasByCasterSpell(entry.spellId, entry.casterGuid); } } @@ -4341,7 +4326,6 @@ void Unit::RemoveNotOwnSingleTargetAuras() else ++iter; } - } void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) |