diff options
author | ariel- <ariel-@users.noreply.github.com> | 2016-10-11 22:01:42 -0300 |
---|---|---|
committer | ariel- <ariel-@users.noreply.github.com> | 2016-10-11 22:01:42 -0300 |
commit | 449ec0d6ff74ccd1874bc09073353d97c1d0151c (patch) | |
tree | 36f2bcf4155f035edd0909ea7780b3e79fd8ae81 /src | |
parent | 3cbd4bc22f013e8a4ab593c6f0afd2654fed6a66 (diff) |
Core/Auras: don't ignore SPELL_ATTR3_ONLY_TARGET_PLAYERS in area auras.
Also, start abusing the arbitrary containers for searchers introduced in 8775f8b28a5ad4403371577787131ff81f14332b
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Grids/Notifiers/GridNotifiers.h | 24 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 93 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 6 |
3 files changed, 64 insertions, 59 deletions
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h index 317378dfa8b..df4788a0a1e 100644 --- a/src/server/game/Grids/Notifiers/GridNotifiers.h +++ b/src/server/game/Grids/Notifiers/GridNotifiers.h @@ -877,10 +877,13 @@ namespace Trinity class AnyGroupedUnitInObjectRangeCheck { public: - AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid) : _source(obj), _refUnit(funit), _range(range), _raid(raid) { } + AnyGroupedUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool raid, bool playerOnly = false) : _source(obj), _refUnit(funit), _range(range), _raid(raid), _playerOnly(playerOnly) { } bool operator()(Unit* u) { - if (G3D::fuzzyEq(_range, 0)) + if (G3D::fuzzyEq(_range, 0.0f)) + return false; + + if (_playerOnly && u->GetTypeId() != TYPEID_PLAYER) return false; if (_raid) @@ -899,6 +902,7 @@ namespace Trinity Unit const* _refUnit; float _range; bool _raid; + bool _playerOnly; }; class AnyUnitInObjectRangeCheck @@ -945,16 +949,18 @@ namespace Trinity class AnyAoETargetUnitInObjectRangeCheck { public: - AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) - : i_obj(obj), i_funit(funit), _spellInfo(NULL), i_range(range) + AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, SpellInfo const* spellInfo = nullptr) + : i_obj(obj), i_funit(funit), _spellInfo(spellInfo), i_range(range) { Unit const* check = i_funit; Unit const* owner = i_funit->GetOwner(); if (owner) check = owner; i_targetForPlayer = (check->GetTypeId() == TYPEID_PLAYER); - if (DynamicObject const* dynObj = i_obj->ToDynObject()) - _spellInfo = sSpellMgr->GetSpellInfo(dynObj->GetSpellId()); + + if (!_spellInfo) + if (DynamicObject const* dynObj = i_obj->ToDynObject()) + _spellInfo = sSpellMgr->GetSpellInfo(dynObj->GetSpellId()); } bool operator()(Unit* u) { @@ -962,10 +968,10 @@ namespace Trinity if (u->GetTypeId() == TYPEID_UNIT && u->IsTotem()) return false; - if (i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : NULL) && i_obj->IsWithinDistInMap(u, i_range)) - return true; + if (_spellInfo && _spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS) && u->GetTypeId() != TYPEID_PLAYER) + return false; - return false; + return i_funit->_IsValidAttackTarget(u, _spellInfo, i_obj->GetTypeId() == TYPEID_DYNAMICOBJECT ? i_obj : nullptr) && i_obj->IsWithinDistInMap(u, i_range); } private: bool i_targetForPlayer; diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 2a6545520ae..a11f4e9b808 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -490,37 +490,36 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) m_updateTargetMapInterval = UPDATE_TARGET_MAP_INTERVAL; // fill up to date target list - // target, effMask - std::map<Unit*, uint8> targets; - + // target, effMask + std::unordered_map<Unit*, uint8> targets; FillTargetMap(targets, caster); - UnitList targetsToRemove; + std::deque<Unit*> targetsToRemove; // mark all auras as ready to remove for (ApplicationMap::iterator appIter = m_applications.begin(); appIter != m_applications.end();++appIter) { - std::map<Unit*, uint8>::iterator existing = targets.find(appIter->second->GetTarget()); + auto itr = targets.find(appIter->second->GetTarget()); // not found in current area - remove the aura - if (existing == targets.end()) + if (itr == targets.end()) targetsToRemove.push_back(appIter->second->GetTarget()); else { // needs readding - remove now, will be applied in next update cycle // (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed) - if (appIter->second->GetEffectMask() != existing->second || !CanBeAppliedOn(existing->first)) + if (appIter->second->GetEffectMask() != itr->second || !CanBeAppliedOn(itr->first)) targetsToRemove.push_back(appIter->second->GetTarget()); // nothing todo - aura already applied // remove from auras to register list - targets.erase(existing); + targets.erase(itr); } } // register auras for units - for (std::map<Unit*, uint8>::iterator itr = targets.begin(); itr!= targets.end();) + for (auto itr = targets.begin(); itr!= targets.end();) { // aura mustn't be already applied on target - if (AuraApplication * aurApp = GetApplicationOfTarget(itr->first->GetGUID())) + if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID())) { // the core created 2 different units with same guid // this is a major failue, which i can't fix right now @@ -530,7 +529,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) if (aurApp->GetTarget() != itr->first) { // remove from auras to register list - targets.erase(itr++); + itr = targets.erase(itr); continue; } else @@ -584,7 +583,7 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) } } if (!addUnit) - targets.erase(itr++); + itr = targets.erase(itr); else { // owner has to be in world, or effect has to be applied to self @@ -602,17 +601,17 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply) } // remove auras from units no longer needing them - for (UnitList::iterator itr = targetsToRemove.begin(); itr != targetsToRemove.end();++itr) - if (AuraApplication * aurApp = GetApplicationOfTarget((*itr)->GetGUID())) - (*itr)->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT); + for (Unit* unit : targetsToRemove) + if (AuraApplication* aurApp = GetApplicationOfTarget(unit->GetGUID())) + unit->_UnapplyAura(aurApp, AURA_REMOVE_BY_DEFAULT); if (!apply) return; // apply aura effects for units - for (std::map<Unit*, uint8>::iterator itr = targets.begin(); itr!= targets.end();++itr) + for (auto itr = targets.begin(); itr!= targets.end(); ++itr) { - if (AuraApplication * aurApp = GetApplicationOfTarget(itr->first->GetGUID())) + if (AuraApplication* aurApp = GetApplicationOfTarget(itr->first->GetGUID())) { // owner has to be in world, or effect has to be applied to self ASSERT((!GetOwner()->IsInWorld() && GetOwner() == itr->first) || GetOwner()->IsInMap(itr->first)); @@ -2449,18 +2448,17 @@ void UnitAura::Remove(AuraRemoveMode removeMode) GetUnitOwner()->RemoveOwnedAura(this, removeMode); } -void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) +void UnitAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* caster) { for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) { if (!HasEffect(effIndex)) continue; - UnitList targetList; + + std::deque<Unit*> units; // non-area aura if (GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AURA) - { - targetList.push_back(GetUnitOwner()); - } + units.push_back(GetUnitOwner()); else { float radius = GetSpellInfo()->Effects[effIndex].CalcRadius(caster); @@ -2472,48 +2470,48 @@ void UnitAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) case SPELL_EFFECT_APPLY_AREA_AURA_PARTY: case SPELL_EFFECT_APPLY_AREA_AURA_RAID: { - targetList.push_back(GetUnitOwner()); - Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID); - Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check); + units.push_back(GetUnitOwner()); + Trinity::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::UnitListSearcher<Trinity::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; } case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND: { - targetList.push_back(GetUnitOwner()); - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check); + units.push_back(GetUnitOwner()); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; } case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY: { - Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); // No GetCharmer in searcher - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check); + Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo); // No GetCharmer in searcher + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check); GetUnitOwner()->VisitNearbyObject(radius, searcher); break; } case SPELL_EFFECT_APPLY_AREA_AURA_PET: - targetList.push_back(GetUnitOwner()); + units.push_back(GetUnitOwner()); // no break case SPELL_EFFECT_APPLY_AREA_AURA_OWNER: { if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner()) if (GetUnitOwner()->IsWithinDistInMap(owner, radius)) - targetList.push_back(owner); + units.push_back(owner); break; } } } } - for (UnitList::iterator itr = targetList.begin(); itr!= targetList.end();++itr) + for (Unit* unit : units) { - std::map<Unit*, uint8>::iterator existing = targets.find(*itr); - if (existing != targets.end()) - existing->second |= 1<<effIndex; + auto itr = targets.find(unit); + if (itr != targets.end()) + itr->second |= 1 << effIndex; else - targets[*itr] = 1<<effIndex; + targets[unit] = 1 << effIndex; } } } @@ -2536,7 +2534,7 @@ void DynObjAura::Remove(AuraRemoveMode removeMode) _Remove(removeMode); } -void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster*/) +void DynObjAura::FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* /*caster*/) { Unit* dynObjOwnerCaster = GetDynobjOwner()->GetCaster(); float radius = GetDynobjOwner()->GetRadius(); @@ -2545,28 +2543,29 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* { if (!HasEffect(effIndex)) continue; - UnitList targetList; + + std::deque<Unit*> units; if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_ALLY || GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_UNIT_DEST_AREA_ALLY) { - Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); - Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check); + Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS)); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check); GetDynobjOwner()->VisitNearbyObject(radius, searcher); } else { Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius); - Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check); + Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check); GetDynobjOwner()->VisitNearbyObject(radius, searcher); } - for (UnitList::iterator itr = targetList.begin(); itr!= targetList.end();++itr) + for (Unit* unit : units) { - std::map<Unit*, uint8>::iterator existing = targets.find(*itr); - if (existing != targets.end()) - existing->second |= 1<<effIndex; + auto itr = targets.find(unit); + if (itr != targets.end()) + itr->second |= 1 << effIndex; else - targets[*itr] = 1<<effIndex; + targets[unit] = 1 << effIndex; } } } diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index a526dd8e340..a6dd29f11d0 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -113,7 +113,7 @@ class TC_GAME_API Aura void _Remove(AuraRemoveMode removeMode); virtual void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) = 0; - virtual void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) = 0; + virtual void FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* caster) = 0; void UpdateTargetMap(Unit* caster, bool apply = true); void _RegisterForTargets() {Unit* caster = GetCaster(); UpdateTargetMap(caster, false);} @@ -283,7 +283,7 @@ class TC_GAME_API UnitAura : public Aura void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; - void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; + void FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* caster) override; // Allow Apply Aura Handler to modify and access m_AuraDRGroup void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; } @@ -301,7 +301,7 @@ class TC_GAME_API DynObjAura : public Aura public: void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) override; - void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; + void FillTargetMap(std::unordered_map<Unit*, uint8>& targets, Unit* caster) override; }; class TC_GAME_API ChargeDropEvent : public BasicEvent |