Jump to content

[patch][6279] Fix Group Area Aura And Add Two New Area Aura


Auntie Mangos

Recommended Posts

  • 38 years later...

This patch add two new area aura: effect 128 friend aura which affects all nearby friendly units and effect 129 enemy aura which affects all nearby enemy.

It also fixes some bugs of the old area aura: effect 35 group aura. Target's aura now can be correctly removed when caster removes his aura or target changes or leaves the group. Pets will also recieve the auras.

Patch has been tested and works fine.

Index: SpellAuraDefines.h
===================================================================
--- SpellAuraDefines.h        (revision 6256)
+++ SpellAuraDefines.h        (working copy)
@@ -291,4 +291,11 @@
        SPELL_AURA_MOD_ENEMY_DODGE = 251,
        TOTAL_AURAS=252
};
+
+enum AreaAuraType
+{
+        AREA_AURA_GROUP         = 0,
+        AREA_AURA_FRIEND        = 1,
+        AREA_AURA_ENEMY         = 2
+};
#endif
Index: SpellAuras.cpp
===================================================================
--- SpellAuras.cpp        (revision 6256)
+++ SpellAuras.cpp        (working copy)
@@ -42,6 +42,9 @@
#include "BattleGround.h"
#include "CreatureAI.h"
#include "Util.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+#include "CellImpl.h"

#define NULL_AURA_SLOT 0xFF

@@ -399,7 +402,7 @@
}

AreaAura::AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target,
-Unit *caster, Item* castItem) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
+Unit *caster, Item* castItem, AreaAuraType type) : Aura(spellproto, eff, currentBasePoints, target, caster, castItem)
{
        m_isAreaAura = true;

@@ -409,6 +412,10 @@
        m_radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(GetSpellProto()->EffectRadiusIndex[m_effIndex]));
        if(Player* modOwner = caster_ptr->GetSpellModOwner())
                modOwner->ApplySpellMod(GetId(), SPELLMOD_RADIUS, m_radius);
+
+        m_auraType = type;
+        if(m_auraType == AREA_AURA_ENEMY && target == caster)
+                m_modifier.m_auraname = SPELL_AURA_DUMMY; // Do not do any effect on self
}

AreaAura::~AreaAura()
@@ -556,93 +563,101 @@
        if(m_caster_guid == m_target->GetGUID())
        {
                Unit* caster = m_target;
+                Unit* owner = caster->GetCharmerOrOwner() ? caster->GetCharmerOrOwner() : caster;
+                std::list<Unit *> targets;

-                Group *pGroup = NULL;
-                if (caster->GetTypeId() == TYPEID_PLAYER)
-                        pGroup = ((Player*)caster)->GetGroup();
-                else if(caster->GetCharmerOrOwnerGUID() != 0)
+                if (m_auraType == AREA_AURA_GROUP)
                {
-                        Unit *owner = caster->GetCharmerOrOwner();
-                        if (owner && owner->GetTypeId() == TYPEID_PLAYER)
+                        Group *pGroup = NULL;
+                        if(owner->GetTypeId() == TYPEID_PLAYER)
                                pGroup = ((Player*)owner)->GetGroup();
-                }

-                if(pGroup)
-                {
-                        for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
+                        if(pGroup)
                        {
-                                Player* Target = itr->getSource();
-                                if(!Target)
-                                        continue;
+                                for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
+                                {
+                                        Player* Target = itr->getSource();

-                                if (caster->GetTypeId() == TYPEID_PLAYER)
-                                {
-                                        if(Target->GetGUID() == m_caster_guid || !Target->isAlive() || !pGroup->SameSubGroup((Player*)caster, Target))
-                                                continue;
+                                        if(Target && Target->isAlive() && pGroup->SameSubGroup((Player*)owner, Target))
+                                        {
+                                                if(caster->IsWithinDistInMap(Target, m_radius) && !Target->GetAura(GetId(), m_effIndex))
+                                                        targets.push_back(Target);
+                                                Pet *pet = Target->GetPet();
+                                                if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius) && !pet->GetAura(GetId(), m_effIndex))
+                                                        targets.push_back(pet);
+                                        }
                                }
-                                else if(caster->GetCharmerOrOwnerGUID() != 0)
-                                {
-                                        Unit *owner = caster->GetCharmerOrOwner();
-                                        if(!Target->isAlive() || (owner->GetTypeId() == TYPEID_PLAYER && !pGroup->SameSubGroup((Player*)owner, Target)))
-                                                continue;
-                                }
+                        }
+                        else
+                        {
+                                if(owner != caster && caster->IsWithinDistInMap(owner, m_radius) && !owner->GetAura(GetId(), m_effIndex))
+                                        targets.push_back(owner);
+                                Pet *pet = owner->GetPet(); // Maybe shamans have both totem and pet (fire element totem)?
+                                if(pet && pet->isAlive() && caster->IsWithinDistInMap(pet, m_radius) && !pet->GetAura(GetId(), m_effIndex))
+                                        targets.push_back(pet);
+                        }
+                }
+                else if (m_auraType == AREA_AURA_ENEMY)
+                {
+                        CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
+                        Cell cell(p);
+                        cell.data.Part.reserved = ALL_DISTRICT;
+                        cell.SetNoCreate();

-                                Aura *t_aura = Target->GetAura(GetId(), m_effIndex);
+                        {
+                                MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher
+                                MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(targets, u_check);

-                                if(caster->IsWithinDistInMap(Target, m_radius) )
-                                {
-                                        // apply aura to players in range that dont have it yet
-                                        if (!t_aura)
-                                        {
-                                                // if rank not found
-                                                if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(),Target->getLevel()))
-                                                {
-                                                        int32 actualBasePoints = m_currentBasePoints;
+                                TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+                                TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer >    grid_unit_searcher(searcher);

-                                                        // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
-                                                        if(actualSpellInfo != GetSpellProto())
-                                                                actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
+                                CellLock<GridReadGuard> cell_lock(cell, p);
+                                cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+                                cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+                        }
+                }
+                else // Unfortunately we do not have an approciate searcher, have to use AnyUnitInObjectRangeCheck
+                {
+                        CellPair p(MaNGOS::ComputeCellPair(caster->GetPositionX(), caster->GetPositionY()));
+                        Cell cell(p);
+                        cell.data.Part.reserved = ALL_DISTRICT;
+                        cell.SetNoCreate();

-                                                        AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, Target, caster);
-                                                        Target->AddAura(aur);
-                                                }
-                                        }
-                                }
-                                else
-                                {
-                                        // remove auras of the same caster from out of range players
-                                        if (t_aura)
-                                                if (t_aura->GetCasterGUID() == m_caster_guid)
-                                                        Target->RemoveAura(GetId(), m_effIndex);
-                                }
+                        {
+                                MaNGOS::AnyUnitInObjectRangeCheck u_check(caster, m_radius);
+                                MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck> searcher(targets, u_check);
+
+                                TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
+                                TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyUnitInObjectRangeCheck>, GridTypeMapContainer >    grid_unit_searcher(searcher);
+
+                                CellLock<GridReadGuard> cell_lock(cell, p);
+                                cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
+                                cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(caster->GetMapId(), caster));
                        }
                }
-                else if (caster->GetCharmerOrOwnerGUID() != 0)
+
+                for(std::list<Unit *>::iterator tIter = targets.begin(); tIter != targets.end(); tIter++)
                {
-                        // add / remove auras from the totem's owner
-                        Unit *owner = caster->GetCharmerOrOwner();
-                        if (owner)
+                        // Additional check for AREA_AURA_FRIEND, maybe we should add a AnyFriendlyUnitInObjectRangeCheck function
+                        if(m_auraType == AREA_AURA_FRIEND && !owner->IsFriendlyTo(*tIter)
+                                || m_auraType != AREA_AURA_GROUP && (*tIter)->GetAura(GetId(), m_effIndex)) // group aura has finished this check
+                                continue;
+
+                        if(SpellEntry const *actualSpellInfo = spellmgr.SelectAuraRankForPlayerLevel(GetSpellProto(), (*tIter)->getLevel()))
                        {
-                                Aura *o_aura = owner->GetAura(GetId(), m_effIndex);
-                                if(caster->IsWithinDistInMap(owner, m_radius))
-                                {
-                                        if (!o_aura)
-                                        {
-                                                AreaAura *aur = new AreaAura(GetSpellProto(), m_effIndex, &m_currentBasePoints, owner, caster);
-                                                owner->AddAura(aur);
-                                        }
-                                }
-                                else
-                                {
-                                        if (o_aura)
-                                                if (o_aura->GetCasterGUID() == m_caster_guid)
-                                                        owner->RemoveAura(GetId(), m_effIndex);
-                                }
+                                int32 actualBasePoints = m_currentBasePoints;
+
+                                // recalculate basepoints for lower rank (all AreaAura spell not use custom basepoints?)
+                                if(actualSpellInfo != GetSpellProto())
+                                        actualBasePoints = actualSpellInfo->EffectBasePoints[m_effIndex];
+                                AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, (*tIter), caster, NULL, m_auraType);
+                                (*tIter)->AddAura(aur);
                        }
                }
+
+                Aura::Update(diff); // Update for caster
        }
-
-        if(m_caster_guid != m_target->GetGUID())                                // aura at non-caster
+        else // aura at non-caster
        {
                Unit * tmp_target = m_target;
                Unit* caster = GetCaster();
@@ -652,11 +667,37 @@
                // DO NOT access its members after update!
                Aura::Update(diff);

-                // remove aura if out-of-range from caster (after teleport for example)
-                if(!caster || !caster->IsWithinDistInMap(tmp_target, m_radius) )
+                // remove aura if out-of-range from caster or caster no longer has the aura
+                if(!caster || !caster->IsWithinDistInMap(tmp_target, m_radius) || !caster->GetAura(tmp_spellId, tmp_effIndex))
                        tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+                // remove aura if type is group aura and no longer in the same group with caster
+                else if(m_auraType == AREA_AURA_GROUP)
+                {
+                        Group *pGroup = NULL;
+                        Unit* owner = caster->GetCharmerOrOwner() ? caster->GetCharmerOrOwner() : caster;
+                        if(owner->GetTypeId() == TYPEID_PLAYER)
+                                pGroup = ((Player*)owner)->GetGroup();
+
+                        if(pGroup)
+                        {
+                                if(tmp_target->GetTypeId() == TYPEID_PLAYER)
+                                {
+                                        if(!pGroup->SameSubGroup((Player*)owner, (Player*)tmp_target))
+                                                tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+                                }
+                                else // For pet
+                                {
+                                        Unit* target_owner = tmp_target->GetCharmerOrOwner();
+                                        if(!target_owner || target_owner->GetTypeId() != TYPEID_PLAYER || !pGroup->SameSubGroup((Player*)owner, (Player*)target_owner))
+                                                tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+                                }
+                        }
+                        else if(tmp_target != owner)
+                                tmp_target->RemoveAura(tmp_spellId, tmp_effIndex);
+                }
+
+                // remove aura if owner changes faction, can this happen?
        }
-        else Aura::Update(diff);
}

void PersistentAreaAura::Update(uint32 diff)
Index: SpellAuras.h
===================================================================
--- SpellAuras.h        (revision 6256)
+++ SpellAuras.h        (working copy)
@@ -346,11 +346,12 @@
class MANGOS_DLL_SPEC AreaAura : public Aura
{
        public:
-                AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
+                AreaAura(SpellEntry const* spellproto, uint32 eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL, AreaAuraType type = AREA_AURA_GROUP);
                ~AreaAura();
                void Update(uint32 diff);
        private:
                float m_radius;
+                AreaAuraType m_auraType; //0: group, 1: friend, 2: enemy
};

class MANGOS_DLL_SPEC PersistentAreaAura : public Aura
Index: SpellEffects.cpp
===================================================================
--- SpellEffects.cpp        (revision 6256)
+++ SpellEffects.cpp        (working copy)
@@ -179,7 +179,7 @@
        &Spell::EffectSkinPlayerCorpse,                                                 //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE             one spell: Remove Insignia, bg usage, required special corpse flags...
        &Spell::EffectSpiritHeal,                                                             //117 SPELL_EFFECT_SPIRIT_HEAL                            one spell: Spirit Heal
        &Spell::EffectSkill,                                                                        //118 SPELL_EFFECT_SKILL                                        professions and more
-        &Spell::EffectApplyPetAura,                                                         //119 SPELL_EFFECT_APPLY_AURA_NEW
+        &Spell::EffectApplyPetAura,                                                         //119 SPELL_EFFECT_APPLY_AURA_PET
        &Spell::EffectUnused,                                                                     //120 SPELL_EFFECT_TELEPORT_GRAVEYARD             one spell: Graveyard Teleport Test
        &Spell::EffectWeaponDmg,                                                                //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
        &Spell::EffectUnused,                                                                     //122 SPELL_EFFECT_122                                            unused
@@ -188,8 +188,8 @@
        &Spell::EffectReduceThreatPercent,                                            //125 SPELL_EFFECT_REDUCE_THREAT_PERCENT
        &Spell::EffectStealBeneficialBuff,                                            //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF        spell steal effect?
        &Spell::EffectProspecting,                                                            //127 SPELL_EFFECT_PROSPECTING                            Prospecting spell
-        &Spell::EffectApplyAura,                                                                //128 SPELL_EFFECT_APPLY_AURA_NEW2                    probably apply aura again
-        &Spell::EffectNULL,                                                                         //129 SPELL_EFFECT_APPLY_AURA_NEW3
+        &Spell::EffectApplyFriendAura,                                                    //128 SPELL_EFFECT_APPLY_AURA_FRIEND
+        &Spell::EffectApplyEnemyAura,                                                     //129 SPELL_EFFECT_APPLY_AURA_ENEMY
        &Spell::EffectNULL,                                                                         //130 SPELL_EFFECT_REDIRECT_THREAT
        &Spell::EffectUnused,                                                                     //131 SPELL_EFFECT_131                                            used in some test spells
        &Spell::EffectNULL,                                                                         //132 SPELL_EFFECT_PLAY_MUSIC                             sound id in misc value
@@ -5674,6 +5675,28 @@
        }
}

+void Spell::EffectApplyFriendAura(uint32 i)
+{
+        if(!unitTarget)
+                return;
+        if(!unitTarget->isAlive())
+                return;
+
+        AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, NULL, AREA_AURA_FRIEND);
+        unitTarget->AddAura(Aur);
+}
+
+void Spell::EffectApplyEnemyAura(uint32 i)
+{
+        if(!unitTarget)
+                return;
+        if(!unitTarget->isAlive())
+                return;
+
+        AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, NULL, AREA_AURA_ENEMY);
+        unitTarget->AddAura(Aur);
+}
+
void Spell::EffectSummonDemon(uint32 i)
{
        float px = m_targets.m_destX;

Link to comment
Share on other sites

SpellAuras.cpp(rev.6279):

...
   593            Group *pGroup;             /* need initialize !!! */
   594            if (owner->GetTypeId() == TYPEID_PLAYER)
   595                    pGroup = ((Player*)owner)->GetGroup();
   596            if( pGroup)
   597            {
   598                    uint8 subgroup = ((Player*)owner)->GetSubGroup();
   599                    for(GroupReference *itr = pGroup->GetFirstMember() ...
                                                                                ~~~~~~ crash !!!
...

Link to comment
Share on other sites

Guest
This topic is now closed to further replies.
×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. Privacy Policy Terms of Use