[9510] Gameobject casting improvements.

* Add IsHostileTo/IsFriendlyTo and implement expected way checks for diff. world object types.
  For controlled object check redirected to specific owner, for wild gameobject base at gameobject faction.
  If faction not set expected to be hostile to anyone.
* Update grid searchers to be usable with world object instead only unit case.
  Some grid searches lost redundent second object arg, AnyAoETargetUnitInObjectRangeCheck lost hitHidden arg
  (for hitHidden==true case added new AnyAoEVisibleTargetUnitInObjectRangeCheck)
* Updated grid searchers used with gameobject area casts now.
  Note: Gameobject area spell cast animation will still wrong show around cast triggering target instead
  center around gameobject.
* In case gameobject aura apply to target for restored use target itself as caster because
  we not have currently another way apply aura form wild gameobject.
This commit is contained in:
VladimirMangos 2010-03-04 04:04:47 +03:00
parent 52701a58f6
commit 7fb5d850bf
18 changed files with 242 additions and 54 deletions

View file

@ -26,6 +26,7 @@
#include "Opcodes.h" #include "Opcodes.h"
#include "GossipDef.h" #include "GossipDef.h"
#include "World.h" #include "World.h"
#include "ObjectMgr.h"
Corpse::Corpse(CorpseType type) : WorldObject() Corpse::Corpse(CorpseType type) : WorldObject()
{ {
@ -232,3 +233,19 @@ bool Corpse::isVisibleForInState(Player const* u, WorldObject const* viewPoint,
{ {
return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); return IsInWorld() && u->IsInWorld() && IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
} }
bool Corpse::IsHostileTo( Unit const* unit ) const
{
if (Player* owner = sObjectMgr.GetPlayer(GetOwnerGUID()))
return owner->IsHostileTo(unit);
else
return false;
}
bool Corpse::IsFriendlyTo( Unit const* unit ) const
{
if (Player* owner = sObjectMgr.GetPlayer(GetOwnerGUID()))
return owner->IsFriendlyTo(unit);
else
return true;
}

View file

@ -71,6 +71,9 @@ class Corpse : public WorldObject
void ResetGhostTime() { m_time = time(NULL); } void ResetGhostTime() { m_time = time(NULL); }
CorpseType GetType() const { return m_type; } CorpseType GetType() const { return m_type; }
bool IsHostileTo(Unit const* unit) const;
bool IsFriendlyTo(Unit const* unit) const;
GridPair const& GetGrid() const { return m_grid; } GridPair const& GetGrid() const { return m_grid; }
void SetGrid(GridPair const& grid) { m_grid = grid; } void SetGrid(GridPair const& grid) { m_grid = grid; }

View file

@ -161,3 +161,19 @@ bool DynamicObject::isVisibleForInState(Player const* u, WorldObject const* view
// normal case // normal case
return IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false); return IsWithinDistInMap(viewPoint, World::GetMaxVisibleDistanceForObject() + (inVisibleList ? World::GetVisibleObjectGreyDistance() : 0.0f), false);
} }
bool DynamicObject::IsHostileTo( Unit const* unit ) const
{
if (Unit* owner = GetCaster())
return owner->IsHostileTo(unit);
else
return false;
}
bool DynamicObject::IsFriendlyTo( Unit const* unit ) const
{
if (Unit* owner = GetCaster())
return owner->IsFriendlyTo(unit);
else
return true;
}

View file

@ -47,6 +47,10 @@ class DynamicObject : public WorldObject
void AddAffected(Unit *unit) { m_affected.insert(unit); } void AddAffected(Unit *unit) { m_affected.insert(unit); }
void RemoveAffected(Unit *unit) { m_affected.erase(unit); } void RemoveAffected(Unit *unit) { m_affected.erase(unit); }
void Delay(int32 delaytime); void Delay(int32 delaytime);
bool IsHostileTo(Unit const* unit) const;
bool IsFriendlyTo(Unit const* unit) const;
bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const; bool isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const;
void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); } void Say(int32 textId, uint32 language, uint64 TargetGuid) { MonsterSay(textId,language,TargetGuid); }

View file

@ -1448,3 +1448,90 @@ void GameObject::UpdateRotationFields(float rotation2 /*=0.0f*/, float rotation3
SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2); SetFloatValue(GAMEOBJECT_PARENTROTATION+2, rotation2);
SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3); SetFloatValue(GAMEOBJECT_PARENTROTATION+3, rotation3);
} }
bool GameObject::IsHostileTo(Unit const* unit) const
{
// always non-hostile to GM in GM mode
if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster())
return false;
// test owner instead if have
if (Unit const* owner = GetOwner())
return owner->IsHostileTo(unit);
if (Unit const* targetOwner = unit->GetCharmerOrOwner())
return IsHostileTo(targetOwner);
// for not set faction case (wild object) use hostile case
if(!GetGOInfo()->faction)
return true;
// faction base cases
FactionTemplateEntry const*tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction);
FactionTemplateEntry const*target_faction = unit->getFactionTemplateEntry();
if(!tester_faction || !target_faction)
return false;
// GvP forced reaction and reputation case
if(unit->GetTypeId()==TYPEID_PLAYER)
{
// forced reaction
if(tester_faction->faction)
{
if(ReputationRank const* force = ((Player*)unit)->GetReputationMgr().GetForcedRankIfAny(tester_faction))
return *force <= REP_HOSTILE;
// apply reputation state
FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction);
if(raw_tester_faction && raw_tester_faction->reputationListID >=0 )
return ((Player const*)unit)->GetReputationMgr().GetRank(raw_tester_faction) <= REP_HOSTILE;
}
}
// common faction based case (GvC,GvP)
return tester_faction->IsHostileTo(*target_faction);
}
bool GameObject::IsFriendlyTo(Unit const* unit) const
{
// always friendly to GM in GM mode
if(unit->GetTypeId()==TYPEID_PLAYER && ((Player const*)unit)->isGameMaster())
return true;
// test owner instead if have
if (Unit const* owner = GetOwner())
return owner->IsFriendlyTo(unit);
if (Unit const* targetOwner = unit->GetCharmerOrOwner())
return IsFriendlyTo(targetOwner);
// for not set faction case (wild object) use hostile case
if(!GetGOInfo()->faction)
return false;
// faction base cases
FactionTemplateEntry const*tester_faction = sFactionTemplateStore.LookupEntry(GetGOInfo()->faction);
FactionTemplateEntry const*target_faction = unit->getFactionTemplateEntry();
if(!tester_faction || !target_faction)
return false;
// GvP forced reaction and reputation case
if(unit->GetTypeId()==TYPEID_PLAYER)
{
// forced reaction
if(tester_faction->faction)
{
if(ReputationRank const* force =((Player*)unit)->GetReputationMgr().GetForcedRankIfAny(tester_faction))
return *force >= REP_FRIENDLY;
// apply reputation state
if(FactionEntry const* raw_tester_faction = sFactionStore.LookupEntry(tester_faction->faction))
if(raw_tester_faction->reputationListID >=0 )
return ((Player const*)unit)->GetReputationMgr().GetRank(raw_tester_faction) >= REP_FRIENDLY;
}
}
// common faction based case (GvC,GvP)
return tester_faction->IsFriendlyTo(*target_faction);
}

View file

@ -677,6 +677,8 @@ class MANGOS_DLL_SPEC GameObject : public WorldObject
// 0 = use `gameobject`.`spawntimesecs` // 0 = use `gameobject`.`spawntimesecs`
void ResetDoorOrButton(); void ResetDoorOrButton();
bool IsHostileTo(Unit const* unit) const;
bool IsFriendlyTo(Unit const* unit) const;
void SummonLinkedTrapIfAny(); void SummonLinkedTrapIfAny();
void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target); void TriggeringLinkedGameObject( uint32 trapEntry, Unit* target);

View file

@ -229,10 +229,10 @@ bool CannibalizeObjectCheck::operator()(Corpse* u)
Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID()); Player* owner = ObjectAccessor::FindPlayer(u->GetOwnerGUID());
if( !owner || i_funit->IsFriendlyTo(owner)) if( !owner || i_fobj->IsFriendlyTo(owner))
return false; return false;
if(i_funit->IsWithinDistInMap(u, i_range) ) if(i_fobj->IsWithinDistInMap(u, i_range) )
return true; return true;
return false; return false;

View file

@ -499,34 +499,34 @@ namespace MaNGOS
class RaiseDeadObjectCheck class RaiseDeadObjectCheck
{ {
public: public:
RaiseDeadObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} RaiseDeadObjectCheck(Player const* fobj, float range) : i_fobj(fobj), i_range(range) {}
bool operator()(Creature* u) bool operator()(Creature* u)
{ {
if (i_funit->GetTypeId()!=TYPEID_PLAYER || !((Player*)i_funit)->isHonorOrXPTarget(u) || if (i_fobj->isHonorOrXPTarget(u) ||
u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() || u->getDeathState() != CORPSE || u->isDeadByDefault() || u->isInFlight() ||
( u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1)) )==0 || ( u->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1)) )==0 ||
(u->GetDisplayId() != u->GetNativeDisplayId())) (u->GetDisplayId() != u->GetNativeDisplayId()))
return false; return false;
return i_funit->IsWithinDistInMap(u, i_range); return i_fobj->IsWithinDistInMap(u, i_range);
} }
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
private: private:
Unit* const i_funit; Player const* i_fobj;
float i_range; float i_range;
}; };
class ExplodeCorpseObjectCheck class ExplodeCorpseObjectCheck
{ {
public: public:
ExplodeCorpseObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} ExplodeCorpseObjectCheck(WorldObject const* fobj, float range) : i_fobj(fobj), i_range(range) {}
bool operator()(Player* u) bool operator()(Player* u)
{ {
if (u->getDeathState()!=CORPSE || u->isInFlight() || if (u->getDeathState()!=CORPSE || u->isInFlight() ||
u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId())) u->HasAuraType(SPELL_AURA_GHOST) || (u->GetDisplayId() != u->GetNativeDisplayId()))
return false; return false;
return i_funit->IsWithinDistInMap(u, i_range); return i_fobj->IsWithinDistInMap(u, i_range);
} }
bool operator()(Creature* u) bool operator()(Creature* u)
{ {
@ -535,37 +535,37 @@ namespace MaNGOS
(u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)!=0) (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)!=0)
return false; return false;
return i_funit->IsWithinDistInMap(u, i_range); return i_fobj->IsWithinDistInMap(u, i_range);
} }
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
private: private:
Unit* const i_funit; WorldObject const* i_fobj;
float i_range; float i_range;
}; };
class CannibalizeObjectCheck class CannibalizeObjectCheck
{ {
public: public:
CannibalizeObjectCheck(Unit* funit, float range) : i_funit(funit), i_range(range) {} CannibalizeObjectCheck(WorldObject const* fobj, float range) : i_fobj(fobj), i_range(range) {}
bool operator()(Player* u) bool operator()(Player* u)
{ {
if( i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ) if( i_fobj->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() )
return false; return false;
return i_funit->IsWithinDistInMap(u, i_range); return i_fobj->IsWithinDistInMap(u, i_range);
} }
bool operator()(Corpse* u); bool operator()(Corpse* u);
bool operator()(Creature* u) bool operator()(Creature* u)
{ {
if (i_funit->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() || if (i_fobj->IsFriendlyTo(u) || u->isAlive() || u->isInFlight() ||
(u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0) (u->GetCreatureTypeMask() & CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD)==0)
return false; return false;
return i_funit->IsWithinDistInMap(u, i_range); return i_fobj->IsWithinDistInMap(u, i_range);
} }
template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; } template<class NOT_INTERESTED> bool operator()(NOT_INTERESTED*) { return false; }
private: private:
Unit* const i_funit; WorldObject const* i_fobj;
float i_range; float i_range;
}; };
@ -688,7 +688,7 @@ namespace MaNGOS
class FriendlyCCedInRange class FriendlyCCedInRange
{ {
public: public:
FriendlyCCedInRange(Unit const* obj, float range) : i_obj(obj), i_range(range) {} FriendlyCCedInRange(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {}
bool operator()(Unit* u) bool operator()(Unit* u)
{ {
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
@ -699,14 +699,14 @@ namespace MaNGOS
return false; return false;
} }
private: private:
Unit const* i_obj; WorldObject const* i_obj;
float i_range; float i_range;
}; };
class FriendlyMissingBuffInRange class FriendlyMissingBuffInRange
{ {
public: public:
FriendlyMissingBuffInRange(Unit const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {} FriendlyMissingBuffInRange(WorldObject const* obj, float range, uint32 spellid) : i_obj(obj), i_range(range), i_spell(spellid) {}
bool operator()(Unit* u) bool operator()(Unit* u)
{ {
if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) && if(u->isAlive() && u->isInCombat() && !i_obj->IsHostileTo(u) && i_obj->IsWithinDistInMap(u, i_range) &&
@ -717,7 +717,7 @@ namespace MaNGOS
return false; return false;
} }
private: private:
Unit const* i_obj; WorldObject const* i_obj;
float i_range; float i_range;
uint32 i_spell; uint32 i_spell;
}; };
@ -761,17 +761,16 @@ namespace MaNGOS
class AnyFriendlyUnitInObjectRangeCheck class AnyFriendlyUnitInObjectRangeCheck
{ {
public: public:
AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range) : i_obj(obj), i_funit(funit), i_range(range) {} AnyFriendlyUnitInObjectRangeCheck(WorldObject const* obj, float range) : i_obj(obj), i_range(range) {}
bool operator()(Unit* u) bool operator()(Unit* u)
{ {
if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_funit->IsFriendlyTo(u)) if(u->isAlive() && i_obj->IsWithinDistInMap(u, i_range) && i_obj->IsFriendlyTo(u))
return true; return true;
else else
return false; return false;
} }
private: private:
WorldObject const* i_obj; WorldObject const* i_obj;
Unit const* i_funit;
float i_range; float i_range;
}; };
@ -816,11 +815,11 @@ namespace MaNGOS
NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&); NearestAttackableUnitInObjectRangeCheck(NearestAttackableUnitInObjectRangeCheck const&);
}; };
class AnyAoETargetUnitInObjectRangeCheck class AnyAoEVisibleTargetUnitInObjectRangeCheck
{ {
public: public:
AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range, bool hitHidden = true) AnyAoEVisibleTargetUnitInObjectRangeCheck(WorldObject const* obj, Unit const* funit, float range)
: i_obj(obj), i_funit(funit), i_range(range), i_hitHidden(hitHidden) : i_obj(obj), i_funit(funit), i_range(range)
{ {
Unit const* check = i_funit; Unit const* check = i_funit;
Unit const* owner = i_funit->GetOwner(); Unit const* owner = i_funit->GetOwner();
@ -835,7 +834,7 @@ namespace MaNGOS
return false; return false;
if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem()) if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem())
return false; return false;
if (!i_hitHidden && !u->isVisibleForOrDetect(i_funit, i_funit, false)) if (!u->isVisibleForOrDetect(i_funit, i_funit, false))
return false; return false;
if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range)) if(( i_targetForPlayer ? !i_funit->IsFriendlyTo(u) : i_funit->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range))
@ -848,7 +847,36 @@ namespace MaNGOS
WorldObject const* i_obj; WorldObject const* i_obj;
Unit const* i_funit; Unit const* i_funit;
float i_range; float i_range;
bool i_hitHidden; };
class AnyAoETargetUnitInObjectRangeCheck
{
public:
AnyAoETargetUnitInObjectRangeCheck(WorldObject const* obj, float range)
: i_obj(obj), i_range(range)
{
i_targetForPlayer = i_obj->IsControlledByPlayer();
}
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;
if(u->GetTypeId()==TYPEID_UNIT && ((Creature*)u)->isTotem())
return false;
if(( i_targetForPlayer ? !i_obj->IsFriendlyTo(u) : i_obj->IsHostileTo(u) )&& i_obj->IsWithinDistInMap(u, i_range))
return true;
return false;
}
private:
bool i_targetForPlayer;
WorldObject const* i_obj;
float i_range;
}; };
// do attack at call of help to friendly crearture // do attack at call of help to friendly crearture
@ -877,6 +905,7 @@ namespace MaNGOS
if (u->AI()) if (u->AI())
u->AI()->AttackStart(i_enemy); u->AI()->AttackStart(i_enemy);
} }
private: private:
Unit* const i_funit; Unit* const i_funit;
Unit* const i_enemy; Unit* const i_enemy;

View file

@ -1958,3 +1958,21 @@ void WorldObject::BuildUpdateData( UpdateDataMapType & update_players)
ClearUpdateMask(false); ClearUpdateMask(false);
} }
bool WorldObject::IsControlledByPlayer() const
{
switch (GetTypeId())
{
case TYPEID_GAMEOBJECT:
return IS_PLAYER_GUID(((GameObject*)this)->GetOwnerGUID());
case TYPEID_UNIT:
case TYPEID_PLAYER:
return ((Unit*)this)->IsCharmerOrOwnerPlayerOrPlayerItself();
case TYPEID_DYNAMICOBJECT:
return IS_PLAYER_GUID(((DynamicObject*)this)->GetCasterGUID());
case TYPEID_CORPSE:
return true;
default:
return false;
}
}

View file

@ -91,6 +91,7 @@ class UpdateData;
class WorldSession; class WorldSession;
class Creature; class Creature;
class Player; class Player;
class Unit;
class Map; class Map;
class UpdateMask; class UpdateMask;
class InstanceData; class InstanceData;
@ -472,6 +473,10 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void SendObjectDeSpawnAnim(uint64 guid); void SendObjectDeSpawnAnim(uint64 guid);
void SendGameObjectCustomAnim(uint64 guid); void SendGameObjectCustomAnim(uint64 guid);
virtual bool IsHostileTo(Unit const* unit) const =0;
virtual bool IsFriendlyTo(Unit const* unit) const =0;
bool IsControlledByPlayer() const;
virtual void SaveRespawnTime() {} virtual void SaveRespawnTime() {}
void AddObjectToRemoveList(); void AddObjectToRemoveList();

View file

@ -19771,7 +19771,7 @@ uint32 Player::GetResurrectionSpellId()
} }
// Used in triggers for check "Only to targets that grant experience or honor" req // Used in triggers for check "Only to targets that grant experience or honor" req
bool Player::isHonorOrXPTarget(Unit* pVictim) bool Player::isHonorOrXPTarget(Unit* pVictim) const
{ {
uint32 v_level = pVictim->getLevel(); uint32 v_level = pVictim->getLevel();
uint32 k_grey = MaNGOS::XP::GetGrayLevel(getLevel()); uint32 k_grey = MaNGOS::XP::GetGrayLevel(getLevel());

View file

@ -1895,7 +1895,7 @@ class MANGOS_DLL_SPEC Player : public Unit
bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const; bool IsAtGroupRewardDistance(WorldObject const* pRewardSource) const;
bool RewardPlayerAndGroupAtKill(Unit* pVictim); bool RewardPlayerAndGroupAtKill(Unit* pVictim);
void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource); void RewardPlayerAndGroupAtEvent(uint32 creature_id,WorldObject* pRewardSource);
bool isHonorOrXPTarget(Unit* pVictim); bool isHonorOrXPTarget(Unit* pVictim) const;
ReputationMgr& GetReputationMgr() { return m_reputationMgr; } ReputationMgr& GetReputationMgr() { return m_reputationMgr; }
ReputationMgr const& GetReputationMgr() const { return m_reputationMgr; } ReputationMgr const& GetReputationMgr() const { return m_reputationMgr; }

View file

@ -1445,7 +1445,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
std::list<Unit *> tempTargetUnitMap; std::list<Unit *> tempTargetUnitMap;
{ {
MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(m_caster, max_range);
MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
@ -1514,7 +1514,7 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
cell.SetNoCreate(); cell.SetNoCreate();
std::list<Unit*> tempTargetUnitMap; std::list<Unit*> tempTargetUnitMap;
{ {
MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, max_range); MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, max_range);
MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
@ -1610,10 +1610,10 @@ void Spell::SetTargetMap(SpellEffectIndex effIndex, uint32 targetMode, UnitList&
std::list<Unit *> tempTargetUnitMap; std::list<Unit *> tempTargetUnitMap;
{ {
MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range, false); MaNGOS::AnyAoEVisibleTargetUnitInObjectRangeCheck u_check(pUnitTarget, originalCaster, max_range);
MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyAoEVisibleTargetUnitInObjectRangeCheck> searcher(m_caster, tempTargetUnitMap, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer> world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoEVisibleTargetUnitInObjectRangeCheck>, WorldTypeMapContainer> world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer> grid_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoEVisibleTargetUnitInObjectRangeCheck>, GridTypeMapContainer> grid_unit_searcher(searcher);
cell.Visit(p, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); cell.Visit(p, world_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
cell.Visit(p, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range); cell.Visit(p, grid_unit_searcher, *m_caster->GetMap(), *pUnitTarget, max_range);
@ -3170,20 +3170,20 @@ void Spell::SendCastResult(Player* caster, SpellEntry const* spellInfo, uint8 ca
void Spell::SendSpellStart() void Spell::SendSpellStart()
{ {
if(!IsNeedSendToClient()) if (!IsNeedSendToClient())
return; return;
sLog.outDebug("Sending SMSG_SPELL_START id=%u", m_spellInfo->Id); sLog.outDebug("Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
uint32 castFlags = CAST_FLAG_UNKNOWN1; uint32 castFlags = CAST_FLAG_UNKNOWN1;
if(IsRangedSpell()) if (IsRangedSpell())
castFlags |= CAST_FLAG_AMMO; castFlags |= CAST_FLAG_AMMO;
if(m_spellInfo->runeCostID) if (m_spellInfo->runeCostID)
castFlags |= CAST_FLAG_UNKNOWN10; castFlags |= CAST_FLAG_UNKNOWN10;
WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2)); WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
if(m_CastItem) if (m_CastItem)
data.append(m_CastItem->GetPackGUID()); data.append(m_CastItem->GetPackGUID());
else else
data.append(m_caster->GetPackGUID()); data.append(m_caster->GetPackGUID());

View file

@ -620,12 +620,12 @@ namespace MaNGOS
Spell &i_spell; Spell &i_spell;
const uint32& i_index; const uint32& i_index;
float i_radius; float i_radius;
Unit* i_originalCaster; WorldObject* i_originalCaster;
SpellNotifierPlayer(Spell &spell, std::list<Unit*> &data, const uint32 &i, float radius) 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_data(data), i_spell(spell), i_index(i), i_radius(radius)
{ {
i_originalCaster = i_spell.GetAffectiveCaster(); i_originalCaster = i_spell.GetCastingObject();
} }
void Visit(PlayerMapType &m) void Visit(PlayerMapType &m)
@ -656,13 +656,15 @@ namespace MaNGOS
SpellNotifyPushType i_push_type; SpellNotifyPushType i_push_type;
float i_radius; float i_radius;
SpellTargets i_TargetType; SpellTargets i_TargetType;
Unit* i_originalCaster; WorldObject* i_originalCaster;
bool i_playerControled;
SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, SpellNotifyPushType type, SpellNotifierCreatureAndPlayer(Spell &spell, std::list<Unit*> &data, float radius, SpellNotifyPushType type,
SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY) SpellTargets TargetType = SPELL_TARGETS_NOT_FRIENDLY)
: i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType) : i_data(&data), i_spell(spell), i_push_type(type), i_radius(radius), i_TargetType(TargetType)
{ {
i_originalCaster = spell.GetAffectiveCaster(); i_originalCaster = spell.GetCastingObject();
i_playerControled = i_originalCaster->IsControlledByPlayer();
} }
template<class T> inline void Visit(GridRefManager<T> &m) template<class T> inline void Visit(GridRefManager<T> &m)
@ -704,16 +706,14 @@ namespace MaNGOS
if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem()) if(itr->getSource()->GetTypeId()==TYPEID_UNIT && ((Creature*)itr->getSource())->isTotem())
continue; continue;
Unit* check = i_originalCaster->GetCharmerOrOwnerOrSelf(); if (i_playerControled)
if( check->GetTypeId()==TYPEID_PLAYER )
{ {
if (check->IsFriendlyTo( itr->getSource() )) if (i_originalCaster->IsFriendlyTo( itr->getSource() ))
continue; continue;
} }
else else
{ {
if (!check->IsHostileTo( itr->getSource() )) if (!i_originalCaster->IsHostileTo( itr->getSource() ))
continue; continue;
} }
} }

View file

@ -759,7 +759,7 @@ void AreaAura::Update(uint32 diff)
cell.data.Part.reserved = ALL_DISTRICT; cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate(); cell.SetNoCreate();
MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, owner, m_radius); MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(caster, m_radius);
MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(caster,targets, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(caster,targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);
@ -774,7 +774,7 @@ void AreaAura::Update(uint32 diff)
cell.data.Part.reserved = ALL_DISTRICT; cell.data.Part.reserved = ALL_DISTRICT;
cell.SetNoCreate(); cell.SetNoCreate();
MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, owner, m_radius); // No GetCharmer in searcher MaNGOS::AnyAoETargetUnitInObjectRangeCheck u_check(caster, m_radius); // No GetCharmer in searcher
MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(caster, targets, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck> searcher(caster, targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer > grid_unit_searcher(searcher);

View file

@ -2826,7 +2826,14 @@ void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
Unit* caster = GetAffectiveCaster(); Unit* caster = GetAffectiveCaster();
if(!caster) if(!caster)
{
// FIXME: currently we can't have auras applied explIcitly by gameobjects
// so for auras from wild gameobjects (no owner) target used
if (IS_GAMEOBJECT_GUID(m_originalCasterGUID))
caster = unitTarget;
else
return; return;
}
sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]); sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]);

View file

@ -12896,7 +12896,7 @@ Unit* Unit::SelectRandomFriendlyTarget(Unit* except /*= NULL*/, float radius /*=
std::list<Unit *> targets; std::list<Unit *> targets;
MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(this, this, radius); MaNGOS::AnyFriendlyUnitInObjectRangeCheck u_check(this, radius);
MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(this, targets, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck> searcher(this, targets, u_check);
TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher); TypeContainerVisitor<MaNGOS::UnitListSearcher<MaNGOS::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "9509" #define REVISION_NR "9510"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__