[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::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));
}

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::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));
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
if(IsInWorld())
{
GetMap()->GetObjectsStore().erase<DynamicObject>(GetGUID(), (DynamicObject*)NULL);
GetViewPoint().Event_RemovedFromWorld();
}
Object::RemoveFromWorld();
}

View file

@ -31,6 +31,7 @@ class DynamicObject;
class GameObject;
class Pet;
class Player;
class Camera;
#define MAX_NUMBER_OF_GRIDS 64
@ -56,10 +57,12 @@ class Player;
#define MAP_HALFSIZE (MAP_SIZE/2)
// 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_5(Creature, Pet, Vehicle, GameObject, DynamicObject) AllMapStoredObjectTypes;
typedef GridRefManager<Camera> CameraMapType;
typedef GridRefManager<Corpse> CorpseMapType;
typedef GridRefManager<Creature> CreatureMapType;
typedef GridRefManager<DynamicObject> DynamicObjectMapType;

View file

@ -28,32 +28,29 @@
using namespace MaNGOS;
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();
if(player == &i_object)
continue;
player->UpdateVisibilityOf(player->GetViewPoint(),&i_object);
iter->getSource()->UpdateVisibilityOf(&i_object);
}
}
void
VisibleNotifier::Notify()
{
Player& player = *i_camera.GetOwner();
// 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
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)
{
if (i_clientGUIDs.find((*itr)->GetGUID()) != i_clientGUIDs.end())
{
// ignore far sight case
(*itr)->UpdateVisibilityOf((*itr),&i_player);
i_player.UpdateVisibilityOf(&i_player,(*itr),i_data,i_visibleNow);
(*itr)->UpdateVisibilityOf(*itr, &player);
player.UpdateVisibilityOf(&player, *itr, i_data, i_visibleNow);
i_clientGUIDs.erase((*itr)->GetGUID());
}
}
@ -63,9 +60,10 @@ VisibleNotifier::Notify()
i_data.AddOutOfRangeGUID(i_clientGUIDs);
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())
@ -73,7 +71,7 @@ VisibleNotifier::Notify()
// send create/outofrange packet to player (except player create updates that already sent using SendUpdateToPlayer)
WorldPacket packet;
i_data.BuildPacket(&packet);
i_player.GetSession()->SendPacket(&packet);
player.GetSession()->SendPacket(&packet);
// send out of range to other players if need
ObjectGuidSet const& oor = i_data.GetOutOfRangeGUIDs();
@ -83,7 +81,7 @@ VisibleNotifier::Notify()
continue;
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)
{
// target aura duration for caster show only if target exist at caster client
if((*vItr)!=&i_player && (*vItr)->isType(TYPEMASK_UNIT))
i_player.SendAurasForTarget((Unit*)(*vItr));
if ((*vItr) != &player && (*vItr)->isType(TYPEMASK_UNIT))
player.SendAurasForTarget((Unit*)(*vItr));
// non finished movements show to player
if ((*vItr)->GetTypeId()==TYPEID_UNIT && ((Creature*)(*vItr))->isAlive())
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&i_player);
((Creature*)(*vItr))->SendMonsterMoveWithSpeedToCurrentDestination(&player);
}
}
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;
if(WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = owner->GetSession())
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();
if(!player->InSamePhase(i_phaseMask) || player == i_skipped_receiver)
Player* owner = iter->getSource()->GetOwner();
if (!owner->InSamePhase(i_phaseMask) || owner == i_skipped_receiver)
continue;
if (WorldSession* session = player->GetSession())
if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message);
}
}
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;
if(WorldSession* session = iter->getSource()->GetSession())
if(WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message);
}
}
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 ) &&
(!i_ownTeamOnly || iter->getSource()->GetTeam() == i_player.GetTeam() ) &&
(!i_dist || iter->getSource()->IsWithinDist(&i_player,i_dist)))
Player * owner = iter->getSource()->GetOwner();
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;
if (WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = owner->GetSession())
session->SendPacket(i_message);
}
}
}
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;
if (WorldSession* session = iter->getSource()->GetSession())
if (WorldSession* session = iter->getSource()->GetOwner()->GetSession())
session->SendPacket(i_message);
}
}

View file

@ -38,13 +38,14 @@ namespace MaNGOS
{
struct MANGOS_DLL_DECL VisibleNotifier
{
Player &i_player;
Camera& i_camera;
UpdateData i_data;
ObjectGuidSet i_clientGUIDs;
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);
void Visit(CameraMapType &m) {}
void Notify(void);
};
@ -54,7 +55,7 @@ namespace MaNGOS
explicit VisibleChangesNotifier(WorldObject &object) : i_object(object) {}
template<class T> void Visit(GridRefManager<T> &) {}
void Visit(PlayerMapType &);
void Visit(CameraMapType &);
};
struct MANGOS_DLL_DECL GridUpdater
@ -82,7 +83,7 @@ namespace MaNGOS
WorldPacket *i_message;
bool i_toSelf;
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> &) {}
};
@ -95,7 +96,7 @@ namespace MaNGOS
MessageDelivererExcept(WorldObject const* obj, WorldPacket *msg, Player const* 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> &) {}
};
@ -105,7 +106,7 @@ namespace MaNGOS
WorldPacket *i_message;
explicit ObjectMessageDeliverer(WorldObject& obj, WorldPacket *msg)
: i_phaseMask(obj.GetPhaseMask()), i_message(msg) {}
void Visit(PlayerMapType &m);
void Visit(CameraMapType &m);
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)
: 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> &) {}
};
@ -129,7 +130,7 @@ namespace MaNGOS
WorldPacket *i_message;
float i_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> &) {}
};
@ -140,6 +141,7 @@ namespace MaNGOS
template<class T> void Visit(GridRefManager<T> &m);
void Visit(PlayerMapType &) {}
void Visit(CorpseMapType &) {}
void Visit(CameraMapType &) {}
void Visit(CreatureMapType &);
};
@ -476,22 +478,21 @@ namespace MaNGOS
};
template<class Do>
struct MANGOS_DLL_DECL PlayerDistWorker
struct MANGOS_DLL_DECL CameraDistWorker
{
WorldObject const* i_searcher;
float i_dist;
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) {}
void Visit(PlayerMapType &m)
void Visit(CameraMapType &m)
{
for(PlayerMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->InSamePhase(i_searcher) && itr->getSource()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource());
for(CameraMapType::iterator itr=m.begin(); itr != m.end(); ++itr)
if (itr->getSource()->GetBody()->InSamePhase(i_searcher) && itr->getSource()->GetBody()->IsWithinDist(i_searcher,i_dist))
i_do(itr->getSource()->GetOwner());
}
template<class NOT_INTERESTED> void Visit(GridRefManager<NOT_INTERESTED> &) {}
};

View file

@ -31,11 +31,9 @@
template<class T>
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)
{
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());
}
}
@ -96,7 +94,7 @@ inline void MaNGOS::PlayerRelocationNotifier::Visit(CreatureMapType &m)
if (!i_player.isAlive() || i_player.isInFlight())
return;
WorldObject const* viewPoint = i_player.GetViewPoint();
WorldObject const* viewPoint = i_player.GetCamera().GetBody();
for(CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
if (iter->getSource()->isAlive())
@ -112,7 +110,7 @@ inline void MaNGOS::CreatureRelocationNotifier::Visit(PlayerMapType &m)
for(PlayerMapType::iterator iter=m.begin(); iter != m.end(); ++iter)
if (Player* player = iter->getSource())
if (player->isAlive() && !player->isInFlight())
PlayerCreatureRelocationWorker(player, player->GetViewPoint(), &i_creature);
PlayerCreatureRelocationWorker(player, player->GetCamera().GetBody(), &i_creature);
}
template<>

View file

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

View file

@ -367,8 +367,9 @@ bool Map::Add(Player *player)
SendInitSelf(player);
SendInitTransports(player);
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
player->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
AddNotifier(player,cell,p);
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());
obj->GetViewPoint().Event_AddedToWorld(&(*grid)(cell.CellX(), cell.CellY()));
UpdateObjectVisibility(obj,cell,p);
AddNotifier(obj,cell,p);
@ -682,7 +684,6 @@ void Map::Remove(Player *player, bool remove)
SendRemoveTransports(player);
UpdateObjectVisibility(player,cell,p);
UpdateObjectsVisibilityFor(player,cell,p);
player->ResetMap();
if( remove )
@ -716,10 +717,9 @@ Map::Remove(T *obj, bool remove)
else
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);
UpdateObjectVisibility(obj,cell,p);
obj->ResetMap();
if( remove )
{
@ -759,10 +759,13 @@ Map::PlayerRelocation(Player *player, float x, float y, float z, float orientati
AddToGrid(player, oldGrid,new_cell);
else
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
UpdateObjectsVisibilityFor(player,new_cell,new_val);
UpdateObjectVisibility(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->GetViewPoint().Call_UpdateVisibilityForOwner();
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());
if( !old_cell.DiffGrid(new_cell) )
{
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
AddToGrid(c,getNGrid(new_cell.GridX(), new_cell.GridY()),new_cell);
c->SetCurrentCell(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()) );
}
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());
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;
}
@ -865,7 +872,9 @@ bool Map::CreatureCellRelocation(Creature *c, Cell new_cell)
RemoveFromGrid(c,getNGrid(old_cell.GridX(), old_cell.GridY()),old_cell);
{
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;
@ -1420,21 +1429,6 @@ void Map::UpdateObjectVisibility( WorldObject* obj, Cell cell, CellPair cellpair
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 )
{
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>
{
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
virtual ~Map();
@ -211,7 +213,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
void AddObjectToRemoveList(WorldObject *obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void UpdateObjectsVisibilityFor(Player* player, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); }
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());
// or update at original position
else
_player->UpdateVisibilityForPlayer();
{
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
}
// or update at original position
else
_player->UpdateVisibilityForPlayer();
{
_player->GetCamera().UpdateVisibilityForOwner();
_player->UpdateObjectVisibility();
}
}
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::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));
}
@ -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::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));
}
@ -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::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);
}
@ -1864,7 +1864,10 @@ void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
m_phaseMask = newPhaseMask;
if(update && IsInWorld())
{
UpdateObjectVisibility();
GetViewPoint().Event_ViewPointVisibilityChanged();
}
}
void WorldObject::PlayDistanceSound( uint32 sound_id, Player* target /*= NULL*/ )
@ -1910,12 +1913,22 @@ struct WorldObjectChangeAccumulator
{
UpdateDataMapType &i_updateDatas;
WorldObject &i_object;
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj) {}
void Visit(PlayerMapType &m)
WorldObjectChangeAccumulator(WorldObject &obj, UpdateDataMapType &d) : i_updateDatas(d), i_object(obj)
{
for(PlayerMapType::iterator iter = m.begin(); iter != m.end(); ++iter)
if(iter->getSource()->HaveAtClient(&i_object))
i_object.BuildUpdateDataForPlayer(iter->getSource(), i_updateDatas);
// send self fields changes in another way, otherwise
// with new camera system when player's camera too far from player, camera wouldn't receive packets and changes from player
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> &) {}

View file

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

View file

@ -25,6 +25,7 @@
#include "Corpse.h"
#include "World.h"
#include "CellImpl.h"
#include "GridDefines.h"
class MANGOS_DLL_DECL ObjectGridRespawnMover
{
@ -105,7 +106,7 @@ template<> void addUnitState(Creature *obj, CellPair const& cell_pair)
}
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;
@ -121,13 +122,16 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
continue;
}
obj->GetGridRef().link(&m, obj);
grid.AddGridObject(obj);
addUnitState(obj,cell);
obj->SetMap(map);
obj->AddToWorld();
if(obj->isActiveObject())
map->AddToActive(obj);
obj->GetViewPoint().Event_AddedToWorld(&grid);
if (bg)
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())
return;
@ -151,7 +155,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
if(!obj)
continue;
obj->GetGridRef().link(&m, obj);
grid.AddWorldObject(obj);
addUnitState(obj,cell);
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);
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
@ -186,7 +191,8 @@ ObjectGridLoader::Visit(CreatureMapType &m)
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
@ -199,7 +205,8 @@ ObjectWorldLoader::Visit(CorpseMapType &m)
// 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);
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

View file

@ -405,7 +405,7 @@ void TradeData::SetAccepted(bool state, bool crosssend /*= false*/)
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;
@ -2409,7 +2409,8 @@ void Player::SetGameMaster(bool on)
getHostileRefManager().setOnlineOfflineState(true);
}
UpdateVisibilityForPlayer();
m_camera.UpdateVisibilityForOwner();
UpdateObjectVisibility();
}
void Player::SetGMVisible(bool on)
@ -4490,8 +4491,10 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
GetZoneAndAreaId(newzone,newarea);
UpdateZone(newzone,newarea);
// update visibility
UpdateVisibilityForPlayer();
// update visibility of world around viewpoint
m_camera.UpdateVisibilityForOwner();
// update visibility of player for nearby cameras
UpdateObjectVisibility();
if(!applySickness)
return;
@ -6073,12 +6076,8 @@ void Player::SaveRecallPosition()
void Player::SendMessageToSet(WorldPacket *data, bool self)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageBroadcast(this, data, self);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageBroadcast(this, data, false);
//if player is not in world and map in not created/already destroyed
//no need to create one, just send packet for itself!
@ -6088,12 +6087,8 @@ void Player::SendMessageToSet(WorldPacket *data, bool self)
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageDistBroadcast(this, data, dist, self);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageDistBroadcast(this, data, dist, false);
if (self)
GetSession()->SendPacket(data);
@ -6101,12 +6096,8 @@ void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self)
void Player::SendMessageToSetInRange(WorldPacket *data, float dist, bool self, bool own_team_only)
{
Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId());
if(_map)
{
_map->MessageDistBroadcast(this, data, dist, self, own_team_only);
return;
}
if (Map * _map = IsInWorld() ? GetMap() : sMapMgr.FindMap(GetMapId(), GetInstanceId()))
_map->MessageDistBroadcast(this, data, dist, false, own_team_only);
if (self)
GetSession()->SendPacket(data);
@ -15322,7 +15313,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
SetCreatorGUID(0);
// reset some aura modifiers before aura apply
SetFarSightGUID(0);
SetUInt64Value(PLAYER_FARSIGHT, 0);
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
@ -18058,7 +18050,7 @@ void Player::HandleStealthedUnitsDetection()
MaNGOS::UnitListSearcher<MaNGOS::AnyStealthedCheck > searcher(this,stealthedUnits, u_check);
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)
{
@ -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
{
// gamemaster in GM mode see all, including ghosts
@ -20736,7 +20717,7 @@ void Player::EnterVehicle(Vehicle *vehicle)
vehicle->setFaction(getFaction());
SetCharm(vehicle); // charm
SetFarSightGUID(vehicle->GetGUID()); // set view
m_camera.SetView(vehicle); // set view
SetClientControl(vehicle, 1); // redirect controls to vehicle
SetMover(vehicle);
@ -20788,7 +20769,7 @@ void Player::ExitVehicle(Vehicle *vehicle)
vehicle->setFaction((GetTeam() == ALLIANCE) ? vehicle->GetCreatureInfo()->faction_A : vehicle->GetCreatureInfo()->faction_H);
SetCharm(NULL);
SetFarSightGUID(0);
m_camera.ResetView();
SetClientControl(vehicle, 0);
SetMover(NULL);
@ -22022,38 +22003,6 @@ bool Player::HasMovementFlag( MovementFlags f ) const
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()
{
m_timeSyncCounter = 0;

View file

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

View file

@ -808,6 +808,7 @@ namespace MaNGOS
template<> inline void Visit(CorpseMapType & ) {}
template<> inline void Visit(GameObjectMapType & ) {}
template<> inline void Visit(DynamicObjectMapType & ) {}
template<> inline void Visit(CameraMapType & ) {}
#endif
};
@ -815,6 +816,7 @@ namespace MaNGOS
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CorpseMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(GameObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(DynamicObjectMapType& ) {}
template<> inline void SpellNotifierCreatureAndPlayer::Visit(CameraMapType& ) {}
#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)))
{
// 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);
((Player*)target)->GetSession()->SendPacket(&data);
return;
@ -3543,7 +3543,11 @@ void Aura::HandleBindSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
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*/)
@ -3552,7 +3556,11 @@ void Aura::HandleFarSight(bool apply, bool /*Real*/)
if(!caster || caster->GetTypeId() != TYPEID_PLAYER)
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*/)
@ -3607,7 +3615,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
return;
Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if( apply )
{
@ -3618,7 +3626,7 @@ void Aura::HandleModPossess(bool apply, bool Real)
p_caster->SetCharm(target);
p_caster->SetFarSightGUID(target->GetGUID());
camera.SetView(target);
p_caster->SetClientControl(target, 1);
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->SetCharm(NULL);
p_caster->SetFarSightGUID(0);
camera.ResetView();
p_caster->SetClientControl(target, 0);
p_caster->SetMover(NULL);
@ -3695,13 +3703,19 @@ void Aura::HandleModPossessPet(bool apply, bool Real)
return;
Player* p_caster = (Player*)caster;
Camera& camera = p_caster->GetCamera();
if(apply)
{
pet->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PLAYER_CONTROLLED);
camera.SetView(pet);
}
else
{
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->SetClientControl(pet, apply ? 1 : 0);
((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);
}
if(Real && target->GetTypeId()==TYPEID_PLAYER)
((Player*)target)->UpdateVisibilityForPlayer();
((Player*)target)->GetCamera().UpdateVisibilityForOwner();
}
void Aura::HandleAuraModRoot(bool apply, bool Real)

View file

@ -4244,7 +4244,8 @@ void Spell::EffectAddFarsight(SpellEffectIndex eff_idx)
dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
m_caster->AddDynObject(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)

View file

@ -10579,10 +10579,6 @@ bool Unit::isVisibleForOrDetect(Unit const* u, WorldObject const* viewPoint, boo
return false;
}
// always seen by far sight caster
if (u->GetTypeId()==TYPEID_PLAYER && ((Player*)u)->GetFarSight()==GetGUID())
return true;
// different visible distance checks
if (u->isInFlight()) // what see player in flight
{
@ -10781,12 +10777,41 @@ void Unit::SetVisibility(UnitVisibility x)
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();
if(GetTypeId()==TYPEID_PLAYER)
m->PlayerRelocation((Player*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
else
m->CreatureRelocation((Creature*)this,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation());
GetViewPoint().Event_ViewPointVisibilityChanged();
}
}
@ -12039,6 +12064,7 @@ void Unit::RemoveFromWorld()
RemoveAllGameObjects();
RemoveAllDynObjects();
CleanupDeletedAuras();
GetViewPoint().Event_RemovedFromWorld();
}
Object::RemoveFromWorld();

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10051"
#define REVISION_NR "10052"
#endif // __REVISION_NR_H__

View file

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

View file

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

View file

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

View file

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