[10052] Camera System

(based on SilverIce's repo commit 4f2f4ab + next 3 more)

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
SilverIce 2010-06-12 05:00:09 +04:00 committed by VladimirMangos
parent f520c9b1e0
commit e427ce80cc
27 changed files with 515 additions and 207 deletions

View file

@ -639,7 +639,7 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
{ {
MaNGOS::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED,achievement->ID); MaNGOS::AchievementChatBuilder say_builder(*GetPlayer(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED,achievement->ID);
MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> say_do(say_builder); MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> say_do(say_builder);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do); MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::AchievementChatBuilder> > say_worker(GetPlayer(),sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
Cell::VisitWorldObjects(GetPlayer(), say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY)); Cell::VisitWorldObjects(GetPlayer(), say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY));
} }

134
src/game/Camera.cpp Normal file
View file

@ -0,0 +1,134 @@
#include "Camera.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
#include "Log.h"
#include "Errors.h"
#include "Player.h"
Camera::Camera(Player* pl) : m_owner(*pl), m_source(pl)
{
m_source->GetViewPoint().Attach(this);
}
Camera::~Camera()
{
// view of camera should be already reseted to owner (RemoveFromWorld -> Event_RemovedFromWorld -> ResetView)
ASSERT(m_source == &m_owner);
// for symmetry with constructor and way to make viewpoint's list empty
m_source->GetViewPoint().Detach(this);
}
void Camera::ReceivePacket(WorldPacket *data)
{
m_owner.SendDirectMessage(data);
}
void Camera::UpdateForCurrentViewPoint()
{
m_gridRef.unlink();
if (GridType* grid = m_source->GetViewPoint().m_grid)
grid->AddWorldObject(this);
m_owner.SetUInt64Value(PLAYER_FARSIGHT, (m_source == &m_owner ? 0 : m_source->GetGUID()));
UpdateVisibilityForOwner();
}
void Camera::SetView(WorldObject *obj)
{
ASSERT(obj);
if (!m_owner.IsInMap(obj))
{
sLog.outError("Camera::SetView, viewpoint is not in map with camera's owner");
return;
}
if (!obj->isType(TYPEMASK_DYNAMICOBJECT | TYPEMASK_UNIT))
{
sLog.outError("Camera::SetView, viewpoint type is not available for client");
return;
}
m_source->GetViewPoint().Detach(this);
m_source = obj;
m_source->GetViewPoint().Attach(this);
UpdateForCurrentViewPoint();
}
void Camera::Event_ViewPointVisibilityChanged()
{
if (!m_owner.HaveAtClient(m_source))
ResetView();
}
void Camera::ResetView()
{
m_source->GetViewPoint().Detach(this);
m_source = &m_owner;
m_source->GetViewPoint().Attach(this);
UpdateForCurrentViewPoint();
}
void Camera::Event_AddedToWorld()
{
GridType* grid = m_source->GetViewPoint().m_grid;
ASSERT(grid);
grid->AddWorldObject(this);
UpdateVisibilityForOwner();
}
void Camera::Event_RemovedFromWorld()
{
if (m_source == &m_owner)
{
m_gridRef.unlink();
return;
}
ResetView();
}
void Camera::Event_Moved()
{
m_gridRef.unlink();
m_source->GetViewPoint().m_grid->AddWorldObject(this);
}
void Camera::UpdateVisibilityOf(WorldObject* target)
{
m_owner.UpdateVisibilityOf(m_source, target);
}
template<class T>
void Camera::UpdateVisibilityOf(T * target, UpdateData &data, std::set<WorldObject*>& vis)
{
m_owner.template UpdateVisibilityOf<T>(m_source, target,data,vis);
}
template void Camera::UpdateVisibilityOf(Player* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(Creature* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(Corpse* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(GameObject* , UpdateData& , std::set<WorldObject*>& );
template void Camera::UpdateVisibilityOf(DynamicObject* , UpdateData& , std::set<WorldObject*>& );
void Camera::UpdateVisibilityForOwner()
{
MaNGOS::VisibleNotifier notifier(*this);
Cell::VisitAllObjects(m_source, notifier, m_source->GetMap()->GetVisibilityDistance(), false);
notifier.Notify();
}
//////////////////
ViewPoint::~ViewPoint()
{
if (!m_cameras.empty())
{
sLog.outError("ViewPoint destructor called, but some cameras referenced to it");
}
}

122
src/game/Camera.h Normal file
View file

@ -0,0 +1,122 @@
#ifndef MANGOSSERVER_CAMERA_H
#define MANGOSSERVER_CAMERA_H
#include "GridDefines.h"
class ViewPoint;
class WorldObject;
class UpdateData;
class WorldPacket;
class Player;
/// Camera - object-receiver. Receives broadcast packets from nearby worldobjects, object visibility changes and sends them to client
class MANGOS_DLL_SPEC Camera
{
friend class ViewPoint;
public:
explicit Camera(Player* pl);
~Camera();
WorldObject* GetBody() { return m_source;}
Player* GetOwner() { return &m_owner;}
// set camera's view to any worldobject
// Note: this worldobject must be in same map, in same phase with camera's owner(player)
// client supports only unit and dynamic objects as farsight objects
void SetView(WorldObject *obj);
// set view to camera's owner
void ResetView();
template<class T>
void UpdateVisibilityOf(T * obj, UpdateData &d, std::set<WorldObject*>& vis);
void UpdateVisibilityOf(WorldObject* obj);
void ReceivePacket(WorldPacket *data);
// updates visibility of worldobjects around viewpoint for camera's owner
void UpdateVisibilityForOwner();
private:
// called when viewpoint changes visibility state
void Event_AddedToWorld();
void Event_RemovedFromWorld();
void Event_Moved();
void Event_ViewPointVisibilityChanged();
Player& m_owner;
WorldObject* m_source;
void UpdateForCurrentViewPoint();
public:
GridReference<Camera>& GetGridRef() { return m_gridRef; }
bool isActiveObject() const { return false; }
private:
GridReference<Camera> m_gridRef;
};
/// Object-observer, notifies farsight object state to cameras that attached to it
class MANGOS_DLL_SPEC ViewPoint
{
friend class Camera;
std::list<Camera*> m_cameras;
std::list<Camera*>::iterator m_camera_iter;
GridType * m_grid;
void Attach(Camera* c) { m_cameras.push_back(c); }
void Detach(Camera* c)
{
if (m_camera_iter != m_cameras.end() && *m_camera_iter == c) // detach called during the loop
m_camera_iter = m_cameras.erase(m_camera_iter);
else
m_cameras.remove(c);
}
void CameraCall(void (Camera::*handler)())
{
if (!m_cameras.empty())
for(m_camera_iter = m_cameras.begin(); m_camera_iter!=m_cameras.end(); ++m_camera_iter)
((*m_camera_iter)->*handler)();
}
public:
ViewPoint() : m_grid(0), m_camera_iter(m_cameras.end()) {}
~ViewPoint();
// these events are called when viewpoint changes visibility state
void Event_AddedToWorld(GridType *grid)
{
m_grid = grid;
CameraCall(&Camera::Event_AddedToWorld);
}
void Event_RemovedFromWorld()
{
m_grid = NULL;
CameraCall(&Camera::Event_RemovedFromWorld);
}
void Event_GridChanged(GridType *grid)
{
m_grid = grid;
CameraCall(&Camera::Event_Moved);
}
void Event_ViewPointVisibilityChanged()
{
CameraCall(&Camera::Event_ViewPointVisibilityChanged);
}
void Call_UpdateVisibilityForOwner()
{
CameraCall(&Camera::UpdateVisibilityForOwner);
}
};
#endif

View file

@ -574,7 +574,7 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
MaNGOS::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit); MaNGOS::EmoteChatBuilder emote_builder(*GetPlayer(), text_emote, emoteNum, unit);
MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > emote_do(emote_builder); MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > emote_do(emote_builder);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), emote_do); MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::EmoteChatBuilder > > emote_worker(GetPlayer(), sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE), emote_do);
Cell::VisitWorldObjects(GetPlayer(), emote_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE)); Cell::VisitWorldObjects(GetPlayer(), emote_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_TEXTEMOTE));
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);

View file

@ -50,7 +50,10 @@ void DynamicObject::RemoveFromWorld()
{ {
///- Remove the dynamicObject from the accessor ///- Remove the dynamicObject from the accessor
if(IsInWorld()) if(IsInWorld())
{
GetMap()->GetObjectsStore().erase<DynamicObject>(GetGUID(), (DynamicObject*)NULL); GetMap()->GetObjectsStore().erase<DynamicObject>(GetGUID(), (DynamicObject*)NULL);
GetViewPoint().Event_RemovedFromWorld();
}
Object::RemoveFromWorld(); Object::RemoveFromWorld();
} }

View file

@ -31,6 +31,7 @@ class DynamicObject;
class GameObject; class GameObject;
class Pet; class Pet;
class Player; class Player;
class Camera;
#define MAX_NUMBER_OF_GRIDS 64 #define MAX_NUMBER_OF_GRIDS 64
@ -56,10 +57,12 @@ class Player;
#define MAP_HALFSIZE (MAP_SIZE/2) #define MAP_HALFSIZE (MAP_SIZE/2)
// Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case) // Creature used instead pet to simplify *::Visit templates (not required duplicate code for Creature->Pet case)
typedef TYPELIST_3(Player, Creature/*pets*/, Corpse/*resurrectable*/) AllWorldObjectTypes; // Cameras in world list just because linked with Player objects
typedef TYPELIST_4(Player, Creature/*pets*/, Corpse/*resurrectable*/, Camera) AllWorldObjectTypes;
typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes; typedef TYPELIST_4(GameObject, Creature/*except pets*/, DynamicObject, Corpse/*Bones*/) AllGridObjectTypes;
typedef TYPELIST_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes; typedef TYPELIST_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes;
typedef GridRefManager<Camera> CameraMapType;
typedef GridRefManager<Corpse> CorpseMapType; typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType; typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType; typedef GridRefManager<DynamicObject> DynamicObjectMapType;

View file

@ -28,32 +28,29 @@
using namespace MaNGOS; using namespace MaNGOS;
void void
VisibleChangesNotifier::Visit(PlayerMapType &m) VisibleChangesNotifier::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{ {
Player* player = iter->getSource(); iter->getSource()->UpdateVisibilityOf(&i_object);
if(player == &i_object)
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
} }
} }
void void
VisibleNotifier::Notify() VisibleNotifier::Notify()
{ {
Player& player = *i_camera.GetOwner();
// at this moment i_clientGUIDs have guids that not iterate at grid level checks // at this moment i_clientGUIDs have guids that not iterate at grid level checks
// but exist one case when this possible and object not out of range: transports // but exist one case when this possible and object not out of range: transports
if(Transport* transport = i_player.GetTransport()) if(Transport* transport = player.GetTransport())
{ {
for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr) for(Transport::PlayerSet::const_iterator itr = transport->GetPassengers().begin();itr!=transport->GetPassengers().end();++itr)
{ {
if(i_clientGUIDs.find((*itr)->GetGUID())!=i_clientGUIDs.end()) if (i_clientGUIDs.find((*itr)->GetGUID()) != i_clientGUIDs.end())
{ {
// ignore far sight case // ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player); (*itr)->UpdateVisibilityOf(*itr, &player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_visibleNow); player.UpdateVisibilityOf(&player, *itr, i_data, i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID()); i_clientGUIDs.erase((*itr)->GetGUID());
} }
} }
@ -63,27 +60,28 @@ VisibleNotifier::Notify()
i_data.AddOutOfRangeGUID(i_clientGUIDs); i_data.AddOutOfRangeGUID(i_clientGUIDs);
for(ObjectGuidSet::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr) for(ObjectGuidSet::iterator itr = i_clientGUIDs.begin();itr!=i_clientGUIDs.end();++itr)
{ {
i_player.m_clientGUIDs.erase(*itr); player.m_clientGUIDs.erase(*itr);
DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "%s is out of range (no in active cells set) now for player %u",itr->GetString().c_str(),i_player.GetGUIDLow()); DEBUG_FILTER_LOG(LOG_FILTER_VISIBILITY_CHANGES, "%s is out of range (no in active cells set) now for %s",
itr->GetString().c_str(), player.GetObjectGuid().GetString().c_str());
} }
if( i_data.HasData() ) if (i_data.HasData())
{ {
// send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer) // send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
WorldPacket packet; WorldPacket packet;
i_data.BuildPacket(&packet); i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet); player.GetSession()->SendPacket(&packet);
// send out of range to other players if need // send out of range to other players if need
ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs(); ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs();
for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter) for(ObjectGuidSet::const_iterator iter = oor.begin(); iter != oor.end(); ++iter)
{ {
if(!iter->IsPlayer()) if (!iter->IsPlayer())
continue; continue;
if (Player* plr = ObjectAccessor::FindPlayer(*iter)) if (Player* plr = ObjectAccessor::FindPlayer(*iter))
plr->UpdateVisibilityOf(plr->GetViewPoint(),&i_player); plr->UpdateVisibilityOf(plr->GetCamera().GetBody(), &player);
} }
} }
@ -93,87 +91,92 @@ VisibleNotifier::Notify()
for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr) for(std::set<WorldObject*>::const_iterator vItr = i_visibleNow.begin(); vItr != i_visibleNow.end(); ++vItr)
{ {
// target aura duration for caster show only if target exist at caster client // target aura duration for caster show only if target exist at caster client
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT)) if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
i_player.SendAurasForTarget((Unit*)(*vItr)); player.SendAurasForTarget((Unit*)(*vItr));
// non finished movements show to player // non finished movements show to player
if((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive()) if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player); ((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&player);
} }
} }
void void
MessageDeliverer::Visit(PlayerMapType &m) MessageDeliverer::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{ {
if (i_toSelf || iter->getSource() != &i_player) Player* owner = iter->getSource()->GetOwner();
if (i_toSelf || owner != &i_player)
{ {
if (!i_player.InSamePhase(iter->getSource())) if (!i_player.InSamePhase(iter->getSource()->GetBody()))
continue; continue;
if(WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
} }
void MessageDelivererExcept::Visit(PlayerMapType &m) void MessageDelivererExcept::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator it = m.begin(); it!= m.end(); ++it) for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{ {
Player* player = it->getSource(); Player* owner = iter->getSource()->GetOwner();
if(!player->InSamePhase(i_phaseMask) || player == i_skipped_receiver)
if (!owner->InSamePhase(i_phaseMask) || owner == i_skipped_receiver)
continue; continue;
if (WorldSession* session = player->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
void void
ObjectMessageDeliverer::Visit(PlayerMapType &m) ObjectMessageDeliverer::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{ {
if(!iter->getSource()->InSamePhase(i_phaseMask)) if(!iter->getSource()->GetBody()->InSamePhase(i_phaseMask))
continue; continue;
if(WorldSession* session = iter->getSource()->GetSession()) if(WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
void void
MessageDistDeliverer::Visit(PlayerMapType &m) MessageDistDeliverer::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{ {
if ((i_toSelf || iter->getSource() != &i_player ) && Player * owner = iter->getSource()->GetOwner();
(!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) &&
(!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist))) if ((i_toSelf || owner != &i_player) &&
(!i_ownTeamOnly || owner->GetTeam() == i_player.GetTeam()) &&
(!i_dist || iter->getSource()->GetBody()->IsWithinDist(&i_player,i_dist)))
{ {
if (!i_player.InSamePhase(iter->getSource())) if (!i_player.InSamePhase(iter->getSource()->GetBody()))
continue; continue;
if (WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }
} }
void void
ObjectMessageDistDeliverer::Visit(PlayerMapType &m) ObjectMessageDistDeliverer::Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(CameraMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
{ {
if (!i_dist || iter->getSource()->IsWithinDist(&i_object,i_dist)) if (!i_dist || iter->getSource()->GetBody()->IsWithinDist(&i_object,i_dist))
{ {
if (!i_object.InSamePhase(iter->getSource())) if (!i_object.InSamePhase(iter->getSource()->GetBody()))
continue; continue;
if (WorldSession* session = iter->getSource()->GetSession()) if (WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message); session->SendPacket(i_message);
} }
} }

View file

@ -38,13 +38,14 @@ namespace MaNGOS
{ {
struct MANGOS_DLL_DECL VisibleNotifier struct MANGOS_DLL_DECL VisibleNotifier
{ {
Player &i_player; Camera& i_camera;
UpdateData i_data; UpdateData i_data;
ObjectGuidSet i_clientGUIDs; ObjectGuidSet i_clientGUIDs;
std::set<WorldObject*> i_visibleNow; std::set<WorldObject*> i_visibleNow;
explicit VisibleNotifier(Player &player) : i_player(player),i_clientGUIDs(player.m_clientGUIDs) {} explicit VisibleNotifier(Camera &c) : i_camera(c), i_clientGUIDs(c.GetOwner()->m_clientGUIDs) {}
template<class T> void Visit(GridRefManager<T> &m); template<class T> void Visit(GridRefManager<T> &m);
void Visit(CameraMapType &m) {}
void Notify(void); void Notify(void);
}; };
@ -54,7 +55,7 @@ namespace MaNGOS
explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {} explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {}
template<class T> void Visit(GridRefManager<T> &) {} template<class T> void Visit(GridRefManager<T> &) {}
void Visit(PlayerMapType &); void Visit(CameraMapType &);
}; };
struct MANGOS_DLL_DECL GridUpdater struct MANGOS_DLL_DECL GridUpdater
@ -82,7 +83,7 @@ namespace MaNGOS
WorldPacket *i_message; WorldPacket *i_message;
bool i_toSelf; bool i_toSelf;
MessageDeliverer(Player &pl, WorldPacket *msg, bool to_self) : i_player(pl), i_message(msg), i_toSelf(to_self) {} MessageDeliverer(Player &pl, WorldPacket *msg, bool to_self) : i_player(pl), i_message(msg), i_toSelf(to_self) {}
void Visit(PlayerMapType &m); void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
}; };
@ -95,7 +96,7 @@ namespace MaNGOS
MessageDelivererExcept(WorldObject const* obj, WorldPacket *msg, Player const* skipped) MessageDelivererExcept(WorldObject const* obj, WorldPacket *msg, Player const* skipped)
: i_phaseMask(obj->GetPhaseMask()), i_message(msg), i_skipped_receiver(skipped) {} : i_phaseMask(obj->GetPhaseMask()), i_message(msg), i_skipped_receiver(skipped) {}
void Visit(PlayerMapType &m); void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
}; };
@ -105,7 +106,7 @@ namespace MaNGOS
WorldPacket *i_message; WorldPacket *i_message;
explicit ObjectMessageDeliverer(WorldObject& obj, WorldPacket *msg) explicit ObjectMessageDeliverer(WorldObject& obj, WorldPacket *msg)
: i_phaseMask(obj.GetPhaseMask()), i_message(msg) {} : i_phaseMask(obj.GetPhaseMask()), i_message(msg) {}
void Visit(PlayerMapType &m); void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
}; };
@ -119,7 +120,7 @@ namespace MaNGOS
MessageDistDeliverer(Player &pl, WorldPacket *msg, float dist, bool to_self, bool ownTeamOnly) MessageDistDeliverer(Player &pl, WorldPacket *msg, float dist, bool to_self, bool ownTeamOnly)
: i_player(pl), i_message(msg), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly), i_dist(dist) {} : i_player(pl), i_message(msg), i_toSelf(to_self), i_ownTeamOnly(ownTeamOnly), i_dist(dist) {}
void Visit(PlayerMapType &m); void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
}; };
@ -129,7 +130,7 @@ namespace MaNGOS
WorldPacket *i_message; WorldPacket *i_message;
float i_dist; float i_dist;
ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, float dist) : i_object(obj), i_message(msg), i_dist(dist) {} ObjectMessageDistDeliverer(WorldObject &obj, WorldPacket *msg, float dist) : i_object(obj), i_message(msg), i_dist(dist) {}
void Visit(PlayerMapType &m); void Visit(CameraMapType &m);
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}
}; };
@ -140,6 +141,7 @@ namespace MaNGOS
template<class T> void Visit(GridRefManager<T> &m); template<class T> void Visit(GridRefManager<T> &m);
void Visit(PlayerMapType &) {} void Visit(PlayerMapType &) {}
void Visit(CorpseMapType &) {} void Visit(CorpseMapType &) {}
void Visit(CameraMapType &) {}
void Visit(CreatureMapType &); void Visit(CreatureMapType &);
}; };
@ -476,22 +478,21 @@ namespace MaNGOS
}; };
template<class Do> template<class Do>
struct MANGOS_DLL_DECL PlayerDistWorker struct MANGOS_DLL_DECL CameraDistWorker
{ {
WorldObject const* i_searcher; WorldObject const* i_searcher;
float i_dist; float i_dist;
Do& i_do; Do& i_do;
PlayerDistWorker(WorldObject const* searcher, float _dist, Do& _do) CameraDistWorker(WorldObject const* searcher, float _dist, Do& _do)
: i_searcher(searcher), i_dist(_dist), i_do(_do) {} : i_searcher(searcher), i_dist(_dist), i_do(_do) {}
void Visit(PlayerMapType &m) void Visit(CameraMapType &m)
{ {
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr) for(CameraMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist)) if (itr->getSource()->GetBody()->InSamePhase(i_searcher) && itr->getSource()->GetBody()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource()); i_do(itr->getSource()->GetOwner());
} }
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {} template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
}; };

View file

@ -31,11 +31,9 @@
template<class T> template<class T>
inline void MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m) inline void MaNGOS::VisibleNotifier::Visit(GridRefManager<T> &m)
{ {
WorldObject const* viewPoint = i_player.GetViewPoint();
for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter) for(typename GridRefManager<T>::iterator iter = m.begin(); iter != m.end(); ++iter)
{ {
i_player.UpdateVisibilityOf(viewPoint,iter->getSource(), i_data, i_visibleNow); i_camera.UpdateVisibilityOf(iter->getSource(), i_data, i_visibleNow);
i_clientGUIDs.erase(iter->getSource()->GetGUID()); i_clientGUIDs.erase(iter->getSource()->GetGUID());
} }
} }
@ -96,7 +94,7 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
if (!i_player.isAlive() || i_player.isInFlight()) if (!i_player.isAlive() || i_player.isInFlight())
return; return;
WorldObject const* viewPoint = i_player.GetViewPoint(); WorldObject const* viewPoint = i_player.GetCamera().GetBody();
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
if (iter->getSource()->isAlive()) if (iter->getSource()->isAlive())
@ -106,13 +104,13 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
template<> template<>
inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m) inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
{ {
if(!i_creature.isAlive()) if (!i_creature.isAlive())
return; return;
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter) for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
if (Player* player = iter->getSource()) if (Player* player = iter->getSource())
if (player->isAlive() && !player->isInFlight()) if (player->isAlive() && !player->isInFlight())
PlayerCreatureRelocationWorker(player, player->GetViewPoint(), &i_creature); PlayerCreatureRelocationWorker(player, player->GetCamera().GetBody(), &i_creature);
} }
template<> template<>

View file

@ -76,6 +76,8 @@ libmangosgame_a_SOURCES = \
Calendar.cpp \ Calendar.cpp \
Calendar.h \ Calendar.h \
CalendarHandler.cpp \ CalendarHandler.cpp \
Camera.cpp \
Camera.h \
Cell.h \ Cell.h \
CellImpl.h \ CellImpl.h \
Channel.cpp \ Channel.cpp \

View file

@ -367,8 +367,9 @@ bool Map::Add(Player *player)
SendInitSelf(player); SendInitSelf(player);
SendInitTransports(player); SendInitTransports(player);
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
player->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(player,cell,p); UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
AddNotifier(player,cell,p); AddNotifier(player,cell,p);
return true; return true;
@ -406,6 +407,7 @@ Map::Add(T *obj)
DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY()); DEBUG_LOG("Object %u enters grid[%u,%u]", GUID_LOPART(obj->GetGUID()), cell.GridX(), cell.GridY());
obj->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(obj,cell,p); UpdateObjectVisibility(obj,cell,p);
AddNotifier(obj,cell,p); AddNotifier(obj,cell,p);
@ -682,7 +684,6 @@ void Map::Remove(Player *player, bool remove)
SendRemoveTransports(player); SendRemoveTransports(player);
UpdateObjectVisibility(player,cell,p); UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
player->ResetMap(); player->ResetMap();
if( remove ) if( remove )
@ -716,10 +717,9 @@ Map::Remove(T *obj, bool remove)
else else
obj->RemoveFromWorld(); obj->RemoveFromWorld();
UpdateObjectVisibility(obj,cell,p); // i think will be better to call this function while object still in grid, this changes nothing but logically is better(as for me)
RemoveFromGrid(obj,grid,cell); RemoveFromGrid(obj,grid,cell);
UpdateObjectVisibility(obj,cell,p);
obj->ResetMap(); obj->ResetMap();
if( remove ) if( remove )
{ {
@ -759,10 +759,13 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
AddToGrid(player, oldGrid,new_cell); AddToGrid(player, oldGrid,new_cell);
else else
EnsureGridLoadedAtEnter(new_cell, player); EnsureGridLoadedAtEnter(new_cell, player);
NGridType* newGrid = getNGrid(new_cell.GridX(), new_cell.GridY());
player->GetViewPoint().Event_GridChanged(&(*newGrid)(new_cell.CellX(),new_cell.CellY()));
} }
player->GetViewPoint().Call_UpdateVisibilityForOwner();
// if move then update what player see and who seen // if move then update what player see and who seen
UpdateObjectsVisibilityFor(player,new_cell,new_val);
UpdateObjectVisibility(player, new_cell, new_val); UpdateObjectVisibility(player, new_cell, new_val);
PlayerRelocationNotify(player,new_cell,new_val); PlayerRelocationNotify(player,new_cell,new_val);
@ -816,6 +819,7 @@ Map::CreatureRelocation(Creature *creature, float x, float y, float z, float ang
creature->SetNeedNotify(); creature->SetNeedNotify();
} }
creature->GetViewPoint().Call_UpdateVisibilityForOwner();
ASSERT(CheckGridIntegrity(creature,true)); ASSERT(CheckGridIntegrity(creature,true));
} }
@ -829,12 +833,12 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
{ {
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY()); DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Creature (GUID: %u Entry: %u) moved in grid[%u,%u] from cell[%u,%u] to cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.CellX(), new_cell.CellY());
if( !old_cell.DiffGrid(new_cell) ) RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
{
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); AddToGrid(c,new_grid,new_cell);
c->SetCurrentCell(new_cell);
} c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
} }
else else
{ {
@ -852,7 +856,10 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY()); DEBUG_FILTER_LOG(LOG_FILTER_CREATURE_MOVES, "Active creature (GUID: %u Entry: %u) moved from grid[%u,%u]cell[%u,%u] to grid[%u,%u]cell[%u,%u].", c->GetGUIDLow(), c->GetEntry(), old_cell.GridX(), old_cell.GridY(), old_cell.CellX(), old_cell.CellY(), new_cell.GridX(), new_cell.GridY(), new_cell.CellX(), new_cell.CellY());
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,new_grid,new_cell);
c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
return true; return true;
} }
@ -865,7 +872,9 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell); RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
{ {
EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY())); EnsureGridCreated(GridPair(new_cell.GridX(), new_cell.GridY()));
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell); NGridType* new_grid = getNGrid(new_cell.GridX(), new_cell.GridY());
AddToGrid(c,new_grid,new_cell);
c->GetViewPoint().Event_GridChanged( &(*new_grid)(new_cell.CellX(),new_cell.CellY()) );
} }
return true; return true;
@ -1420,21 +1429,6 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance()); cell.Visit(cellpair, player_notifier, *this, *obj, GetVisibilityDistance());
} }
void Map::UpdateObjectsVisibilityFor( Player* player, Cell cell, CellPair cellpair )
{
MaNGOS::VisibleNotifier notifier(*player);
cell.data.Part.reserved = ALL_DISTRICT;
//cell.SetNoCreate(); need trigger cell loading around the player
TypeContainerVisitor<MaNGOS::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<MaNGOS::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier);
cell.Visit(cellpair, world_notifier, *this, *player, GetVisibilityDistance());
cell.Visit(cellpair, grid_notifier, *this, *player, GetVisibilityDistance());
// send data
notifier.Notify();
}
void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair ) void Map::PlayerRelocationNotify( Player* player, Cell cell, CellPair cellpair )
{ {
MaNGOS::PlayerRelocationNotifier relocationNotifier(*player); MaNGOS::PlayerRelocationNotifier relocationNotifier(*player);

View file

@ -84,6 +84,8 @@ enum LevelRequirementVsMode
class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex> class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::ObjectLevelLockable<Map, ACE_Thread_Mutex>
{ {
friend class MapReference; friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
public: public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL); Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
virtual ~Map(); virtual ~Map();
@ -211,7 +213,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void AddObjectToRemoveList(WorldObject *obj); void AddObjectToRemoveList(WorldObject *obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair); void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); } void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); } bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }

View file

@ -397,11 +397,17 @@ void WorldSession::SendSpiritResurrect()
_player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation()); _player->TeleportTo(corpseGrave->map_id, corpseGrave->x, corpseGrave->y, corpseGrave->z, _player->GetOrientation());
// or update at original position // or update at original position
else else
_player->UpdateVisibilityForPlayer(); {
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
} }
// or update at original position // or update at original position
else else
_player->UpdateVisibilityForPlayer(); {
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
} }
void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data ) void WorldSession::HandleBinderActivateOpcode( WorldPacket & recv_data )

View file

@ -1496,7 +1496,7 @@ void WorldObject::MonsterSay(int32 textId, uint32 language, uint64 TargetGuid)
{ {
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid); MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_SAY, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build); MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do); MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY),say_do);
Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY)); Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_SAY));
} }
@ -1507,7 +1507,7 @@ void WorldObject::MonsterYell(int32 textId, uint32 language, uint64 TargetGuid)
MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid); MaNGOS::MonsterChatBuilder say_build(*this, CHAT_MSG_MONSTER_YELL, textId,language,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build); MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do); MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL)); Cell::VisitWorldObjects(this, say_worker, sWorld.getConfig(CONFIG_FLOAT_LISTEN_RANGE_YELL));
} }
@ -1530,7 +1530,7 @@ void WorldObject::MonsterTextEmote(int32 textId, uint64 TargetGuid, bool IsBossE
MaNGOS::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid); MaNGOS::MonsterChatBuilder say_build(*this, IsBossEmote ? CHAT_MSG_RAID_BOSS_EMOTE : CHAT_MSG_MONSTER_EMOTE, textId,LANG_UNIVERSAL,TargetGuid);
MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build); MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> say_do(say_build);
MaNGOS::PlayerDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do); MaNGOS::CameraDistWorker<MaNGOS::LocalizedPacketDo<MaNGOS::MonsterChatBuilder> > say_worker(this,range,say_do);
Cell::VisitWorldObjects(this, say_worker, range); Cell::VisitWorldObjects(this, say_worker, range);
} }
@ -1864,7 +1864,10 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask; m_phaseMask = newPhaseMask;
if(update && IsInWorld()) if(update && IsInWorld())
{
UpdateObjectVisibility(); UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
} }
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ ) void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1910,12 +1913,22 @@ struct WorldObjectChangeAccumulator
{ {
UpdateDataMapType &i_updateDatas; UpdateDataMapType &i_updateDatas;
WorldObject &i_object; WorldObject &i_object;
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {} WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj)
void Visit(PlayerMapType &m)
{ {
for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter) // send self fields changes in another way, otherwise
if(iter->getSource()->HaveAtClient(&i_object)) // with new camera system when player's camera too far from player, camera wouldn't receive packets and changes from player
i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas); if(i_object.isType(TYPEMASK_PLAYER))
i_object.BuildUpdateDataForPlayer((Player*)&i_object, i_updateDatas);
}
void Visit(CameraMapType &m)
{
for(CameraMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
{
Player* owner = iter->getSource()->GetOwner();
if(owner != &i_object && owner->HaveAtClient(&i_object))
i_object.BuildUpdateDataForPlayer(owner, i_updateDatas);
}
} }
template<class SKIP> void Visit(GridRefManager<SKIP> &) {} template<class SKIP> void Visit(GridRefManager<SKIP> &) {}

View file

@ -23,8 +23,8 @@
#include "ByteBuffer.h" #include "ByteBuffer.h"
#include "UpdateFields.h" #include "UpdateFields.h"
#include "UpdateData.h" #include "UpdateData.h"
#include "GameSystem/GridReference.h"
#include "ObjectGuid.h" #include "ObjectGuid.h"
#include "Camera.h"
#include <set> #include <set>
#include <string> #include <string>
@ -476,6 +476,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void BuildUpdateData(UpdateDataMapType &); void BuildUpdateData(UpdateDataMapType &);
Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime); Creature* SummonCreature(uint32 id, float x, float y, float z, float ang,TempSummonType spwtype,uint32 despwtime);
ViewPoint& GetViewPoint() { return m_viewPoint; }
protected: protected:
explicit WorldObject(); explicit WorldObject();
@ -498,6 +500,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
float m_positionY; float m_positionY;
float m_positionZ; float m_positionZ;
float m_orientation; float m_orientation;
ViewPoint m_viewPoint;
}; };
#endif #endif

View file

@ -25,6 +25,7 @@
#include "Corpse.h" #include "Corpse.h"
#include "World.h" #include "World.h"
#include "CellImpl.h" #include "CellImpl.h"
#include "GridDefines.h"
class MANGOS_DLL_DECL ObjectGridRespawnMover class MANGOS_DLL_DECL ObjectGridRespawnMover
{ {
@ -105,7 +106,7 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair)
} }
template <class T> template <class T>
void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map) void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &m, uint32 &count, Map* map, GridType& grid)
{ {
BattleGround* bg = map->IsBattleGroundOrArena() ? ((BattleGroundMap*)map)->GetBG() : NULL; BattleGround* bg = map->IsBattleGroundOrArena() ? ((BattleGroundMap*)map)->GetBG() : NULL;
@ -121,13 +122,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
continue; continue;
} }
obj->GetGridRef().link(&m, obj); grid.AddGridObject(obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map); obj->SetMap(map);
obj->AddToWorld(); obj->AddToWorld();
if(obj->isActiveObject()) if(obj->isActiveObject())
map->AddToActive(obj); map->AddToActive(obj);
obj->GetViewPoint().Event_AddedToWorld(&grid);
if (bg) if (bg)
bg->OnObjectDBLoad(obj); bg->OnObjectDBLoad(obj);
@ -135,7 +139,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
} }
} }
void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map) void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType &m, uint32 &count, Map* map, GridType& grid)
{ {
if(cell_corpses.empty()) if(cell_corpses.empty())
return; return;
@ -151,7 +155,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
if(!obj) if(!obj)
continue; continue;
obj->GetGridRef().link(&m, obj); grid.AddWorldObject(obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map); obj->SetMap(map);
@ -173,7 +177,8 @@ ObjectGridLoader::Visit(GameObjectMapType &m)
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map); GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.gameobjects, cell_pair, m, i_gameObjects, i_map, grid);
} }
void void
@ -186,7 +191,8 @@ ObjectGridLoader::Visit(CreatureMapType &m)
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id); CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), i_map->GetSpawnMode(), cell_id);
LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map); GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.creatures, cell_pair, m, i_creatures, i_map, grid);
} }
void void
@ -199,7 +205,8 @@ ObjectWorldLoader::Visit(CorpseMapType &m)
// corpses are always added to spawn mode 0 and they are spawned by their instance id // corpses are always added to spawn mode 0 and they are spawned by their instance id
CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id); CellObjectGuids const& cell_guids = sObjectMgr.GetCellObjectGuids(i_map->GetId(), 0, cell_id);
LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map); GridType& grid = (*i_map->getNGrid(i_cell.GridX(),i_cell.GridY())) (i_cell.CellX(),i_cell.CellY());
LoadHelper(cell_guids.corpses, cell_pair, m, i_corpses, i_map, grid);
} }
void void

View file

@ -405,7 +405,7 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
UpdateMask Player::updateVisualBits; UpdateMask Player::updateVisualBits;
Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this) Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputationMgr(this), m_camera(this)
{ {
m_transport = 0; m_transport = 0;
@ -2409,7 +2409,8 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(true); getHostileRefManager().setOnlineOfflineState(true);
} }
UpdateVisibilityForPlayer(); m_camera.UpdateVisibilityForOwner();
UpdateObjectVisibility();
} }
void Player::SetGMVisible(bool on) void Player::SetGMVisible(bool on)
@ -4490,8 +4491,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
GetZoneAndAreaId(newzone,newarea); GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea); UpdateZone(newzone,newarea);
// update visibility // update visibility of world around viewpoint
UpdateVisibilityForPlayer(); m_camera.UpdateVisibilityForOwner();
// update visibility of player for nearby cameras
UpdateObjectVisibility();
if(!applySickness) if(!applySickness)
return; return;
@ -6073,42 +6076,30 @@ void Player::SaveRecallPosition()
void Player::SendMessageToSet(WorldPacket *data, bool self) void Player::SendMessageToSet(WorldPacket *data, bool self)
{ {
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()); if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
if(_map) _map->MessageBroadcast(this, data, false);
{
_map->MessageBroadcast(this, data, self);
return;
}
//if player is not in world and map in not created/already destroyed //if player is not in world and map in not created/already destroyed
//no need to create one, just send packet for itself! //no need to create one, just send packet for itself!
if(self) if (self)
GetSession()->SendPacket(data); GetSession()->SendPacket(data);
} }
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self) void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self)
{ {
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()); if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
if(_map) _map->MessageDistBroadcast(this, data, dist, false);
{
_map->MessageDistBroadcast(this, data, dist, self);
return;
}
if(self) if (self)
GetSession()->SendPacket(data); GetSession()->SendPacket(data);
} }
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only) void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only)
{ {
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()); if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
if(_map) _map->MessageDistBroadcast(this, data, dist, false, own_team_only);
{
_map->MessageDistBroadcast(this, data, dist, self, own_team_only);
return;
}
if(self) if (self)
GetSession()->SendPacket(data); GetSession()->SendPacket(data);
} }
@ -15322,7 +15313,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
SetCreatorGUID(0); SetCreatorGUID(0);
// reset some aura modifiers before aura apply // reset some aura modifiers before aura apply
SetFarSightGUID(0);
SetUInt64Value(PLAYER_FARSIGHT, 0);
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 ); SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 ); SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
@ -18058,7 +18050,7 @@ void Player::HandleStealthedUnitsDetection()
MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck > searcher(this,stealthedUnits, u_check); MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck > searcher(this,stealthedUnits, u_check);
Cell::VisitAllObjects(this, searcher, MAX_PLAYER_STEALTH_DETECT_RANGE); Cell::VisitAllObjects(this, searcher, MAX_PLAYER_STEALTH_DETECT_RANGE);
WorldObject const* viewPoint = GetViewPoint(); WorldObject const* viewPoint = GetCamera().GetBody();
for (std::list<Unit*>::const_iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i) for (std::list<Unit*>::const_iterator i = stealthedUnits.begin(); i != stealthedUnits.end(); ++i)
{ {
@ -19154,17 +19146,6 @@ void Player::ReportedAfkBy(Player* reporter)
} }
} }
WorldObject const* Player::GetViewPoint() const
{
if(uint64 far_sight = GetFarSight())
{
WorldObject const* viewPoint = GetMap()->GetWorldObject(far_sight);
return viewPoint ? viewPoint : this; // always expected not NULL
}
else
return this;
}
bool Player::IsVisibleInGridForPlayer( Player* pl ) const bool Player::IsVisibleInGridForPlayer( Player* pl ) const
{ {
// gamemaster in GM mode see all, including ghosts // gamemaster in GM mode see all, including ghosts
@ -20736,7 +20717,7 @@ void Player::EnterVehicle(Vehicle *vehicle)
vehicle->setFaction(getFaction()); vehicle->setFaction(getFaction());
SetCharm(vehicle); // charm SetCharm(vehicle); // charm
SetFarSightGUID(vehicle->GetGUID()); // set view m_camera.SetView(vehicle); // set view
SetClientControl(vehicle, 1); // redirect controls to vehicle SetClientControl(vehicle, 1); // redirect controls to vehicle
SetMover(vehicle); SetMover(vehicle);
@ -20788,7 +20769,7 @@ void Player::ExitVehicle(Vehicle *vehicle)
vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H); vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
SetCharm(NULL); SetCharm(NULL);
SetFarSightGUID(0); m_camera.ResetView();
SetClientControl(vehicle, 0); SetClientControl(vehicle, 0);
SetMover(NULL); SetMover(NULL);
@ -22022,38 +22003,6 @@ bool Player::HasMovementFlag( MovementFlags f ) const
return m_movementInfo.HasMovementFlag(f); return m_movementInfo.HasMovementFlag(f);
} }
void Player::SetFarSightGUID( uint64 guid )
{
if(GetFarSight() == guid)
return;
SetUInt64Value(PLAYER_FARSIGHT, guid);
// need triggering load grids around new view point
UpdateVisibilityForPlayer();
}
void Player::UpdateVisibilityForPlayer()
{
WorldObject const* viewPoint = GetViewPoint();
Map* m = GetMap();
CellPair p(MaNGOS::ComputeCellPair(GetPositionX(), GetPositionY()));
Cell cell(p);
m->UpdateObjectVisibility(this, cell, p);
if (this != viewPoint)
{
CellPair pView(MaNGOS::ComputeCellPair(viewPoint->GetPositionX(), viewPoint->GetPositionY()));
Cell cellView(pView);
m->UpdateObjectsVisibilityFor(this, cellView, pView);
}
else
m->UpdateObjectsVisibilityFor(this, cell, p);
}
void Player::ResetTimeSync() void Player::ResetTimeSync()
{ {
m_timeSyncCounter = 0; m_timeSyncCounter = 0;

View file

@ -1128,8 +1128,6 @@ class MANGOS_DLL_SPEC Player : public Unit
Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask); Creature* GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask);
GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const; GameObject* GetGameObjectIfCanInteractWith(ObjectGuid guid, uint32 gameobject_type = MAX_GAMEOBJECT_TYPE) const;
void UpdateVisibilityForPlayer();
bool ToggleAFK(); bool ToggleAFK();
bool ToggleDND(); bool ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); } bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }
@ -2250,7 +2248,6 @@ class MANGOS_DLL_SPEC Player : public Unit
bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); } bool HaveAtClient(WorldObject const* u) { return u==this || m_clientGUIDs.find(u->GetGUID())!=m_clientGUIDs.end(); }
WorldObject const* GetViewPoint() const;
bool IsVisibleInGridForPlayer(Player* pl) const; bool IsVisibleInGridForPlayer(Player* pl) const;
bool IsVisibleGloballyFor(Player* pl) const; bool IsVisibleGloballyFor(Player* pl) const;
@ -2262,6 +2259,8 @@ class MANGOS_DLL_SPEC Player : public Unit
// Stealth detection system // Stealth detection system
void HandleStealthedUnitsDetection(); void HandleStealthedUnitsDetection();
Camera& GetCamera() { return m_camera; }
uint8 m_forced_speed_changes[MAX_MOVE_TYPE]; uint8 m_forced_speed_changes[MAX_MOVE_TYPE];
bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; } bool HasAtLoginFlag(AtLoginFlags f) const { return m_atLoginFlags & f; }
@ -2603,6 +2602,8 @@ class MANGOS_DLL_SPEC Player : public Unit
m_DelayedOperations |= operation; m_DelayedOperations |= operation;
} }
Camera m_camera;
GridReference<Player> m_gridRef; GridReference<Player> m_gridRef;
MapReference m_mapRef; MapReference m_mapRef;

View file

@ -808,6 +808,7 @@ namespace MaNGOS
template<> inline void Visit(CorpseMapType & ) {} template<> inline void Visit(CorpseMapType & ) {}
template<> inline void Visit(GameObjectMapType & ) {} template<> inline void Visit(GameObjectMapType & ) {}
template<> inline void Visit(DynamicObjectMapType & ) {} template<> inline void Visit(DynamicObjectMapType & ) {}
template<> inline void Visit(CameraMapType & ) {}
#endif #endif
}; };
@ -815,6 +816,7 @@ namespace MaNGOS
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {} template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CameraMapType& ) {}
#endif #endif
} }

View file

@ -2380,7 +2380,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
(GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 1 || GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 128))) (GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 1 || GetSpellProto()->EffectApplyAuraName[EFFECT_INDEX_0] == 128)))
{ {
// spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425 // spells with SpellEffect=72 and aura=4: 6196, 6197, 21171, 21425
((Player*)target)->SetFarSightGUID(0); ((Player*)target)->GetCamera().ResetView();
WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0); WorldPacket data(SMSG_CLEAR_FAR_SIGHT_IMMEDIATE, 0);
((Player*)target)->GetSession()->SendPacket(&data); ((Player*)target)->GetSession()->SendPacket(&data);
return; return;
@ -3543,7 +3543,11 @@ void Aura::HandleBindSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; return;
((Player*)caster)->SetFarSightGUID(apply ? GetTarget()->GetGUID() : 0); Camera& camera = ((Player*)caster)->GetCamera();
if (apply)
camera.SetView(m_target);
else
camera.ResetView();
} }
void Aura::HandleFarSight(bool apply, bool /*Real*/) void Aura::HandleFarSight(bool apply, bool /*Real*/)
@ -3552,7 +3556,11 @@ void Aura::HandleFarSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER) if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
return; return;
((Player*)caster)->SetFarSightGUID(apply ? GetTarget()->GetGUID() : 0); Camera& camera = ((Player*)caster)->GetCamera();
if (apply)
camera.SetView(GetTarget());
else
camera.ResetView();
} }
void Aura::HandleAuraTrackCreatures(bool apply, bool /*Real*/) void Aura::HandleAuraTrackCreatures(bool apply, bool /*Real*/)
@ -3607,7 +3615,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
return; return;
Player* p_caster = (Player*)caster; Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if( apply ) if( apply )
{ {
@ -3618,7 +3626,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
p_caster->SetCharm(target); p_caster->SetCharm(target);
p_caster->SetFarSightGUID(target->GetGUID()); camera.SetView(target);
p_caster->SetClientControl(target, 1); p_caster->SetClientControl(target, 1);
p_caster->SetMover(target); p_caster->SetMover(target);
@ -3646,7 +3654,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now p_caster->InterruptSpell(CURRENT_CHANNELED_SPELL); // the spell is not automatically canceled when interrupted, do it now
p_caster->SetCharm(NULL); p_caster->SetCharm(NULL);
p_caster->SetFarSightGUID(0); camera.ResetView();
p_caster->SetClientControl(target, 0); p_caster->SetClientControl(target, 0);
p_caster->SetMover(NULL); p_caster->SetMover(NULL);
@ -3695,13 +3703,19 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
return; return;
Player* p_caster = (Player*)caster; Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if(apply) if(apply)
{
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
camera.SetView(pet);
}
else else
{
pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED); pet->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
camera.ResetView();
}
p_caster->SetFarSightGUID(apply ? pet->GetGUID() : 0);
p_caster->SetCharm(apply ? pet : NULL); p_caster->SetCharm(apply ? pet : NULL);
p_caster->SetClientControl(pet, apply ? 1 : 0); p_caster->SetClientControl(pet, apply ? 1 : 0);
((Player*)caster)->SetMover(apply ? pet : NULL); ((Player*)caster)->SetMover(apply ? pet : NULL);
@ -4182,7 +4196,7 @@ void Aura::HandleInvisibilityDetect(bool apply, bool Real)
target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue); target->m_detectInvisibilityMask |= (1 << m_modifier.m_miscvalue);
} }
if(Real && target->GetTypeId()==TYPEID_PLAYER) if(Real && target->GetTypeId()==TYPEID_PLAYER)
((Player*)target)->UpdateVisibilityForPlayer(); ((Player*)target)->GetCamera().UpdateVisibilityForOwner();
} }
void Aura::HandleAuraModRoot(bool apply, bool Real) void Aura::HandleAuraModRoot(bool apply, bool Real)

View file

@ -4244,7 +4244,8 @@ void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002); dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
m_caster->AddDynObject(dynObj); m_caster->AddDynObject(dynObj);
m_caster->GetMap()->Add(dynObj); m_caster->GetMap()->Add(dynObj);
((Player*)m_caster)->SetFarSightGUID(dynObj->GetGUID());
((Player*)m_caster)->GetCamera().SetView(dynObj);
} }
void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction) void Spell::DoSummonWild(SpellEffectIndex eff_idx, uint32 forceFaction)

View file

@ -10579,10 +10579,6 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return false; return false;
} }
// always seen by far sight caster
if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true;
// different visible distance checks // different visible distance checks
if (u->isInFlight()) // what see player in flight if (u->isInFlight()) // what see player in flight
{ {
@ -10781,12 +10777,41 @@ void Unit::SetVisibility(UnitVisibility x)
if(IsInWorld()) if(IsInWorld())
{ {
// some auras requires visible target
if(m_Visibility == VISIBILITY_GROUP_NO_DETECT || m_Visibility == VISIBILITY_OFF)
{
static const AuraType auratypes[] = {SPELL_AURA_BIND_SIGHT, SPELL_AURA_FAR_SIGHT, SPELL_AURA_NONE};
for (AuraType const* type = &auratypes[0]; *type != SPELL_AURA_NONE; ++type)
{
AuraList& alist = m_modAuras[*type];
if(alist.empty())
continue;
for (AuraList::iterator it = alist.begin(); it != alist.end();)
{
Aura* aura = (*it);
Unit* owner = aura->GetCaster();
if (!owner || !isVisibleForOrDetect(owner,this,false))
{
alist.erase(it);
RemoveAura(aura);
it = alist.begin();
}
else
++it;
}
}
}
Map *m = GetMap(); Map *m = GetMap();
if(GetTypeId()==TYPEID_PLAYER) if(GetTypeId()==TYPEID_PLAYER)
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
else else
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
GetViewPoint().Event_ViewPointVisibilityChanged();
} }
} }
@ -12039,6 +12064,7 @@ void Unit::RemoveFromWorld()
RemoveAllGameObjects(); RemoveAllGameObjects();
RemoveAllDynObjects(); RemoveAllDynObjects();
CleanupDeletedAuras(); CleanupDeletedAuras();
GetViewPoint().Event_RemovedFromWorld();
} }
Object::RemoveFromWorld(); Object::RemoveFromWorld();

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 "10051" #define REVISION_NR "10052"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__

View file

@ -370,6 +370,7 @@
<ClCompile Include="..\..\src\game\BattleGroundWS.cpp" /> <ClCompile Include="..\..\src\game\BattleGroundWS.cpp" />
<ClCompile Include="..\..\src\game\Calendar.cpp" /> <ClCompile Include="..\..\src\game\Calendar.cpp" />
<ClCompile Include="..\..\src\game\CalendarHandler.cpp" /> <ClCompile Include="..\..\src\game\CalendarHandler.cpp" />
<ClCompile Include="..\..\src\game\Camera.cpp" />
<ClCompile Include="..\..\src\game\Channel.cpp" /> <ClCompile Include="..\..\src\game\Channel.cpp" />
<ClCompile Include="..\..\src\game\ChannelHandler.cpp" /> <ClCompile Include="..\..\src\game\ChannelHandler.cpp" />
<ClCompile Include="..\..\src\game\ChannelMgr.cpp" /> <ClCompile Include="..\..\src\game\ChannelMgr.cpp" />
@ -517,6 +518,7 @@
<ClInclude Include="..\..\src\game\BattleGroundSA.h" /> <ClInclude Include="..\..\src\game\BattleGroundSA.h" />
<ClInclude Include="..\..\src\game\BattleGroundWS.h" /> <ClInclude Include="..\..\src\game\BattleGroundWS.h" />
<ClInclude Include="..\..\src\game\Calendar.h" /> <ClInclude Include="..\..\src\game\Calendar.h" />
<ClInclude Include="..\..\src\game\Camera.h" />
<ClInclude Include="..\..\src\game\Cell.h" /> <ClInclude Include="..\..\src\game\Cell.h" />
<ClInclude Include="..\..\src\game\CellImpl.h" /> <ClInclude Include="..\..\src\game\CellImpl.h" />
<ClInclude Include="..\..\src\game\Channel.h" /> <ClInclude Include="..\..\src\game\Channel.h" />

View file

@ -442,6 +442,9 @@
<ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp"> <ClCompile Include="..\..\src\game\CharacterDatabaseCleaner.cpp">
<Filter>Tool</Filter> <Filter>Tool</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="..\..\src\game\Camera.cpp">
<Filter>Object</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="..\..\src\game\AccountMgr.h"> <ClInclude Include="..\..\src\game\AccountMgr.h">
@ -832,5 +835,8 @@
<ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h"> <ClInclude Include="..\..\src\game\CharacterDatabaseCleaner.h">
<Filter>Tool</Filter> <Filter>Tool</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="..\..\src\game\Camera.h">
<Filter>Object</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -669,6 +669,14 @@
RelativePath="..\..\src\game\CalendarHandler.cpp" RelativePath="..\..\src\game\CalendarHandler.cpp"
> >
</File> </File>
<File
RelativePath="..\..\src\game\Camera.cpp"
>
</File>
<File
RelativePath="..\..\src\game\Camera.h"
>
</File>
<File <File
RelativePath="..\..\src\game\Cell.h" RelativePath="..\..\src\game\Cell.h"
> >

View file

@ -1162,6 +1162,14 @@
RelativePath="..\..\src\game\Calendar.h" RelativePath="..\..\src\game\Calendar.h"
> >
</File> </File>
<File
RelativePath="..\..\src\game\Camera.cpp"
>
</File>
<File
RelativePath="..\..\src\game\Camera.h"
>
</File>
<File <File
RelativePath="..\..\src\game\Corpse.cpp" RelativePath="..\..\src\game\Corpse.cpp"
> >