[9850] Fixed target selection for area spells casted from aura at enemy.

* Spell::GetCastingObject must be use for selection visual/point cast,
  not for friend/enemy checks. Add extanded GetAffectiveCasterObject
  for proper provide for referecned checks wild gameobject casted case.

* Also support chain damage spells casted by gameobjects.
This commit is contained in:
VladimirMangos 2010-05-08 00:27:25 +04:00
parent d1130af777
commit 921b0d668f
4 changed files with 29 additions and 15 deletions

View file

@ -821,34 +821,36 @@ namespace MaNGOS
class AnyAoEVisibleTargetUnitInObjectRangeCheck
{
public:
AnyAoEVisibleTargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range)
: i_obj(obj), i_funit(funit), i_range(range)
AnyAoEVisibleTargetUnitInObjectRangeCheck(WorldObject const* obj, WorldObject const* originalCaster, float range)
: i_obj(obj), i_originalCaster(originalCaster), i_range(range)
{
Unit const* check = i_funit;
Unit const* owner = i_funit->GetOwner();
if(owner)
check = owner;
i_targetForPlayer = ( check->GetTypeId()==TYPEID_PLAYER );
i_targetForUnit = i_originalCaster->isType(TYPEMASK_UNIT);
i_targetForPlayer = (i_originalCaster->GetTypeId() == TYPEID_PLAYER);
}
bool operator()(Unit* u)
{
// Check contains checks for: live, non-selectable, non-attackable flags, flight check and GM check, ignore totems
if (!u->isTargetableForAttack())
return false;
// ignore totems as AoE targets
if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem())
return false;
if (!u->isVisibleForOrDetect(i_funit, i_funit, false))
// check visibility only for unit-like original casters
if (i_targetForUnit && !u->isVisibleForOrDetect((Unit const*)i_originalCaster, i_originalCaster, false))
return false;
if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range))
if ((i_targetForPlayer ? !i_originalCaster->IsFriendlyTo(u) : i_originalCaster->IsHostileTo(u)) && i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
}
private:
bool i_targetForUnit;
bool i_targetForPlayer;
WorldObject const* i_obj;
Unit const* i_funit;
WorldObject const* i_originalCaster;
float i_range;
};

View file

@ -1660,7 +1660,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
else
{
Unit* pUnitTarget = m_targets.getUnitTarget();
Unit* originalCaster = GetAffectiveCaster();
WorldObject* originalCaster = GetAffectiveCasterObject();
if(!pUnitTarget || !originalCaster)
break;
@ -6486,6 +6486,16 @@ void Spell::FillRaidOrPartyHealthPriorityTargets(UnitList &targetUnitMap, Unit*
}
}
WorldObject* Spell::GetAffectiveCasterObject() const
{
if (m_originalCasterGUID.IsEmpty())
return m_caster;
if (m_originalCasterGUID.IsGameobject() && m_caster->IsInWorld())
return m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
return m_originalCaster;
}
WorldObject* Spell::GetCastingObject() const
{
if (m_originalCasterGUID.IsGameobject())

View file

@ -475,7 +475,9 @@ class Spell
// caster types:
// formal spell caster, in game source of spell affects cast
Unit* GetCaster() const { return m_caster; }
// real source of cast affects, explcit caster, or DoT/HoT applier, or GO owner, etc. Can be NULL
// real source of cast affects, explcit caster, or DoT/HoT applier, or GO owner, or wild GO itself. Can be NULL
WorldObject* GetAffectiveCasterObject() const;
// limited version returning NULL in cases not Unit* caster object, need for Aura (auras currently not support non-Unit caster)
Unit* GetAffectiveCaster() const { return !m_originalCasterGUID.IsEmpty() ? m_originalCaster : m_caster; }
// m_originalCasterGUID can store GO guid, and in this case this is visual caster
WorldObject* GetCastingObject() const;
@ -656,7 +658,7 @@ namespace MaNGOS
SpellNotifierPlayer(Spell &spell, std::list<Unit*> &data, const uint32 &i, float radius)
: i_data(data), i_spell(spell), i_index(i), i_radius(radius)
{
i_originalCaster = i_spell.GetCastingObject();
i_originalCaster = i_spell.GetAffectiveCasterObject();
}
void Visit(PlayerMapType &m)
@ -694,7 +696,7 @@ namespace MaNGOS
SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY)
: i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType)
{
i_originalCaster = spell.GetCastingObject();
i_originalCaster = i_spell.GetAffectiveCasterObject();
i_playerControled = i_originalCaster ? i_originalCaster->IsControlledByPlayer() : false;
}

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "9849"
#define REVISION_NR "9850"
#endif // __REVISION_NR_H__