mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Core/Auras: don't ignore SPELL_ATTR3_ONLY_TARGET_PLAYERS in area auras.
Also, start abusing the arbitrary containers for searchers introduced in 8775f8b28a
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user