[8182] Store and use Map* pointer in WorldObject instead map ids for speedup

Also some code logic cleanups.
Changes let make more cleanups in base map access and other places,
but this chnages not inlcuded in patch.

Signed-off-by: VladimirMangos <vladimir@getmangos.com>
This commit is contained in:
Ambal 2009-07-15 01:30:13 +04:00 committed by VladimirMangos
parent fcb34b3928
commit 58209ee79a
25 changed files with 180 additions and 193 deletions

View file

@ -72,12 +72,15 @@ bool Corpse::Create( uint32 guidlow )
bool Corpse::Create( uint32 guidlow, Player *owner) bool Corpse::Create( uint32 guidlow, Player *owner)
{ {
SetInstanceId(owner->GetInstanceId()); ASSERT(owner);
WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetMapId(), owner->GetPhaseMask());
WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask());
Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation());
//we need to assign owner's map for corpse
//in other way we will get a crash in Corpse::SaveToDB()
SetMap(owner->GetMap());
if(!IsPositionValid()) if(!IsPositionValid())
{ {
sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)",
@ -207,8 +210,8 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields)
SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE));
// place // place
SetInstanceId(instanceid); SetLocationInstanceId(instanceid);
SetMapId(mapid); SetLocationMapId(mapid);
SetPhaseMask(phaseMask, false); SetPhaseMask(phaseMask, false);
Relocate(positionX, positionY, positionZ, ort); Relocate(positionX, positionY, positionZ, ort);

View file

@ -563,8 +563,8 @@ bool Creature::AIM_Initialize()
bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data) bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, const CreatureData *data)
{ {
SetMapId(map->GetId()); ASSERT(map);
SetInstanceId(map->GetInstanceId()); SetMap(map);
SetPhaseMask(phaseMask,false); SetPhaseMask(phaseMask,false);
//oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0;
@ -572,6 +572,12 @@ bool Creature::Create (uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry,
if (bResult) if (bResult)
{ {
//Notify the map's instance data.
//Only works if you create the object in it, not if it is moves to that map.
//Normally non-players do not teleport to other maps.
if(map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData())
((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this);
switch (GetCreatureInfo()->rank) switch (GetCreatureInfo()->rank)
{ {
case CREATURE_ELITE_RARE: case CREATURE_ELITE_RARE:
@ -1312,15 +1318,6 @@ bool Creature::CreateFromProto(uint32 guidlow, uint32 Entry, uint32 team, const
if(!UpdateEntry(Entry, team, data)) if(!UpdateEntry(Entry, team, data))
return false; return false;
//Notify the map's instance data.
//Only works if you create the object in it, not if it is moves to that map.
//Normally non-players do not teleport to other maps.
Map *map = MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
if(map && map->IsDungeon() && ((InstanceMap*)map)->GetInstanceData())
{
((InstanceMap*)map)->GetInstanceData()->OnCreatureCreate(this);
}
return true; return true;
} }

View file

@ -56,9 +56,8 @@ void DynamicObject::RemoveFromWorld()
bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius ) bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 effIndex, float x, float y, float z, int32 duration, float radius )
{ {
SetInstanceId(caster->GetInstanceId()); WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask());
SetMap(caster->GetMap());
WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetMapId(), caster->GetPhaseMask());
Relocate(x, y, z, 0); Relocate(x, y, z, 0);
if(!IsPositionValid()) if(!IsPositionValid())

View file

@ -109,9 +109,9 @@ void GameObject::RemoveFromWorld()
bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state) bool GameObject::Create(uint32 guidlow, uint32 name_id, Map *map, uint32 phaseMask, float x, float y, float z, float ang, float rotation0, float rotation1, float rotation2, float rotation3, uint32 animprogress, GOState go_state)
{ {
ASSERT(map);
Relocate(x,y,z,ang); Relocate(x,y,z,ang);
SetMapId(map->GetId()); SetMap(map);
SetInstanceId(map->GetInstanceId());
SetPhaseMask(phaseMask,false); SetPhaseMask(phaseMask,false);
if(!IsPositionValid()) if(!IsPositionValid())

View file

@ -124,14 +124,12 @@ void Map::LoadMap(int gx,int gy, bool reload)
if(GridMaps[gx][gy]) if(GridMaps[gx][gy])
return; return;
Map* baseMap = const_cast<Map*>(MapManager::Instance().CreateBaseMap(i_id));
// load grid map for base map // load grid map for base map
if (!baseMap->GridMaps[gx][gy]) if (!m_parentMap->GridMaps[gx][gy])
baseMap->EnsureGridCreated(GridPair(63-gx,63-gy)); m_parentMap->EnsureGridCreated(GridPair(63-gx,63-gy));
((MapInstanced*)(baseMap))->AddGridMapReference(GridPair(gx,gy)); ((MapInstanced*)(m_parentMap))->AddGridMapReference(GridPair(gx,gy));
GridMaps[gx][gy] = baseMap->GridMaps[gx][gy]; GridMaps[gx][gy] = m_parentMap->GridMaps[gx][gy];
return; return;
} }
@ -184,11 +182,11 @@ void Map::DeleteStateMachine()
delete si_GridStates[GRID_STATE_REMOVAL]; delete si_GridStates[GRID_STATE_REMOVAL];
} }
Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
: i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode),
i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0),
m_activeNonPlayersIter(m_activeNonPlayers.end()), m_activeNonPlayersIter(m_activeNonPlayers.end()),
i_gridExpiry(expiry) i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this)
{ {
for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx) for(unsigned int idx=0; idx < MAX_NUMBER_OF_GRIDS; ++idx)
{ {
@ -295,6 +293,13 @@ void Map::DeleteFromWorld(T* obj)
delete obj; delete obj;
} }
template<>
void Map::DeleteFromWorld(Player* pl)
{
ObjectAccessor::Instance().RemoveObject(pl);
delete pl;
}
template<class T> template<class T>
void Map::AddNotifier(T* , Cell const& , CellPair const& ) void Map::AddNotifier(T* , Cell const& , CellPair const& )
{ {
@ -399,8 +404,7 @@ void Map::LoadGrid(const Cell& cell, bool no_unload)
bool Map::Add(Player *player) bool Map::Add(Player *player)
{ {
player->GetMapRef().link(this, player); player->GetMapRef().link(this, player);
player->SetMap(this);
player->SetInstanceId(GetInstanceId());
// update player state for other player and visa-versa // update player state for other player and visa-versa
CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
@ -431,6 +435,8 @@ Map::Add(T *obj)
return; return;
} }
obj->SetMap(this);
Cell cell(p); Cell cell(p);
if(obj->isActiveObject()) if(obj->isActiveObject())
EnsureGridLoadedAtEnter(cell); EnsureGridLoadedAtEnter(cell);
@ -688,8 +694,12 @@ void Map::Remove(Player *player, bool remove)
CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); CellPair p = MaNGOS::ComputeCellPair(player->GetPositionX(), player->GetPositionY());
if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP)
{ {
if(remove)
player->CleanupsBeforeDelete();
// invalid coordinates // invalid coordinates
player->RemoveFromWorld(); player->RemoveFromWorld();
player->ResetMap();
if( remove ) if( remove )
DeleteFromWorld(player); DeleteFromWorld(player);
@ -709,13 +719,16 @@ void Map::Remove(Player *player, bool remove)
NGridType *grid = getNGrid(cell.GridX(), cell.GridY()); NGridType *grid = getNGrid(cell.GridX(), cell.GridY());
assert(grid != NULL); assert(grid != NULL);
if(remove)
player->CleanupsBeforeDelete();
player->RemoveFromWorld(); player->RemoveFromWorld();
RemoveFromGrid(player,grid,cell); RemoveFromGrid(player,grid,cell);
SendRemoveTransports(player); SendRemoveTransports(player);
UpdateObjectsVisibilityFor(player,cell,p); UpdateObjectsVisibilityFor(player,cell,p);
player->ResetMap();
if( remove ) if( remove )
DeleteFromWorld(player); DeleteFromWorld(player);
} }
@ -760,6 +773,7 @@ Map::Remove(T *obj, bool remove)
UpdateObjectVisibility(obj,cell,p); UpdateObjectVisibility(obj,cell,p);
obj->ResetMap();
if( remove ) if( remove )
{ {
// if option set then object already saved at this moment // if option set then object already saved at this moment
@ -1029,7 +1043,8 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool pForce)
VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx); VMAP::VMapFactory::createOrGetVMapManager()->unloadMap(GetId(), gy, gx);
} }
else else
((MapInstanced*)(MapManager::Instance().CreateBaseMap(i_id)))->RemoveGridMapReference(GridPair(gx, gy)); ((MapInstanced*)m_parentMap)->RemoveGridMapReference(GridPair(gx, gy));
GridMaps[gx][gy] = NULL; GridMaps[gx][gy] = NULL;
} }
DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, i_id); DEBUG_LOG("Unloading grid[%u,%u] for map %u finished", x,y, i_id);
@ -2196,8 +2211,8 @@ template void Map::Remove(DynamicObject *, bool);
/* ******* Dungeon Instance Maps ******* */ /* ******* Dungeon Instance Maps ******* */
InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode) InstanceMap::InstanceMap(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent)
: Map(id, expiry, InstanceId, SpawnMode), : Map(id, expiry, InstanceId, SpawnMode, _parent),
m_resetAfterUnload(false), m_unloadWhenEmpty(false), m_resetAfterUnload(false), m_unloadWhenEmpty(false),
i_data(NULL), i_script_id(0) i_data(NULL), i_script_id(0)
{ {
@ -2534,8 +2549,8 @@ uint32 InstanceMap::GetMaxPlayers() const
/* ******* Battleground Instance Maps ******* */ /* ******* Battleground Instance Maps ******* */
BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId) BattleGroundMap::BattleGroundMap(uint32 id, time_t expiry, uint32 InstanceId, Map* _parent)
: Map(id, expiry, InstanceId, DIFFICULTY_NORMAL) : Map(id, expiry, InstanceId, DIFFICULTY_NORMAL, _parent)
{ {
} }

View file

@ -245,7 +245,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
{ {
friend class MapReference; friend class MapReference;
public: public:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent = NULL);
virtual ~Map(); virtual ~Map();
// currently unused for normal maps // currently unused for normal maps
@ -300,6 +300,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
static void InitStateMachine(); static void InitStateMachine();
static void DeleteStateMachine(); static void DeleteStateMachine();
Map const * GetParent() const { return m_parentMap; }
// some calls like isInWater should not use vmaps due to processor power // some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height // can return INVALID_HEIGHT if under z+2 z coord not found height
float GetHeight(float x, float y, float z, bool pCheckVMap=true) const; float GetHeight(float x, float y, float z, bool pCheckVMap=true) const;
@ -461,6 +463,10 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj
ActiveNonPlayers m_activeNonPlayers; ActiveNonPlayers m_activeNonPlayers;
ActiveNonPlayers::iterator m_activeNonPlayersIter; ActiveNonPlayers::iterator m_activeNonPlayersIter;
private: private:
//used for fast base_map (e.g. MapInstanced class object) search for
//InstanceMaps and BattleGroundMaps...
Map* m_parentMap;
typedef GridReadGuard ReadGuard; typedef GridReadGuard ReadGuard;
typedef GridWriteGuard WriteGuard; typedef GridWriteGuard WriteGuard;
@ -520,7 +526,7 @@ enum InstanceResetMethod
class MANGOS_DLL_SPEC InstanceMap : public Map class MANGOS_DLL_SPEC InstanceMap : public Map
{ {
public: public:
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode); InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
~InstanceMap(); ~InstanceMap();
bool Add(Player *); bool Add(Player *);
void Remove(Player *, bool); void Remove(Player *, bool);
@ -545,7 +551,7 @@ class MANGOS_DLL_SPEC InstanceMap : public Map
class MANGOS_DLL_SPEC BattleGroundMap : public Map class MANGOS_DLL_SPEC BattleGroundMap : public Map
{ {
public: public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId); BattleGroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent);
~BattleGroundMap(); ~BattleGroundMap();
bool Add(Player *); bool Add(Player *);

View file

@ -108,84 +108,59 @@ void MapInstanced::UnloadAll(bool pForce)
- create the instance if it's not created already - create the instance if it's not created already
- the player is not actually added to the instance (only in InstanceMap::Add) - the player is not actually added to the instance (only in InstanceMap::Add)
*/ */
Map* MapInstanced::GetInstance(const WorldObject* obj) Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player)
{ {
uint32 CurInstanceId = obj->GetInstanceId(); if(GetId() != mapId || !player)
Map* map = NULL; return NULL;
if (obj->GetMapId() == GetId() && CurInstanceId != 0) Map* map = NULL;
uint32 NewInstanceId = 0; // instanceId of the resulting map
if(IsBattleGroundOrArena())
{ {
// the object wants to be put in a certain instance of this map // instantiate or find existing bg map for player
map = _FindMap(CurInstanceId); // the instance id is set in battlegroundid
NewInstanceId = player->GetBattleGroundId();
ASSERT(NewInstanceId);
map = _FindMap(NewInstanceId);
if(!map) if(!map)
{ map = CreateBattleGround(NewInstanceId);
// For players if the instanceId is set, it's assumed they are already in a map,
// hence the map must be loaded. For Creatures, GameObjects etc the map must exist
// prior to calling GetMap, they are not allowed to create maps for themselves.
sLog.outError("GetInstance: object %s(%d), typeId %d, in world %d, should be in map %d,%d but that's not loaded yet.", obj->GetName(), obj->GetGUIDLow(), obj->GetTypeId(), obj->IsInWorld(), obj->GetMapId(), obj->GetInstanceId());
assert(false);
}
return(map);
} }
else else
{ {
// instance not specified, find an existing or create a new one InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty());
if(obj->GetTypeId() != TYPEID_PLAYER) InstanceSave *pSave = pBind ? pBind->save : NULL;
// the player's permanent player bind is taken into consideration first
// then the player's group bind and finally the solo bind.
if(!pBind || !pBind->perm)
{ {
sLog.outError("MAPINSTANCED: WorldObject '%u' (Entry: %u TypeID: %u) is in map %d,%d and requested base map instance of map %d, this must not happen", obj->GetGUIDLow(), obj->GetEntry(), obj->GetTypeId(), obj->GetMapId(), obj->GetInstanceId(), GetId()); InstanceGroupBind *groupBind = NULL;
assert(false); Group *group = player->GetGroup();
return NULL; // use the player's difficulty setting (it may not be the same as the group's)
if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty())))
pSave = groupBind->save;
}
if(pSave)
{
// solo/perm/group
NewInstanceId = pSave->GetInstanceId();
map = _FindMap(NewInstanceId);
// it is possible that the save exists but the map doesn't
if(!map)
map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty());
} }
else else
{ {
uint32 NewInstanceId = 0; // instanceId of the resulting map // if no instanceId via group members or instance saves is found
Player* player = (Player*)obj; // the instance will be created for the first time
NewInstanceId = MapManager::Instance().GenerateInstanceId();
if(IsBattleGroundOrArena()) map = CreateInstance(NewInstanceId, NULL, player->GetDifficulty());
{
// instantiate or find existing bg map for player
// the instance id is set in battlegroundid
NewInstanceId = player->GetBattleGroundId();
assert(NewInstanceId);
map = _FindMap(NewInstanceId);
if(!map)
map = CreateBattleGround(NewInstanceId);
return map;
}
InstancePlayerBind *pBind = player->GetBoundInstance(GetId(), player->GetDifficulty());
InstanceSave *pSave = pBind ? pBind->save : NULL;
// the player's permanet player bind is taken into consideration first
// then the player's group bind and finally the solo bind.
if(!pBind || !pBind->perm)
{
InstanceGroupBind *groupBind = NULL;
Group *group = player->GetGroup();
// use the player's difficulty setting (it may not be the same as the group's)
if(group && (groupBind = group->GetBoundInstance(GetId(), player->GetDifficulty())))
pSave = groupBind->save;
}
if(pSave)
{
// solo/perm/group
NewInstanceId = pSave->GetInstanceId();
map = _FindMap(NewInstanceId);
// it is possible that the save exists but the map doesn't
if(!map)
map = CreateInstance(NewInstanceId, pSave, pSave->GetDifficulty());
return map;
}
else
{
// if no instanceId via group members or instance saves is found
// the instance will be created for the first time
NewInstanceId = MapManager::Instance().GenerateInstanceId();
return CreateInstance(NewInstanceId, NULL, player->GetDifficulty());
}
} }
} }
return map;
} }
InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty) InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save, uint8 difficulty)
@ -210,10 +185,10 @@ InstanceMap* MapInstanced::CreateInstance(uint32 InstanceId, InstanceSave *save,
// some instances only have one difficulty // some instances only have one difficulty
if (entry && !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL; if (entry && !entry->SupportsHeroicMode()) difficulty = DIFFICULTY_NORMAL;
sLog.outDebug("MapInstanced::CreateInstance: %smap instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal"); sLog.outDebug("MapInstanced::CreateInstance: %s map instance %d for %d created with difficulty %s", save?"":"new ", InstanceId, GetId(), difficulty?"heroic":"normal");
InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty); InstanceMap *map = new InstanceMap(GetId(), GetGridExpiry(), InstanceId, difficulty, this);
assert(map->IsDungeon()); ASSERT(map->IsDungeon());
bool load_data = save != NULL; bool load_data = save != NULL;
map->CreateInstanceData(load_data); map->CreateInstanceData(load_data);
@ -229,8 +204,8 @@ BattleGroundMap* MapInstanced::CreateBattleGround(uint32 InstanceId)
sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId()); sLog.outDebug("MapInstanced::CreateBattleGround: map bg %d for %d created.", InstanceId, GetId());
BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId); BattleGroundMap *map = new BattleGroundMap(GetId(), GetGridExpiry(), InstanceId, this);
assert(map->IsBattleGroundOrArena()); ASSERT(map->IsBattleGroundOrArena());
m_InstancedMaps[InstanceId] = map; m_InstancedMaps[InstanceId] = map;
return map; return map;

View file

@ -38,7 +38,7 @@ class MANGOS_DLL_DECL MapInstanced : public Map
bool RemoveBones(uint64 guid, float x, float y); bool RemoveBones(uint64 guid, float x, float y);
void UnloadAll(bool pForce); void UnloadAll(bool pForce);
Map* GetInstance(const WorldObject* obj); Map* CreateInstance(const uint32 mapId, Player * player);
Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); } Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); }
void DestroyInstance(uint32 InstanceId); void DestroyInstance(uint32 InstanceId);
void DestroyInstance(InstancedMaps::iterator &itr); void DestroyInstance(InstancedMaps::iterator &itr);

View file

@ -122,13 +122,13 @@ MapManager::_createBaseMap(uint32 id)
return m; return m;
} }
Map* MapManager::GetMap(uint32 id, const WorldObject* obj) Map* MapManager::CreateMap(uint32 id, const WorldObject* obj)
{ {
ASSERT(obj); ASSERT(obj);
//if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId()); //if(!obj->IsInWorld()) sLog.outError("GetMap: called for map %d with object (typeid %d, guid %d, mapid %d, instanceid %d) who is not in world!", id, obj->GetTypeId(), obj->GetGUIDLow(), obj->GetMapId(), obj->GetInstanceId());
Map *m = _createBaseMap(id); Map *m = _createBaseMap(id);
if (m && obj && m->Instanceable()) m = ((MapInstanced*)m)->GetInstance(obj); if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj);
return m; return m;
} }

View file

@ -37,7 +37,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS::
public: public:
Map* GetMap(uint32, const WorldObject* obj); Map* CreateMap(uint32, const WorldObject* obj);
Map const* CreateBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_createBaseMap(id); } Map const* CreateBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_createBaseMap(id); }
Map* FindMap(uint32 mapid, uint32 instanceId = 0) const; Map* FindMap(uint32 mapid, uint32 instanceId = 0) const;

View file

@ -65,18 +65,17 @@ void WorldSession::HandleMoveWorldportAckOpcode()
GetPlayer()->SetSemaphoreTeleportFar(false); GetPlayer()->SetSemaphoreTeleportFar(false);
// relocate the player to the teleport destination // relocate the player to the teleport destination
GetPlayer()->SetMapId(loc.mapid); GetPlayer()->SetMap(MapManager::Instance().CreateMap(loc.mapid, GetPlayer())); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
// since the MapId is set before the GetInstance call, the InstanceId must be set to 0
// to let GetInstance() determine the proper InstanceId based on the player's binds
GetPlayer()->SetInstanceId(0);
GetPlayer()->SendInitialPacketsBeforeAddToMap(); GetPlayer()->SendInitialPacketsBeforeAddToMap();
// the CanEnter checks are done in TeleporTo but conditions may change // the CanEnter checks are done in TeleporTo but conditions may change
// while the player is in transit, for example the map may get full // while the player is in transit, for example the map may get full
if(!GetPlayer()->GetMap()->Add(GetPlayer())) if(!GetPlayer()->GetMap()->Add(GetPlayer()))
{ {
//if player wasn't added to map, reset his map pointer!
GetPlayer()->ResetMap();
sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); sLog.outDebug("WORLD: teleport of player %s (%d) to location %d, %f, %f, %f, %f failed", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid, loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation);
// teleport the player home // teleport the player home
if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()))

View file

@ -1049,7 +1049,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const
WorldObject::WorldObject() WorldObject::WorldObject()
: m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f) m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL)
{ {
} }
@ -1057,11 +1057,9 @@ void WorldObject::CleanupsBeforeDelete()
{ {
} }
void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask ) void WorldObject::_Create( uint32 guidlow, HighGuid guidhigh, uint32 phaseMask )
{ {
Object::_Create(guidlow, 0, guidhigh); Object::_Create(guidlow, 0, guidhigh);
m_mapId = mapid;
m_phaseMask = phaseMask; m_phaseMask = phaseMask;
} }
@ -1538,14 +1536,19 @@ void WorldObject::SendObjectDeSpawnAnim(uint64 guid)
SendMessageToSet(&data, true); SendMessageToSet(&data, true);
} }
Map* WorldObject::GetMap() const void WorldObject::SetMap(Map * map)
{ {
return MapManager::Instance().GetMap(GetMapId(), this); ASSERT(map);
m_currMap = map;
//lets save current map's Id/instanceId
m_mapId = map->GetId();
m_InstanceId = map->GetInstanceId();
} }
Map const* WorldObject::GetBaseMap() const Map const* WorldObject::GetBaseMap() const
{ {
return MapManager::Instance().CreateBaseMap(GetMapId()); ASSERT(m_currMap);
return m_currMap->GetParent();
} }
void WorldObject::AddObjectToRemoveList() void WorldObject::AddObjectToRemoveList()
@ -1557,7 +1560,6 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
{ {
TemporarySummon* pCreature = new TemporarySummon(GetGUID()); TemporarySummon* pCreature = new TemporarySummon(GetGUID());
pCreature->SetInstanceId(GetInstanceId());
uint32 team = 0; uint32 team = 0;
if (GetTypeId()==TYPEID_PLAYER) if (GetTypeId()==TYPEID_PLAYER)
team = ((Player*)this)->GetTeam(); team = ((Player*)this)->GetTeam();

View file

@ -346,7 +346,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
virtual void Update ( uint32 /*time_diff*/ ) { } virtual void Update ( uint32 /*time_diff*/ ) { }
void _Create( uint32 guidlow, HighGuid guidhigh, uint32 mapid, uint32 phaseMask); void _Create( uint32 guidlow, HighGuid guidhigh, uint32 phaseMask);
void Relocate(float x, float y, float z, float orientation) void Relocate(float x, float y, float z, float orientation)
{ {
@ -395,8 +395,8 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const; void GetRandomPoint( float x, float y, float z, float distance, float &rand_x, float &rand_y, float &rand_z ) const;
void SetMapId(uint32 newMap) { m_mapId = newMap; }
uint32 GetMapId() const { return m_mapId; } uint32 GetMapId() const { return m_mapId; }
uint32 GetInstanceId() const { return m_InstanceId; }
virtual void SetPhaseMask(uint32 newPhaseMask, bool update); virtual void SetPhaseMask(uint32 newPhaseMask, bool update);
uint32 GetPhaseMask() const { return m_phaseMask; } uint32 GetPhaseMask() const { return m_phaseMask; }
@ -421,8 +421,7 @@ class MANGOS_DLL_SPEC WorldObject : public Object
float GetDistanceZ(const WorldObject* obj) const; float GetDistanceZ(const WorldObject* obj) const;
bool IsInMap(const WorldObject* obj) const bool IsInMap(const WorldObject* obj) const
{ {
return IsInWorld() && obj->IsInWorld() && GetMapId()==obj->GetMapId() && return IsInWorld() && obj->IsInWorld() && (GetMap() == obj->GetMap()) && InSamePhase(obj);
GetInstanceId()==obj->GetInstanceId() && InSamePhase(obj);
} }
bool IsWithinDist3d(float x, float y, float z, float dist2compare) const; bool IsWithinDist3d(float x, float y, float z, float dist2compare) const;
bool IsWithinDist2d(float x, float y, float dist2compare) const; bool IsWithinDist2d(float x, float y, float dist2compare) const;
@ -469,10 +468,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object
void SendObjectDeSpawnAnim(uint64 guid); void SendObjectDeSpawnAnim(uint64 guid);
virtual void SaveRespawnTime() {} virtual void SaveRespawnTime() {}
uint32 GetInstanceId() const { return m_InstanceId; }
void SetInstanceId(uint32 val) { m_InstanceId = val; }
void AddObjectToRemoveList(); void AddObjectToRemoveList();
// main visibility check function in normal case (ignore grey zone distance check) // main visibility check function in normal case (ignore grey zone distance check)
@ -481,15 +476,29 @@ class MANGOS_DLL_SPEC WorldObject : public Object
// low level function for visibility change code, must be define in all main world object subclasses // low level function for visibility change code, must be define in all main world object subclasses
virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0; virtual bool isVisibleForInState(Player const* u, bool inVisibleList) const = 0;
Map * GetMap() const; void SetMap(Map * map);
Map * GetMap() const { ASSERT(m_currMap); return m_currMap; }
//used to check all object's GetMap() calls when object is not in world!
void ResetMap() { m_currMap = NULL; }
//this function should be removed in nearest time...
Map const* GetBaseMap() const; Map const* GetBaseMap() const;
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);
protected: protected:
explicit WorldObject(); explicit WorldObject();
std::string m_name; std::string m_name;
//these functions are used mostly for Relocate() and Corpse/Player specific stuff...
//use them ONLY in LoadFromDB()/Create() funcs and nowhere else!
//mapId/instanceId should be set in SetMap() function!
void SetLocationMapId(uint32 _mapId) { m_mapId = _mapId; }
void SetLocationInstanceId(uint32 _instanceId) { m_InstanceId = _instanceId; }
private: private:
Map * m_currMap; //current object's Map location
uint32 m_mapId; // object at map with map_id uint32 m_mapId; // object at map with map_id
uint32 m_InstanceId; // in map copy with instance id uint32 m_InstanceId; // in map copy with instance id
uint32 m_phaseMask; // in area phase state uint32 m_phaseMask; // in area phase state

View file

@ -363,8 +363,6 @@ ObjectAccessor::ConvertCorpseForPlayer(uint64 player_guid, bool insignia)
// bones->m_inWorld = m_inWorld; // don't overwrite world state // bones->m_inWorld = m_inWorld; // don't overwrite world state
// bones->m_type = m_type; // don't overwrite type // bones->m_type = m_type; // don't overwrite type
bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation()); bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
bones->SetMapId(corpse->GetMapId());
bones->SetInstanceId(corpse->GetInstanceId());
bones->SetPhaseMask(corpse->GetPhaseMask(), false); bones->SetPhaseMask(corpse->GetPhaseMask(), false);
bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES); bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);

View file

@ -123,6 +123,7 @@ void LoadHelper(CellGuidSet const& guid_set, CellPair &cell, GridRefManager<T> &
obj->GetGridRef().link(&m, obj); obj->GetGridRef().link(&m, obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map);
obj->AddToWorld(); obj->AddToWorld();
if(obj->isActiveObject()) if(obj->isActiveObject())
map->AddToActive(obj); map->AddToActive(obj);
@ -151,6 +152,7 @@ void LoadHelper(CellCorpseSet const& cell_corpses, CellPair &cell, CorpseMapType
obj->GetGridRef().link(&m, obj); obj->GetGridRef().link(&m, obj);
addUnitState(obj,cell); addUnitState(obj,cell);
obj->SetMap(map);
obj->AddToWorld(); obj->AddToWorld();
if(obj->isActiveObject()) if(obj->isActiveObject())
map->AddToActive(obj); map->AddToActive(obj);

View file

@ -744,9 +744,6 @@ bool Pet::CreateBaseAtCreature(Creature* creature)
} }
uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET); uint32 guid=objmgr.GenerateLowGuid(HIGHGUID_PET);
sLog.outBasic("SetInstanceID()");
SetInstanceId(creature->GetInstanceId());
sLog.outBasic("Create pet"); sLog.outBasic("Create pet");
uint32 pet_number = objmgr.GeneratePetNumber(); uint32 pet_number = objmgr.GeneratePetNumber();
if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number)) if(!Create(guid, creature->GetMap(), creature->GetPhaseMask(), creature->GetEntry(), pet_number))
@ -1841,8 +1838,7 @@ bool Pet::IsPermanentPetFor(Player* owner)
bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number)
{ {
SetMapId(map->GetId()); SetMap(map);
SetInstanceId(map->GetInstanceId());
SetPhaseMask(phaseMask,false); SetPhaseMask(phaseMask,false);
Object::_Create(guidlow, pet_number, HIGHGUID_PET); Object::_Create(guidlow, pet_number, HIGHGUID_PET);

View file

@ -540,7 +540,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i) for (int i = 0; i < PLAYER_SLOTS_COUNT; ++i)
m_items[i] = NULL; m_items[i] = NULL;
SetMapId(info->mapId); SetLocationMapId(info->mapId);
Relocate(info->positionX,info->positionY,info->positionZ); Relocate(info->positionX,info->positionY,info->positionZ);
ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_); ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_);
@ -550,6 +550,8 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8
return false; return false;
} }
SetMap(MapManager::Instance().CreateMap(info->mapId, this));
uint8 powertype = cEntry->powerType; uint8 powertype = cEntry->powerType;
SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE);
@ -12031,7 +12033,11 @@ void Player::PrepareQuestMenu( uint64 guid )
} }
else else
{ {
GameObject *pGameObject = GetMap()->GetGameObject(guid); //we should obtain map pointer from GetMap() in 99% of cases. Special case
//only for quests which cast teleport spells on player
Map * _map = IsInWorld() ? GetMap() : MapManager::Instance().FindMap(GetMapId(), GetInstanceId());
ASSERT(_map);
GameObject *pGameObject = _map->GetGameObject(guid);
if( pGameObject ) if( pGameObject )
{ {
pObject = (Object*)pGameObject; pObject = (Object*)pGameObject;
@ -13829,7 +13835,8 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid )
m_name = fields[2].GetCppString(); m_name = fields[2].GetCppString();
Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat()); Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat());
SetMapId(fields[6].GetUInt32()); SetLocationMapId(fields[6].GetUInt32());
// the instance id is not needed at character enum // the instance id is not needed at character enum
m_Played_time[0] = fields[7].GetUInt32(); m_Played_time[0] = fields[7].GetUInt32();
@ -14108,7 +14115,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// init saved position, and fix it later if problematic // init saved position, and fix it later if problematic
uint32 transGUID = fields[31].GetUInt32(); uint32 transGUID = fields[31].GetUInt32();
Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat()); Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat());
SetMapId(fields[16].GetUInt32()); SetLocationMapId(fields[16].GetUInt32());
SetDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup SetDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup
_LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP));
@ -14183,7 +14190,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
else else
{ {
const WorldLocation& _loc = GetBattleGroundEntryPoint(); const WorldLocation& _loc = GetBattleGroundEntryPoint();
SetMapId(_loc.mapid); SetLocationMapId(_loc.mapid);
Relocate(_loc.coord_x, _loc.coord_y, _loc.coord_z, _loc.orientation); Relocate(_loc.coord_x, _loc.coord_y, _loc.coord_z, _loc.orientation);
//RemoveArenaAuras(true); //RemoveArenaAuras(true);
} }
@ -14196,7 +14203,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
if(!mapEntry || mapEntry->IsBattleGroundOrArena()) if(!mapEntry || mapEntry->IsBattleGroundOrArena())
{ {
// return to BG master // return to BG master
SetMapId(fields[43].GetUInt32()); SetLocationMapId(fields[43].GetUInt32());
Relocate(fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat()); Relocate(fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat());
// check entry point and fix to homebind if need // check entry point and fix to homebind if need
@ -14250,7 +14257,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
m_transport = *iter; m_transport = *iter;
m_transport->AddPassenger(this); m_transport->AddPassenger(this);
SetMapId(m_transport->GetMapId()); SetLocationMapId(m_transport->GetMapId());
break; break;
} }
} }
@ -14283,11 +14290,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
// NOW player must have valid map // NOW player must have valid map
// load the player's map here if it's not already loaded // load the player's map here if it's not already loaded
Map *map = GetMap(); SetMap(MapManager::Instance().CreateMap(GetMapId(), this));
// since the player may not be bound to the map yet, make sure subsequent
// getmap calls won't create new maps
SetInstanceId(map->GetInstanceId());
// if the player is in an instance and it has been reset in the meantime teleport him to the entrance // if the player is in an instance and it has been reset in the meantime teleport him to the entrance
if(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId())) if(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId()))
@ -14465,15 +14468,19 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
{ {
sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow());
RelocateToHomebind(); RelocateToHomebind();
SaveRecallPosition(); // save as recall also to prevent recall and fall from sky
} }
else // have start node, to it else // have start node, to it
{ {
sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow()); sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow());
SetMapId(nodeEntry->map_id); SetLocationMapId(nodeEntry->map_id);
Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f); Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f);
SaveRecallPosition(); // save as recall also to prevent recall and fall from sky
} }
//we can be relocated from taxi and still have an outdated Map pointer!
//so we need to get a new Map pointer!
SetMap(MapManager::Instance().CreateMap(GetMapId(), this));
SaveRecallPosition(); // save as recall also to prevent recall and fall from sky
m_taxi.ClearTaxiDestinations(); m_taxi.ClearTaxiDestinations();
} }
else if(uint32 node_id = m_taxi.GetTaxiSource()) else if(uint32 node_id = m_taxi.GetTaxiSource())

View file

@ -2071,7 +2071,7 @@ class MANGOS_DLL_SPEC Player : public Unit
float m_homebindX; float m_homebindX;
float m_homebindY; float m_homebindY;
float m_homebindZ; float m_homebindZ;
void RelocateToHomebind() { SetMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); } void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); }
// currently visible objects at player client // currently visible objects at player client
typedef std::set<uint64> ClientGUIDs; typedef std::set<uint64> ClientGUIDs;

View file

@ -4080,7 +4080,6 @@ void Spell::EffectSummonPet(uint32 i)
return; return;
OldSummon->GetMap()->Remove((Creature*)OldSummon,false); OldSummon->GetMap()->Remove((Creature*)OldSummon,false);
OldSummon->SetMapId(m_caster->GetMapId());
float px, py, pz; float px, py, pz;
m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize()); m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());

View file

@ -54,8 +54,6 @@ void Totem::Update( uint32 time )
void Totem::Summon(Unit* owner) void Totem::Summon(Unit* owner)
{ {
sLog.outDebug("AddObject at Totem.cpp line 49"); sLog.outDebug("AddObject at Totem.cpp line 49");
SetInstanceId(owner->GetInstanceId());
owner->GetMap()->Add((Creature*)this); owner->GetMap()->Add((Creature*)this);
// select totem model in dependent from owner team // select totem model in dependent from owner team

View file

@ -102,7 +102,8 @@ void MapManager::LoadTransports()
m_TransportsByMap[*i].insert(t); m_TransportsByMap[*i].insert(t);
//If we someday decide to use the grid to track transports, here: //If we someday decide to use the grid to track transports, here:
//MapManager::Instance().LoadGrid(mapid,x,y,true); t->SetMap(MapManager::Instance().CreateMap(mapid, t));
//t->GetMap()->Add<GameObject>((GameObject *)t); //t->GetMap()->Add<GameObject>((GameObject *)t);
++count; ++count;
} while(result->NextRow()); } while(result->NextRow());
@ -138,8 +139,6 @@ Transport::Transport() : GameObject()
bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags)
{ {
Relocate(x,y,z,ang); Relocate(x,y,z,ang);
SetMapId(mapid);
// instance id and phaseMask isn't set to values different from std. // instance id and phaseMask isn't set to values different from std.
if(!IsPositionValid()) if(!IsPositionValid())
@ -432,7 +431,6 @@ Transport::WayPointMap::const_iterator Transport::GetNextWayPoint()
void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
{ {
Map const* oldMap = GetMap(); Map const* oldMap = GetMap();
SetMapId(newMapid);
Relocate(x, y, z); Relocate(x, y, z);
for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();) for(PlayerSet::iterator itr = m_passengers.begin(); itr != m_passengers.end();)
@ -458,7 +456,11 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z)
//plr->GetSession()->SendPacket(&data); //plr->GetSession()->SendPacket(&data);
} }
Map const* newMap = GetMap(); //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference...
//player far teleport would try to create same instance, but we need it NOW for transport...
//correct me if I'm wrong O.o
Map * newMap = MapManager::Instance().CreateMap(newMapid, this);
SetMap(newMap);
if(oldMap != newMap) if(oldMap != newMap)
{ {

View file

@ -54,24 +54,11 @@ class TransportPath
std::vector<PathNode> i_nodes; std::vector<PathNode> i_nodes;
}; };
class Transport : protected GameObject class Transport : public GameObject
{ {
public: public:
explicit Transport(); explicit Transport();
// prevent using Transports as normal GO, but allow call some inherited functions
using GameObject::IsTransport;
using GameObject::GetEntry;
using GameObject::GetGUID;
using GameObject::GetGUIDLow;
using GameObject::GetMapId;
using GameObject::GetPositionX;
using GameObject::GetPositionY;
using GameObject::GetPositionZ;
using GameObject::BuildCreateUpdateBlockForPlayer;
using GameObject::BuildOutOfRangeUpdateBlock;
using GameObject::GetPackGUID;
bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags);
bool GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids); bool GenerateWaypoints(uint32 pathid, std::set<uint32> &mapids);
void Update(uint32 p_time); void Update(uint32 p_time);

View file

@ -62,8 +62,7 @@ void Vehicle::Update(uint32 diff)
bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team) bool Vehicle::Create(uint32 guidlow, Map *map, uint32 Entry, uint32 vehicleId, uint32 team)
{ {
SetMapId(map->GetId()); SetMap(map);
SetInstanceId(map->GetInstanceId());
Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE); Object::_Create(guidlow, Entry, HIGHGUID_VEHICLE);

View file

@ -385,15 +385,9 @@ void WorldSession::LogoutPlayer(bool Save)
// the player may not be in the world when logging out // the player may not be in the world when logging out
// e.g if he got disconnected during a transfer to another map // e.g if he got disconnected during a transfer to another map
// calls to GetMap in this case may cause crashes // calls to GetMap in this case may cause crashes
if(_player->IsInWorld()) _player->GetMap()->Remove(_player, false); Map* _map = _player->GetMap();
// RemoveFromWorld does cleanup that requires the player to be in the accessor _map->Remove(_player, true);
ObjectAccessor::Instance().RemoveObject(_player); _player = NULL; // deleted in Remove call
///- Delete the player object
_player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data
delete _player;
_player = NULL;
///- Send the 'logout complete' packet to the client ///- Send the 'logout complete' packet to the client
WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 ); WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 );

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 "8181" #define REVISION_NR "8182"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__