*Update dispel code and fix crash related to it. Thanks to megamage.

--HG--
branch : trunk
This commit is contained in:
QAston
2009-03-23 01:54:50 +01:00
parent b5eed3626d
commit ce71c0e798
7 changed files with 120 additions and 123 deletions
-15
View File
@@ -5245,21 +5245,6 @@ void Aura::HandleShapeshiftBoosts(bool apply)
m_target->SetHealth(uint32(ceil((double)m_target->GetMaxHealth() * healthPercentage)));*/ 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) void Aura::HandleAuraEmpathy(bool apply, bool Real)
{ {
if(m_target->GetTypeId() != TYPEID_UNIT) if(m_target->GetTypeId() != TYPEID_UNIT)
-2
View File
@@ -318,8 +318,6 @@ class TRINITY_DLL_SPEC Aura
void HandleAuraAllowOnlyAbility(bool apply, bool Real); void HandleAuraAllowOnlyAbility(bool apply, bool Real);
void HandleShapeshiftBoosts(bool apply); void HandleShapeshiftBoosts(bool apply);
bool GetDispelChance(Spell* spell);
// Allow Apply Aura Handler to modify and access m_AuraDRGroup // Allow Apply Aura Handler to modify and access m_AuraDRGroup
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; } DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; }
+34 -35
View File
@@ -3464,8 +3464,9 @@ void Spell::EffectDispel(uint32 i)
if(!unitTarget) if(!unitTarget)
return; return;
// Fill possible dispel list //std::vector <DispelEntry> dispel_list;
std::vector <Aura *> dispel_list; DispelSet dispel_list;
DispelEntry entry;
// Create dispel mask by dispel type // Create dispel mask by dispel type
uint32 dispel_type = m_spellInfo->EffectMiscValue[i]; uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
@@ -3489,43 +3490,36 @@ void Spell::EffectDispel(uint32 i)
if(positive == unitTarget->IsFriendlyTo(m_caster)) if(positive == unitTarget->IsFriendlyTo(m_caster))
continue; continue;
} }
// Add every aura stack to dispel list entry.casterGuid = itr->second->GetCasterGUID();
for(uint32 stack_amount = 0; stack_amount < aur->GetStackAmount(); ++stack_amount) entry.spellId = itr->second->GetId();
dispel_list.push_back(aur); entry.caster = itr->second->GetCaster();
entry.stackAmount = itr->second->GetStackAmount();
dispel_list.insert (entry);
} }
} }
// Ok if exist some buffs for dispel try dispel it // 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 < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
std::list < uint32 > fail_list; // spell_id std::list < uint32 > fail_list; // spell_id
int32 list_size = dispel_list.size();
// dispel N = damage buffs (or while exist buffs for dispel) // dispel N = damage buffs (or while exist buffs for dispel)
for (int32 count=0; count < damage && list_size > 0; ++count) for (int32 count=0; count < damage && list_size > 0; ++count)
{ {
// Random select buff for dispel // 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(); if (GetDispelChance(this, itr->caster, itr->spellId))
// 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(); )
{ {
Aura *dispelled = *j; entry.stackAmount-=1;
if (dispelled->GetId() == aur->GetId() && dispelled->GetCasterGUID() == aur->GetCasterGUID()) if (!itr->stackAmount)
{ dispel_list.erase(itr);
j = dispel_list.erase(j); success_list.push_back(std::pair<uint32,uint64>(itr->spellId,itr->casterGuid));
--list_size;
break;
}
else
++j;
} }
else
fail_list.push_back(itr->spellId);
} }
// Send success log and really remove auras // Send success log and really remove auras
if (!success_list.empty()) if (!success_list.empty())
@@ -6024,21 +6018,26 @@ void Spell::EffectDispelMechanic(uint32 i)
uint32 mechanic = m_spellInfo->EffectMiscValue[i]; uint32 mechanic = m_spellInfo->EffectMiscValue[i];
std::deque <Aura *> dispel_list; DispelSet dispel_list;
DispelEntry entry;
Unit::AuraMap& Auras = unitTarget->GetAuras(); 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(); SpellEntry const *spell = iter->second->GetSpellProto();
if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic) if(GetSpellMechanicMask(spell, iter->second->GetEffIndex()) & (1<<(mechanic-1)))
dispel_list.push_back(iter->second); {
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()); entry = *itr;
dispel_list.pop_front(); if (GetDispelChance(this, entry.caster, entry.spellId))
unitTarget->RemoveAurasByCasterSpell(entry.spellId, entry.casterGuid);
} }
} }
+15
View File
@@ -236,6 +236,21 @@ int32 GetSpellMaxDuration(SpellEntry const *spellInfo)
return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]); 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) uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell)
{ {
SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex); SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex);
+16
View File
@@ -152,6 +152,7 @@ SpellSpecific GetSpellSpecific(uint32 spellId);
inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); } inline float GetSpellRadiusForHostile(SpellRadiusEntry const *radius) { return (radius ? radius->radiusHostile : 0); }
inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); } inline float GetSpellRadiusForFriend(SpellRadiusEntry const *radius) { return (radius ? radius->radiusFriend : 0); }
uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell = NULL); 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 GetSpellMinRangeForHostile(SpellRangeEntry const *range) { return (range ? range->minRangeHostile : 0); }
inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); } inline float GetSpellMaxRangeForHostile(SpellRangeEntry const *range) { return (range ? range->maxRangeHostile : 0); }
inline float GetSpellMinRangeForFriend(SpellRangeEntry const *range) { return (range ? range->minRangeFriend : 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 GetSpellDuration(SpellEntry const *spellInfo);
int32 GetSpellMaxDuration(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) inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
{ {
for(int i= 0; i < 3; ++i) for(int i= 0; i < 3; ++i)
+10 -26
View File
@@ -505,37 +505,22 @@ void Unit::RemoveAuraTypeByCaster(AuraType auraType, uint64 casterGUID)
void Unit::RemoveSpellsCausingAuraWithDispel(AuraType auraType, Spell * spell) void Unit::RemoveSpellsCausingAuraWithDispel(AuraType auraType, Spell * spell)
{ {
if (auraType >= TOTAL_AURAS) return; if (auraType >= TOTAL_AURAS) return;
DispelEntry entry;
DispelSet dispel_list;
AuraList::iterator iter, next; AuraList::iterator iter, next;
for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next) for (iter = m_modAuras[auraType].begin(); iter != m_modAuras[auraType].end(); iter = next)
{ {
next = iter; entry.casterGuid = (*iter)->GetCasterGUID();
++next; entry.spellId = (*iter)->GetId();
entry.caster = (*iter)->GetCaster();
if (*iter) dispel_list.insert (entry);
{
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; for(DispelSet::iterator itr = dispel_list.begin(); itr != dispel_list.end();++itr)
AuraList const& dispelAuras = GetAurasByType(auraType);
for(AuraList::const_iterator itr = dispelAuras.begin(); itr != dispelAuras.end(); ++itr)
{ {
if (!(*iter)->GetDispelChance( spell)) entry = *itr;
continue; if (GetDispelChance(spell, entry.caster, entry.spellId))
dispel_list.push_back(*iter); RemoveAurasByCasterSpell(entry.spellId, entry.casterGuid);
}
for(;!dispel_list.empty();)
{
RemoveAurasDueToSpell(dispel_list.front()->GetId());
dispel_list.pop_front();
} }
} }
@@ -4341,7 +4326,6 @@ void Unit::RemoveNotOwnSingleTargetAuras()
else else
++iter; ++iter;
} }
} }
void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode) void Unit::RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode)