mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-21 20:56:23 +00:00
fix(Core/Spells): Forward core changes (#8841)
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
#include "ArenaSpectator.h"
|
||||
#include "CellImpl.h"
|
||||
#include "Common.h"
|
||||
#include "ConditionMgr.h"
|
||||
#include "DynamicObject.h"
|
||||
#include "GridNotifiers.h"
|
||||
#include "GridNotifiersImpl.h"
|
||||
@@ -560,19 +561,18 @@ 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
|
||||
{
|
||||
@@ -580,22 +580,22 @@ void Aura::UpdateTargetMap(Unit* caster, bool apply)
|
||||
if (IsArea())
|
||||
for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
|
||||
{
|
||||
if ((existing->second & (1 << effIndex)) && existing->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex))
|
||||
existing->second &= ~(1 << effIndex);
|
||||
if ((itr->second & (1 << effIndex)) && itr->first->IsImmunedToSpellEffect(GetSpellInfo(), effIndex))
|
||||
itr->second &= ~(1 << effIndex);
|
||||
}
|
||||
|
||||
// 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()))
|
||||
@@ -608,7 +608,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
|
||||
@@ -675,7 +675,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
|
||||
@@ -693,15 +693,15 @@ 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()))
|
||||
{
|
||||
@@ -2660,72 +2660,85 @@ 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);
|
||||
|
||||
if (!GetUnitOwner()->HasUnitState(UNIT_STATE_ISOLATED))
|
||||
{
|
||||
Unit* ref = caster;
|
||||
ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
|
||||
SpellTargetCheckTypes selectionType = TARGET_CHECK_DEFAULT;
|
||||
switch (GetSpellInfo()->Effects[effIndex].Effect)
|
||||
{
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
|
||||
{
|
||||
targetList.push_back(GetUnitOwner());
|
||||
Acore::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, GetSpellInfo()->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID);
|
||||
Acore::UnitListSearcher<Acore::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check);
|
||||
units.push_back(GetUnitOwner());
|
||||
Acore::AnyGroupedUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->Effects[effIndex].Effect == SPELL_EFFECT_APPLY_AREA_AURA_RAID, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER));
|
||||
Acore::UnitListSearcher<Acore::AnyGroupedUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
|
||||
{
|
||||
targetList.push_back(GetUnitOwner());
|
||||
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius);
|
||||
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check);
|
||||
units.push_back(GetUnitOwner());
|
||||
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER));
|
||||
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
|
||||
{
|
||||
Acore::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius); // No GetCharmer in searcher
|
||||
Acore::UnitListSearcher<Acore::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), targetList, u_check);
|
||||
Acore::AnyAoETargetUnitInObjectRangeCheck u_check(GetUnitOwner(), GetUnitOwner(), radius, m_spellInfo); // No GetCharmer in searcher
|
||||
Acore::UnitListSearcher<Acore::AnyAoETargetUnitInObjectRangeCheck> searcher(GetUnitOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
|
||||
break;
|
||||
}
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_PET:
|
||||
targetList.push_back(GetUnitOwner());
|
||||
if (!condList || sConditionMgr->IsObjectMeetToConditions(GetUnitOwner(), ref, *condList))
|
||||
units.push_back(GetUnitOwner());
|
||||
[[fallthrough]]; // TODO: Not sure whether the fallthrough was a mistake (forgetting a break) or intended. This should be double-checked.
|
||||
case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
|
||||
{
|
||||
if (Unit* owner = GetUnitOwner()->GetCharmerOrOwner())
|
||||
if (GetUnitOwner()->IsWithinDistInMap(owner, radius))
|
||||
targetList.push_back(owner);
|
||||
if (!condList || sConditionMgr->IsObjectMeetToConditions(owner, ref, *condList))
|
||||
units.push_back(owner);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (selectionType != TARGET_CHECK_DEFAULT)
|
||||
{
|
||||
Acore::WorldObjectSpellAreaTargetCheck check(radius, GetUnitOwner(), ref, GetUnitOwner(), m_spellInfo, selectionType, condList);
|
||||
Acore::UnitListSearcher<Acore::WorldObjectSpellAreaTargetCheck> searcher(GetUnitOwner(), units, check);
|
||||
Cell::VisitAllObjects(GetUnitOwner(), searcher, radius);
|
||||
}
|
||||
|
||||
for (Unit* unit : units)
|
||||
{
|
||||
auto itr = targets.find(unit);
|
||||
if (itr != targets.end())
|
||||
itr->second |= 1 << effIndex;
|
||||
else
|
||||
targets[unit] = 1 << effIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
{
|
||||
std::map<Unit*, uint8>::iterator existing = targets.find(*itr);
|
||||
if (existing != targets.end())
|
||||
existing->second |= 1 << effIndex;
|
||||
else
|
||||
targets[*itr] = 1 << effIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2747,7 +2760,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();
|
||||
@@ -2756,12 +2769,13 @@ 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)
|
||||
{
|
||||
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
|
||||
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check);
|
||||
Acore::AnyFriendlyUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius, m_spellInfo->HasAttribute(SPELL_ATTR3_ONLY_ON_PLAYER));
|
||||
Acore::UnitListSearcher<Acore::AnyFriendlyUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
|
||||
}
|
||||
// pussywizard: TARGET_DEST_DYNOBJ_NONE is supposed to search for both friendly and unfriendly targets, so for any unit
|
||||
@@ -2769,30 +2783,35 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8>& targets, Unit* /*caster*/
|
||||
else if (GetSpellInfo()->Effects[effIndex].TargetB.GetTarget() == TARGET_DEST_DYNOBJ_NONE)
|
||||
{
|
||||
Acore::AnyAttackableUnitExceptForOriginalCasterInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
|
||||
Acore::UnitListSearcher<Acore::AnyAttackableUnitExceptForOriginalCasterInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check);
|
||||
Acore::UnitListSearcher<Acore::AnyAttackableUnitExceptForOriginalCasterInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
|
||||
}
|
||||
else
|
||||
{
|
||||
Acore::AnyAoETargetUnitInObjectRangeCheck u_check(GetDynobjOwner(), dynObjOwnerCaster, radius);
|
||||
Acore::UnitListSearcher<Acore::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), targetList, u_check);
|
||||
Acore::UnitListSearcher<Acore::AnyAoETargetUnitInObjectRangeCheck> searcher(GetDynobjOwner(), units, u_check);
|
||||
Cell::VisitAllObjects(GetDynobjOwner(), searcher, radius);
|
||||
}
|
||||
|
||||
for (UnitList::iterator itr = targetList.begin(); itr != targetList.end(); ++itr)
|
||||
for (Unit* unit : units)
|
||||
{
|
||||
// xinef: check z level and los dependence
|
||||
Unit* target = *itr;
|
||||
float zLevel = GetDynobjOwner()->GetPositionZ();
|
||||
if (target->GetPositionZ() + 3.0f < zLevel || target->GetPositionZ() - 5.0f > zLevel)
|
||||
if (!target->IsWithinLOSInMap(GetDynobjOwner()))
|
||||
if (unit->GetPositionZ() + 3.0f < zLevel || unit->GetPositionZ() - 5.0f > zLevel)
|
||||
{
|
||||
if (!unit->IsWithinLOSInMap(GetDynobjOwner()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user