diff options
author | QAston <none@none> | 2009-08-01 00:20:32 +0200 |
---|---|---|
committer | QAston <none@none> | 2009-08-01 00:20:32 +0200 |
commit | 1d96091d2a4f9a886a4d3cd80ec3c873d395dbdd (patch) | |
tree | 88589d294e7eb5ccabf7e667970b116e6a2670a6 | |
parent | 0db1fd6c26b90241cfe039f2e2b3e35d10cb9cbd (diff) |
*Improvements in map managing.
--HG--
branch : trunk
-rw-r--r-- | src/game/BattleGroundMgr.cpp | 2 | ||||
-rw-r--r-- | src/game/CharacterHandler.cpp | 2 | ||||
-rw-r--r-- | src/game/Corpse.cpp | 20 | ||||
-rw-r--r-- | src/game/Corpse.h | 4 | ||||
-rw-r--r-- | src/game/Creature.cpp | 9 | ||||
-rw-r--r-- | src/game/DynamicObject.cpp | 4 | ||||
-rw-r--r-- | src/game/GameObject.cpp | 5 | ||||
-rw-r--r-- | src/game/Map.cpp | 56 | ||||
-rw-r--r-- | src/game/Map.h | 12 | ||||
-rw-r--r-- | src/game/MapInstanced.cpp | 17 | ||||
-rw-r--r-- | src/game/MapInstanced.h | 2 | ||||
-rw-r--r-- | src/game/MapManager.cpp | 4 | ||||
-rw-r--r-- | src/game/MapManager.h | 2 | ||||
-rw-r--r-- | src/game/MovementHandler.cpp | 28 | ||||
-rw-r--r-- | src/game/Object.cpp | 6 | ||||
-rw-r--r-- | src/game/Object.h | 30 | ||||
-rw-r--r-- | src/game/ObjectAccessor.cpp | 4 | ||||
-rw-r--r-- | src/game/ObjectAccessor.h | 2 | ||||
-rw-r--r-- | src/game/ObjectMgr.cpp | 6 | ||||
-rw-r--r-- | src/game/Pet.cpp | 3 | ||||
-rw-r--r-- | src/game/Player.cpp | 288 | ||||
-rw-r--r-- | src/game/Player.h | 6 | ||||
-rw-r--r-- | src/game/SpellEffects.cpp | 3 | ||||
-rw-r--r-- | src/game/Transports.cpp | 8 |
24 files changed, 247 insertions, 276 deletions
diff --git a/src/game/BattleGroundMgr.cpp b/src/game/BattleGroundMgr.cpp index 371c204717d..3e0a4f25314 100644 --- a/src/game/BattleGroundMgr.cpp +++ b/src/game/BattleGroundMgr.cpp @@ -1474,6 +1474,8 @@ BattleGround * BattleGroundMgr::GetBattleGroundThroughClientInstance(uint32 inst BattleGround * BattleGroundMgr::GetBattleGround(uint32 InstanceID, BattleGroundTypeId bgTypeId) { + if (!InstanceID) + return NULL; //search if needed BattleGroundSet::iterator itr; if (bgTypeId == BATTLEGROUND_TYPE_NONE) diff --git a/src/game/CharacterHandler.cpp b/src/game/CharacterHandler.cpp index a1a2122a050..fded85cf715 100644 --- a/src/game/CharacterHandler.cpp +++ b/src/game/CharacterHandler.cpp @@ -64,7 +64,7 @@ bool LoginQueryHolder::Initialize() // NOTE: all fields in `characters` must be read to prevent lost character data at next save in case wrong DB structure. // !!! NOTE: including unused `zone`,`online` - res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,bgid,bgteam,bgmap,bgx,bgy,bgz,bgo,instance_id FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); + res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADFROM, "SELECT guid, account, data, name, race, class, gender, level, xp, money, playerBytes, playerBytes2, playerFlags, position_x, position_y, position_z, map, orientation, taximask, cinematic, totaltime, leveltime, rest_bonus, logout_time, is_logout_resting, resettalents_cost, resettalents_time, trans_x, trans_y, trans_z, trans_o, transguid, extra_flags, stable_slots, at_login, zone, online, death_expire_time, taxi_path, dungeon_difficulty, arena_pending_points,instance_id,bgteam,bgmap,bgx,bgy,bgz,bgo FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT leaderGuid FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_mask,stackcount,amount0, amount1, amount2 ,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid)); diff --git a/src/game/Corpse.cpp b/src/game/Corpse.cpp index ea8ad57c910..3f6d724b6a8 100644 --- a/src/game/Corpse.cpp +++ b/src/game/Corpse.cpp @@ -76,13 +76,12 @@ bool Corpse::Create( uint32 guidlow, Player *owner) { ASSERT(owner); - WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); - 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()); + Relocate(owner->GetPositionX(), owner->GetPositionY(), owner->GetPositionZ(), owner->GetOrientation()); + if(!IsPositionValid()) { sLog.outError("Corpse (guidlow %d, owner %s) not created. Suggested coordinates isn't valid (X: %f Y: %f)", @@ -90,6 +89,8 @@ bool Corpse::Create( uint32 guidlow, Player *owner) return false; } + WorldObject::_Create(guidlow, HIGHGUID_CORPSE, owner->GetPhaseMask()); + SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); SetUInt64Value( CORPSE_FIELD_OWNER, owner->GetGUID() ); @@ -149,6 +150,7 @@ void Corpse::DeleteFromDB() CharacterDatabase.PExecute("DELETE FROM corpse WHERE player = '%d' AND corpse_type <> '0'", GUID_LOPART(GetOwnerGUID())); } +/* bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) { bool external = (result != NULL); @@ -176,9 +178,9 @@ bool Corpse::LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId) delete result; return true; -} +}*/ -bool Corpse::LoadFromDB(uint32 guid, Field *fields) +bool Corpse::LoadFromDB(uint32 guid, Field *fields, uint32 & mapId, uint32 & instanceId) { // 0 1 2 3 4 5 6 7 8 9 //result = CharacterDatabase.PQuery("SELECT position_x,position_y,position_z,orientation,map,data,time,corpse_type,instance,phaseMask FROM corpse WHERE guid = '%u'",guid); @@ -186,7 +188,6 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) float positionY = fields[1].GetFloat(); float positionZ = fields[2].GetFloat(); float ort = fields[3].GetFloat(); - uint32 mapid = fields[4].GetUInt32(); Object::_Create(guid, 0, HIGHGUID_CORPSE); @@ -196,6 +197,9 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) return false; } + mapId = fields[4].GetUInt32(); + instanceId = fields[8].GetUInt32(); + m_time = time_t(fields[6].GetUInt64()); m_type = CorpseType(fields[7].GetUInt32()); @@ -205,15 +209,11 @@ bool Corpse::LoadFromDB(uint32 guid, Field *fields) return false; } - uint32 instanceid = fields[8].GetUInt32(); uint32 phaseMask = fields[9].GetUInt32(); // overwrite possible wrong/corrupted guid SetUInt64Value(OBJECT_FIELD_GUID, MAKE_NEW_GUID(guid, 0, HIGHGUID_CORPSE)); - // place - SetLocationInstanceId(instanceid); - SetLocationMapId(mapid); SetPhaseMask(phaseMask, false); Relocate(positionX, positionY, positionZ, ort); diff --git a/src/game/Corpse.h b/src/game/Corpse.h index da3511abfbb..e21b0796d62 100644 --- a/src/game/Corpse.h +++ b/src/game/Corpse.h @@ -61,8 +61,8 @@ class Corpse : public WorldObject bool Create( uint32 guidlow, Player *owner ); void SaveToDB(); - bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); - bool LoadFromDB(uint32 guid, Field *fields); + //bool LoadFromDB(uint32 guid, QueryResult *result, uint32 InstanceId); + bool LoadFromDB(uint32 guid, Field *fields, uint32 & mapId, uint32 & instanceId); void DeleteBonesFromWorld(); void DeleteFromDB(); diff --git a/src/game/Creature.cpp b/src/game/Creature.cpp index a1f37c65f1e..4fd772091cf 100644 --- a/src/game/Creature.cpp +++ b/src/game/Creature.cpp @@ -691,17 +691,18 @@ void Creature::Motion_Initialize() bool Creature::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 team, float x, float y, float z, float ang, const CreatureData *data) { + ASSERT(map); + SetMap(map); + SetPhaseMask(phaseMask,false); + Relocate(x, y, z, ang); + if(!IsPositionValid()) { sLog.outError("Creature (guidlow %d, entry %d) not loaded. Suggested coordinates isn't valid (X: %f Y: %f)",guidlow,Entry,x,y); return false; } - ASSERT(map); - SetMap(map); - SetPhaseMask(phaseMask,false); - //oX = x; oY = y; dX = x; dY = y; m_moveTime = 0; m_startMove = 0; const bool bResult = CreateFromProto(guidlow, Entry, team, data); diff --git a/src/game/DynamicObject.cpp b/src/game/DynamicObject.cpp index c910e343bd7..80b0d91a1b8 100644 --- a/src/game/DynamicObject.cpp +++ b/src/game/DynamicObject.cpp @@ -72,8 +72,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 ) { - WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); SetMap(caster->GetMap()); + Relocate(x, y, z, 0); if(!IsPositionValid()) @@ -82,6 +82,8 @@ bool DynamicObject::Create( uint32 guidlow, Unit *caster, uint32 spellId, uint32 return false; } + WorldObject::_Create(guidlow, HIGHGUID_DYNAMICOBJECT, caster->GetPhaseMask()); + SetEntry(spellId); SetFloatValue( OBJECT_FIELD_SCALE_X, 1 ); SetUInt64Value( DYNAMICOBJECT_CASTER, caster->GetGUID() ); diff --git a/src/game/GameObject.cpp b/src/game/GameObject.cpp index b6ac3442c0d..e6ff16f251c 100644 --- a/src/game/GameObject.cpp +++ b/src/game/GameObject.cpp @@ -137,16 +137,17 @@ 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, uint32 ArtKit) { ASSERT(map); - Relocate(x,y,z,ang); SetMap(map); - SetPhaseMask(phaseMask,false); + Relocate(x,y,z,ang); if(!IsPositionValid()) { sLog.outError("Gameobject (GUID: %u Entry: %u ) not created. Suggested coordinates isn't valid (X: %f Y: %f)",guidlow,name_id,x,y); return false; } + SetPhaseMask(phaseMask,false); + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id); if (!goinfo) { diff --git a/src/game/Map.cpp b/src/game/Map.cpp index c01944b14c7..4f0ecb1d26a 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -155,7 +155,7 @@ void Map::LoadMap(int gx,int gy, bool reload) //map already load, delete it before reloading (Is it necessary? Do we really need the ability the reload maps during runtime?) if(GridMaps[gx][gy]) { - sLog.outDetail("Unloading already loaded map %u before reloading.",i_id); + sLog.outDetail("Unloading already loaded map %u before reloading.",GetId()); delete (GridMaps[gx][gy]); GridMaps[gx][gy]=NULL; } @@ -164,7 +164,7 @@ void Map::LoadMap(int gx,int gy, bool reload) char *tmp=NULL; int len = sWorld.GetDataPath().length()+strlen("maps/%03u%02u%02u.map")+1; tmp = new char[len]; - snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),i_id,gx,gy); + snprintf(tmp, len, (char *)(sWorld.GetDataPath()+"maps/%03u%02u%02u.map").c_str(),GetId(),gx,gy); sLog.outDetail("Loading map %s",tmp); // loading data GridMaps[gx][gy] = new GridMap(); @@ -199,8 +199,7 @@ void Map::DeleteStateMachine() } Map::Map(uint32 id, time_t expiry, uint32 InstanceId, uint8 SpawnMode, Map* _parent) - : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), - i_id(id), i_InstanceId(InstanceId), m_unloadTimer(0), + : i_mapEntry (sMapStore.LookupEntry(id)), i_spawnMode(SpawnMode), i_InstanceId(InstanceId), m_unloadTimer(0), m_activeNonPlayersIter(m_activeNonPlayers.end()), i_gridExpiry(expiry), m_parentMap(_parent ? _parent : this) , i_lock(true) @@ -411,7 +410,7 @@ Map::EnsureGridCreated(const GridPair &p) Guard guard(*this); if(!getNGrid(p.x_coord, p.y_coord)) { - sLog.outDebug("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, i_id, i_InstanceId); + sLog.outDebug("Creating grid[%u,%u] for map %u instance %u", p.x_coord, p.y_coord, GetId(), i_InstanceId); setNGrid(new NGridType(p.x_coord*MAX_NUMBER_OF_GRIDS + p.y_coord, p.x_coord, p.y_coord, i_gridExpiry, sWorld.getConfig(CONFIG_GRID_UNLOAD)), p.x_coord, p.y_coord); @@ -443,11 +442,11 @@ Map::EnsureGridLoadedAtEnter(const Cell &cell, Player *player) if (player) { player->SendDelayResponse(MAX_GRID_LOAD_TIME); - DEBUG_LOG("Player %s enter cell[%u,%u] triggers of loading grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), i_id); + DEBUG_LOG("Player %s enter cell[%u,%u] triggers of loading grid[%u,%u] on map %u", player->GetName(), cell.CellX(), cell.CellY(), cell.GridX(), cell.GridY(), GetId()); } else { - DEBUG_LOG("Active object nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), i_id); + DEBUG_LOG("Active object nearby triggers of loading grid [%u,%u] on map %u", cell.GridX(), cell.GridY(), GetId()); } ResetGridExpiry(*getNGrid(cell.GridX(), cell.GridY()), 0.1f); @@ -468,7 +467,7 @@ bool Map::EnsureGridLoaded(const Cell &cell) assert(grid != NULL); if( !isGridObjectDataLoaded(cell.GridX(), cell.GridY()) ) { - sLog.outDebug("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), i_id, i_InstanceId); + sLog.outDebug("Loading grid[%u,%u] for map %u instance %u", cell.GridX(), cell.GridY(), GetId(), i_InstanceId); ObjectGridLoader loader(*grid, this, cell); loader.LoadN(); @@ -492,9 +491,8 @@ void Map::LoadGrid(float x, float y) bool Map::Add(Player *player) { - player->GetMapRef().link(this, player); - player->SetMap(this); - + // Check if we are adding to correct map + assert (player->GetMap() == this); // update player state for other player and visa-versa CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); Cell cell(p); @@ -812,14 +810,6 @@ void Map::Update(const uint32 &t_diff) void Map::Remove(Player *player, bool remove) { - // this may be called during Map::Update - // after decrement+unlink, ++m_mapRefIter will continue correctly - // when the first element of the list is being removed - // nocheck_prev will return the padding element of the RefManager - // instead of NULL in the case of prev - if(m_mapRefIter == player->GetMapRef()) - m_mapRefIter = m_mapRefIter->nocheck_prev(); - player->GetMapRef().unlink(); CellPair p = Trinity::ComputeCellPair(player->GetPositionX(), player->GetPositionY()); if(p.x_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP || p.y_coord >= TOTAL_NUMBER_OF_CELLS_PER_MAP) { @@ -857,7 +847,6 @@ void Map::Remove(Player *player, bool remove) SendRemoveTransports(player); UpdateObjectVisibility(player,cell,p); - player->ResetMap(); if( remove ) DeleteFromWorld(player); } @@ -1152,7 +1141,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) if(!unloadAll && ActiveObjectsNearGrid(x, y) ) return false; - sLog.outDebug("Unloading grid[%u,%u] for map %u", x,y, i_id); + sLog.outDebug("Unloading grid[%u,%u] for map %u", x,y, GetId()); ObjectGridUnloader unloader(*grid); @@ -1202,7 +1191,7 @@ bool Map::UnloadGrid(const uint32 &x, const uint32 &y, bool unloadAll) 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, GetId()); return true; } @@ -1824,7 +1813,7 @@ uint16 Map::GetAreaFlag(float x, float y, float z) const areaflag = gmap->getArea(x, y); // this used while not all *.map files generated (instances) else - areaflag = GetAreaFlagByMapId(i_id); + areaflag = GetAreaFlagByMapId(GetId()); //FIXME: some hacks for areas above or underground for ground area // required for area specific spells/etc, until map/vmap data @@ -2129,7 +2118,7 @@ void Map::SendInitTransports( Player * player ) for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) { // send data for current transport in other place - if((*i) != player->GetTransport() && (*i)->GetMapId()==i_id) + if((*i) != player->GetTransport() && (*i)->GetMapId()==GetId()) { (*i)->BuildCreateUpdateBlockForPlayer(&transData, player); } @@ -2155,7 +2144,7 @@ void Map::SendRemoveTransports( Player * player ) // except used transport for (MapManager::TransportSet::const_iterator i = tset.begin(); i != tset.end(); ++i) - if((*i) != player->GetTransport() && (*i)->GetMapId()!=i_id) + if((*i) != player->GetTransport() && (*i)->GetMapId()!=GetId()) (*i)->BuildOutOfRangeUpdateBlock(&transData); WorldPacket packet; @@ -2422,8 +2411,9 @@ bool InstanceMap::Add(Player *player) { Guard guard(*this); - if(!CanEnter(player)) - return false; + // Check moved to void WorldSession::HandleMoveWorldportAckOpcode() + //if(!CanEnter(player)) + //return false; // Dungeon only code if(IsDungeon()) @@ -2726,8 +2716,9 @@ bool BattleGroundMap::Add(Player * player) { { Guard guard(*this); - if(!CanEnter(player)) - return false; + //Check moved to void WorldSession::HandleMoveWorldportAckOpcode() + //if(!CanEnter(player)) + //return false; // reset instance validity, battleground maps do not homebind player->m_InstanceValid = true; } @@ -3638,3 +3629,10 @@ Map::GetDynamicObject(uint64 guid) return NULL; return ret; } + +void Map::UpdateIteratorBack(Player *player) +{ + if(m_mapRefIter == player->GetMapRef()) + m_mapRefIter = m_mapRefIter->nocheck_prev(); +} + diff --git a/src/game/Map.h b/src/game/Map.h index bbb861e8aeb..0597cfde8a0 100644 --- a/src/game/Map.h +++ b/src/game/Map.h @@ -46,6 +46,7 @@ class InstanceSave; class Object; class WorldObject; class TempSummon; +class Player; class CreatureGroup; struct ScriptInfo; struct ScriptAction; @@ -309,7 +310,7 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj } time_t GetGridExpiry(void) const { return i_gridExpiry; } - uint32 GetId(void) const { return i_id; } + uint32 GetId(void) const { return i_mapEntry->MapID; } static bool ExistMap(uint32 mapid, int gx, int gy); static bool ExistVMap(uint32 mapid, int gx, int gy); @@ -338,17 +339,17 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj uint32 GetAreaId(float x, float y, float z) const { - return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),i_id); + return GetAreaIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); } uint32 GetZoneId(float x, float y, float z) const { - return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),i_id); + return GetZoneIdByAreaFlag(GetAreaFlag(x,y,z),GetId()); } void GetZoneAndAreaId(uint32& zoneid, uint32& areaid, float x, float y, float z) const { - GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),i_id); + GetZoneAndAreaIdByAreaFlag(zoneid,areaid,GetAreaFlag(x,y,z),GetId()); } virtual void MoveAllCreaturesInMoveList(); @@ -431,6 +432,8 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj template<class NOTIFIER> void VisitGrid(const float &x, const float &y, float radius, NOTIFIER ¬ifier); CreatureGroupHolderType CreatureGroupHolder; + void UpdateIteratorBack(Player *player); + #ifdef MAP_BASED_RAND_GEN MTRand mtRand; int32 irand(int32 min, int32 max) { return int32 (mtRand.randInt(max - min)) + min; } @@ -492,7 +495,6 @@ class MANGOS_DLL_SPEC Map : public GridRefManager<NGridType>, public MaNGOS::Obj MapEntry const* i_mapEntry; uint8 i_spawnMode; - uint32 i_id; uint32 i_InstanceId; uint32 m_unloadTimer; diff --git a/src/game/MapInstanced.cpp b/src/game/MapInstanced.cpp index 89be57275bb..dfb673955c3 100644 --- a/src/game/MapInstanced.cpp +++ b/src/game/MapInstanced.cpp @@ -116,27 +116,16 @@ void MapInstanced::UnloadAll() - create the instance if it's not created already - the player is not actually added to the instance (only in InstanceMap::Add) */ -Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player) +Map* MapInstanced::CreateInstance(const uint32 mapId, Player * player, uint32 instanceId) { - uint32 instanceId = player->GetInstanceId(); - if(instanceId) if(Map *map = _FindMap(instanceId)) return map; if(IsBattleGroundOrArena()) { - instanceId = player->GetBattleGroundId(); - - if(instanceId) - { - if(Map *map = _FindMap(instanceId)) - return map; - else - return CreateBattleGround(instanceId); - } - else - return NULL; + assert(player->GetBattleGroundId()); + return CreateBattleGround(player->GetBattleGroundId()); } if(InstanceSave *pSave = player->GetInstanceSave(GetId())) diff --git a/src/game/MapInstanced.h b/src/game/MapInstanced.h index 83064bc074d..31e7b2da0f3 100644 --- a/src/game/MapInstanced.h +++ b/src/game/MapInstanced.h @@ -42,7 +42,7 @@ class TRINITY_DLL_DECL MapInstanced : public Map void UnloadAll(); bool CanEnter(Player* player); - Map* CreateInstance(const uint32 mapId, Player * player); + Map* CreateInstance(const uint32 mapId, Player * player, uint32 instanceId); Map* FindMap(uint32 InstanceId) const { return _FindMap(InstanceId); } void DestroyInstance(uint32 InstanceId); void DestroyInstance(InstancedMaps::iterator &itr); diff --git a/src/game/MapManager.cpp b/src/game/MapManager.cpp index 79a81f2afa3..1645419fd4d 100644 --- a/src/game/MapManager.cpp +++ b/src/game/MapManager.cpp @@ -128,13 +128,13 @@ MapManager::_createBaseMap(uint32 id) return m; } -Map* MapManager::CreateMap(uint32 id, const WorldObject* obj) +Map* MapManager::CreateMap(uint32 id, const WorldObject* obj, uint32 instanceId) { 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()); Map *m = _createBaseMap(id); - if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj); + if (m && (obj->GetTypeId() == TYPEID_PLAYER) && m->Instanceable()) m = ((MapInstanced*)m)->CreateInstance(id, (Player*)obj, instanceId); return m; } diff --git a/src/game/MapManager.h b/src/game/MapManager.h index a9ce5d73998..aac25af8a41 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -39,7 +39,7 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::Singleton<MapManager, MaNGOS:: public: - Map* CreateMap(uint32, const WorldObject* obj); + Map* CreateMap(uint32, const WorldObject* obj, uint32 instanceId); Map const* CreateBaseMap(uint32 id) const { return const_cast<MapManager*>(this)->_createBaseMap(id); } Map* FindMap(uint32 mapid, uint32 instanceId = 0) const; diff --git a/src/game/MovementHandler.cpp b/src/game/MovementHandler.cpp index 18e84092ddf..68deb5af9f4 100644 --- a/src/game/MovementHandler.cpp +++ b/src/game/MovementHandler.cpp @@ -66,13 +66,17 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->SetSemaphoreTeleportFar(false); + GetPlayer()->ResetMap(); + // relocate the player to the teleport destination - Map * newMap = MapManager::Instance().CreateMap(loc.mapid, GetPlayer()); - if (!newMap) + Map * newMap = MapManager::Instance().CreateMap(loc.mapid, GetPlayer(), 0); + // the CanEnter checks are done in TeleporTo but conditions may change + // while the player is in transit, for example the map may get full + if (!newMap->CanEnter(GetPlayer())) { sLog.outError("Map %d could not be created for player %d, porting player to homebind", loc.mapid, GetPlayer()->GetGUIDLow()); - GetPlayer()->RelocateToHomebind(); - newMap = MapManager::Instance().CreateMap(GetPlayer()->GetMapId(), GetPlayer()); + GetPlayer()->RelocateToHomebind(loc.mapid); + newMap = MapManager::Instance().CreateMap(loc.mapid, GetPlayer(), 0); } else GetPlayer()->Relocate(loc.coord_x, loc.coord_y, loc.coord_z, loc.orientation); @@ -80,22 +84,10 @@ void WorldSession::HandleMoveWorldportAckOpcode() GetPlayer()->SetMap(newMap); GetPlayer()->SendInitialPacketsBeforeAddToMap(); - // the CanEnter checks are done in TeleporTo but conditions may change - // while the player is in transit, for example the map may get full 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); - // teleport the player home - if(!GetPlayer()->TeleportTo(GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation())) - { - // the player must always be able to teleport home - sLog.outError("WORLD: failed to teleport player %s (%d) to homebind location %d, %f, %f, %f, %f!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), GetPlayer()->m_homebindMapId, GetPlayer()->m_homebindX, GetPlayer()->m_homebindY, GetPlayer()->m_homebindZ, GetPlayer()->GetOrientation()); - assert(false); - } - return; + sLog.outError("WORLD: failed to teleport player %s (%d) to map %d because of unknown reason!", GetPlayer()->GetName(), GetPlayer()->GetGUIDLow(), loc.mapid); + assert(false); } // battleground state prepare (in case join to BG), at relogin/tele player not invited diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 53f98214703..8a9a3e09be5 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1066,7 +1066,7 @@ bool Object::PrintIndexError(uint32 index, bool set) const } WorldObject::WorldObject() - : m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL), + : m_phaseMask(PHASEMASK_NORMAL), m_positionX(0.0f), m_positionY(0.0f), m_positionZ(0.0f), m_orientation(0.0f), m_currMap(NULL) , m_zoneScript(NULL) , m_isActive(false), IsTempWorldObject(false) @@ -1691,11 +1691,9 @@ void WorldObject::SendObjectDeSpawnAnim(uint64 guid) void WorldObject::SetMap(Map * map) { + assert (!m_currMap); 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 diff --git a/src/game/Object.h b/src/game/Object.h index 235b3fb6b38..732d9bc8944 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -407,7 +407,7 @@ class TRINITY_DLL_SPEC WorldObject : public Object void GetPosition( float &x, float &y, float &z ) const { x = m_positionX; y = m_positionY; z = m_positionZ; } void GetPosition( WorldLocation &loc ) const - { loc.mapid = m_mapId; GetPosition(loc.coord_x, loc.coord_y, loc.coord_z); loc.orientation = GetOrientation(); } + { loc.mapid = GetMapId(); GetPosition(loc.coord_x, loc.coord_y, loc.coord_z); loc.orientation = GetOrientation(); } void GetPosition(Position pos) const { pos[0] = m_positionX; pos[1] = m_positionY; pos[2] = m_positionZ; pos[3] = m_orientation; } float GetOrientation( ) const { return m_orientation; } @@ -439,8 +439,8 @@ class TRINITY_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; - uint32 GetMapId() const { return m_mapId; } - uint32 GetInstanceId() const { return m_InstanceId; } + uint32 GetMapId() const { return m_currMap ? m_currMap->GetId() : 0; } + uint32 GetInstanceId() const { return m_currMap ? m_currMap->GetInstanceId() : 0; } virtual void SetPhaseMask(uint32 newPhaseMask, bool update); uint32 GetPhaseMask() const { return m_phaseMask; } @@ -528,11 +528,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object // Low Level Packets void SendPlaySound(uint32 Sound, bool OnlySelf); - void SetMap(Map * map); + virtual void SetMap(Map * map); Map * GetMap() const { ASSERT(m_currMap); return m_currMap; } Map * FindMap() const { return m_currMap; } //used to check all object's GetMap() calls when object is not in world! - void ResetMap() { m_currMap = NULL; } + virtual void ResetMap() { assert(m_currMap); m_currMap = NULL; } //this function should be removed in nearest time... Map const* GetBaseMap() const; @@ -560,12 +560,11 @@ class TRINITY_DLL_SPEC WorldObject : public Object bool IsTempWorldObject; #ifdef MAP_BASED_RAND_GEN - // Object may not have map assigned - use global scope rand in that case - int32 irand(int32 min, int32 max) const { return FindMap() ? int32 (GetMap()->mtRand.randInt(max - min)) + min : ::irand(min, max); } - uint32 urand(uint32 min, uint32 max) const { return FindMap() ? GetMap()->mtRand.randInt(max - min) + min : ::urand(min, max); } - int32 rand32() const { return FindMap() ? GetMap()->mtRand.randInt(): ::rand32(); } - double rand_norm() const { return FindMap() ? GetMap()->mtRand.randExc(): ::rand_norm(); } - double rand_chance() const { return FindMap() ? GetMap()->mtRand.randExc(100.0): ::rand_chance(); } + int32 irand(int32 min, int32 max) const { int32 (GetMap()->mtRand.randInt(max - min)) + min; } + uint32 urand(uint32 min, uint32 max) const { GetMap()->mtRand.randInt(max - min) + min} + int32 rand32() const { GetMap()->mtRand.randInt()} + double rand_norm() const { GetMap()->mtRand.randExc()} + double rand_chance() const { GetMap()->mtRand.randExc(100.0)} #endif protected: @@ -574,17 +573,8 @@ class TRINITY_DLL_SPEC WorldObject : public Object bool m_isActive; ZoneScript *m_zoneScript; - //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: Map * m_currMap; //current object's Map location - - uint32 m_mapId; // object at map with map_id - uint32 m_InstanceId; // in map copy with instance id uint32 m_phaseMask; // in area phase state float m_positionX; diff --git a/src/game/ObjectAccessor.cpp b/src/game/ObjectAccessor.cpp index cd58d564106..b334ef8c5a8 100644 --- a/src/game/ObjectAccessor.cpp +++ b/src/game/ObjectAccessor.cpp @@ -268,7 +268,7 @@ ObjectAccessor::RemoveCorpse(Corpse *corpse) } void -ObjectAccessor::AddCorpse(Corpse *corpse) +ObjectAccessor::AddCorpse(Corpse *corpse, uint32 mapId, uint32 instanceId) { assert(corpse && corpse->GetType() != CORPSE_BONES); @@ -280,7 +280,7 @@ ObjectAccessor::AddCorpse(Corpse *corpse) CellPair cell_pair = Trinity::ComputeCellPair(corpse->GetPositionX(), corpse->GetPositionY()); uint32 cell_id = (cell_pair.y_coord*TOTAL_NUMBER_OF_CELLS_PER_MAP) + cell_pair.x_coord; - objmgr.AddCorpseCellData(corpse->GetMapId(), cell_id, corpse->GetOwnerGUID(), corpse->GetInstanceId()); + objmgr.AddCorpseCellData(mapId, cell_id, corpse->GetOwnerGUID(), instanceId); } void diff --git a/src/game/ObjectAccessor.h b/src/game/ObjectAccessor.h index fea928a54eb..2dd1b56641f 100644 --- a/src/game/ObjectAccessor.h +++ b/src/game/ObjectAccessor.h @@ -210,7 +210,7 @@ class MANGOS_DLL_DECL ObjectAccessor : public MaNGOS::Singleton<ObjectAccessor, Corpse* GetCorpseForPlayerGUID(uint64 guid); void RemoveCorpse(Corpse *corpse); - void AddCorpse(Corpse* corpse); + void AddCorpse(Corpse *corpse, uint32 mapId, uint32 instanceId); void AddCorpsesToGrid(GridPair const& gridpair,GridType& grid,Map* map); Corpse* ConvertCorpseForPlayer(uint64 player_guid, bool insignia = false); diff --git a/src/game/ObjectMgr.cpp b/src/game/ObjectMgr.cpp index 7557c23d072..d249c60a175 100644 --- a/src/game/ObjectMgr.cpp +++ b/src/game/ObjectMgr.cpp @@ -6483,14 +6483,16 @@ void ObjectMgr::LoadCorpses() uint32 guid = fields[result->GetFieldCount()-1].GetUInt32(); + uint32 mapId; + uint32 instanceId; Corpse *corpse = new Corpse; - if(!corpse->LoadFromDB(guid,fields)) + if(!corpse->LoadFromDB(guid,fields,mapId,instanceId)) { delete corpse; continue; } - ObjectAccessor::Instance().AddCorpse(corpse); + ObjectAccessor::Instance().AddCorpse(corpse,mapId,instanceId); ++count; } diff --git a/src/game/Pet.cpp b/src/game/Pet.cpp index 4071cfb50bb..05764beec11 100644 --- a/src/game/Pet.cpp +++ b/src/game/Pet.cpp @@ -1778,9 +1778,10 @@ bool Pet::IsPermanentPetFor(Player* owner) bool Pet::Create(uint32 guidlow, Map *map, uint32 phaseMask, uint32 Entry, uint32 pet_number) { + assert(map); SetMap(map); - SetPhaseMask(phaseMask,false); + SetPhaseMask(phaseMask,false); Object::_Create(guidlow, pet_number, HIGHGUID_PET); m_DBTableGuid = guidlow; diff --git a/src/game/Player.cpp b/src/game/Player.cpp index f96eff21012..8cd21e1ef48 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -316,10 +316,6 @@ Player::Player (WorldSession *session): Unit(), m_achievementMgr(this), m_reputa m_nextSave = sWorld.getConfig(CONFIG_INTERVAL_SAVE); - // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] - // this must help in case next save after mass player load after server startup - m_nextSave = urand(m_nextSave/2,m_nextSave*3/2); - clearResurrectRequestData(); memset(m_items, 0, sizeof(Item*)*PLAYER_SLOTS_COUNT); @@ -485,6 +481,10 @@ Player::~Player () // it must be unloaded already in PlayerLogout and accessed only for loggined player //m_social = NULL; + // Remove reference to map if still exists + if (FindMap()) + ResetMap(); + // Note: buy back item already deleted from DB when player was saved for(uint8 i = 0; i < PLAYER_SLOTS_COUNT; ++i) { @@ -548,7 +548,6 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 for (uint8 i = 0; i < PLAYER_SLOTS_COUNT; i++) m_items[i] = NULL; - SetLocationMapId(info->mapId); Relocate(info->positionX,info->positionY,info->positionZ); ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(class_); @@ -558,7 +557,7 @@ bool Player::Create( uint32 guidlow, const std::string& name, uint8 race, uint8 return false; } - SetMap(MapManager::Instance().CreateMap(info->mapId, this)); + SetMap(MapManager::Instance().CreateMap(info->mapId, this, 0)); uint8 powertype = cEntry->powerType; @@ -4360,7 +4359,7 @@ void Player::CreateCorpse() corpse->SaveToDB(); // register for player, but not show - ObjectAccessor::Instance().AddCorpse(corpse); + ObjectAccessor::Instance().AddCorpse(corpse, corpse->GetMapId(), corpse->GetInstanceId()); } void Player::SpawnCorpseBones() @@ -14253,7 +14252,12 @@ bool Player::MinimalLoadFromDB( QueryResult *result, uint32 guid ) m_name = fields[2].GetCppString(); Relocate(fields[3].GetFloat(),fields[4].GetFloat(),fields[5].GetFloat()); - SetLocationMapId(fields[6].GetUInt32()); + Map *map = MapManager::Instance().CreateMap(fields[6].GetUInt32(), this, 0); + SetMap(map); + + // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] + // this must help in case next save after mass player load after server startup + m_nextSave = urand(m_nextSave/2,m_nextSave*3/2); // the instance id is not needed at character enum @@ -14560,14 +14564,8 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) InitPrimaryProfessions(); // to max set before any spell loaded - // init saved position, and fix it later if problematic - uint32 transGUID = fields[31].GetUInt32(); - Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat()); - SetLocationMapId(fields[16].GetUInt32()); SetDifficulty(fields[39].GetUInt32()); // may be changed in _LoadGroup - SetLocationInstanceId(fields[47].GetFloat()); - _LoadGroup(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGROUP)); _LoadArenaTeamInfo(holder->GetResult(PLAYER_LOGIN_QUERY_LOADARENAINFO)); @@ -14596,35 +14594,42 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) _LoadBoundInstances(holder->GetResult(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES)); + // load player map related values + uint32 transGUID = fields[31].GetUInt32(); + Relocate(fields[13].GetFloat(),fields[14].GetFloat(),fields[15].GetFloat(),fields[17].GetFloat()); + uint32 mapId = fields[16].GetUInt32(); + uint32 instanceId = fields[41].GetFloat(); + std::string taxi_nodes = fields[38].GetCppString(); + + MapEntry const * mapEntry = sMapStore.LookupEntry(mapId); if(!IsPositionValid()) { sLog.outError("Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - RelocateToHomebind(); + RelocateToHomebind(mapId); transGUID = 0; + instanceId = 0; m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; m_movementInfo.t_z = 0.0f; m_movementInfo.t_o = 0.0f; } - - uint32 bgid = fields[41].GetUInt32(); - uint32 bgteam = fields[42].GetUInt32(); - - if(bgid) //saved in BattleGround + // Player was saved in Arena or Bg + else if (mapEntry && mapEntry->IsBattleGroundOrArena()) { + // Get Entry Point(bg master) or Homebind SetBattleGroundEntryPoint(fields[43].GetUInt32(),fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat()); - // check entry point and fix to homebind if need - MapEntry const* mapEntry = sMapStore.LookupEntry(m_bgEntryPoint.mapid); - if(!mapEntry || mapEntry->Instanceable() || !MapManager::IsValidMapCoord(m_bgEntryPoint)) + MapEntry const* bgEntry = sMapStore.LookupEntry(m_bgEntryPoint.mapid); + if(!bgEntry || bgEntry->Instanceable() || !MapManager::IsValidMapCoord(m_bgEntryPoint)) SetBattleGroundEntryPoint(m_homebindMapId,m_homebindX,m_homebindY,m_homebindZ,0.0f); - BattleGround *currentBg = sBattleGroundMgr.GetBattleGround(bgid, BATTLEGROUND_TYPE_NONE); - + // Bg still exists - join it! + BattleGround *currentBg = sBattleGroundMgr.GetBattleGround(instanceId, BATTLEGROUND_TYPE_NONE); if(currentBg && currentBg->IsPlayerInBattleGround(GetGUID())) { + uint32 bgteam = fields[42].GetUInt32(); BattleGroundQueueTypeId bgQueueTypeId = sBattleGroundMgr.BGQueueTypeId(currentBg->GetTypeID(), currentBg->GetArenaType()); AddBattleGroundQueueId(bgQueueTypeId); @@ -14637,34 +14642,21 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetInviteForBattleGroundQueueType(bgQueueTypeId,currentBg->GetInstanceID()); } + // Bg was not found - go to Entry Point else { + // Do not look for instance if bg not found + instanceId = 0; const WorldLocation& _loc = GetBattleGroundEntryPoint(); - SetLocationMapId(_loc.mapid); + mapId = _loc.mapid; Relocate(_loc.coord_x, _loc.coord_y, _loc.coord_z, _loc.orientation); - //RemoveArenaAuras(true); } } - else + else if (transGUID != 0) { - MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); - // if server restart after player save in BG or area - // player can have current coordinates in to BG/Arean map, fix this - if(!mapEntry || mapEntry->IsBattleGroundOrArena()) - { - // return to BG master - SetLocationMapId(fields[43].GetUInt32()); - Relocate(fields[44].GetFloat(),fields[45].GetFloat(),fields[46].GetFloat(),fields[47].GetFloat()); - - // check entry point and fix to homebind if need - mapEntry = sMapStore.LookupEntry(GetMapId()); - if(!mapEntry || mapEntry->IsBattleGroundOrArena() || !IsPositionValid()) - RelocateToHomebind(); - } - } + // There are no transports on instances + assert (!instanceId); - if (transGUID != 0) - { m_movementInfo.t_x = fields[27].GetFloat(); m_movementInfo.t_y = fields[28].GetFloat(); m_movementInfo.t_z = fields[29].GetFloat(); @@ -14680,7 +14672,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) guid,GetPositionX()+m_movementInfo.t_x,GetPositionY()+m_movementInfo.t_y, GetPositionZ()+m_movementInfo.t_z,GetOrientation()+m_movementInfo.t_o); - RelocateToHomebind(); + RelocateToHomebind(mapId); m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; @@ -14689,112 +14681,136 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) transGUID = 0; } - } - - if (transGUID != 0) - { - for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) + else { - if( (*iter)->GetGUIDLow() == transGUID) + for (MapManager::TransportSet::iterator iter = MapManager::Instance().m_Transports.begin(); iter != MapManager::Instance().m_Transports.end(); ++iter) { - MapEntry const* transMapEntry = sMapStore.LookupEntry((*iter)->GetMapId()); - // client without expansion support - if(GetSession()->Expansion() < transMapEntry->Expansion()) + if( (*iter)->GetGUIDLow() == transGUID) { - sLog.outDebug("Player %s using client without required expansion tried login at transport at non accessible map %u", GetName(), (*iter)->GetMapId()); + m_transport = *iter; + m_transport->AddPassenger(this); + mapId = (m_transport->GetMapId()); break; } - - m_transport = *iter; - m_transport->AddPassenger(this); - SetLocationMapId(m_transport->GetMapId()); - break; } - } - - if(!m_transport) - { - sLog.outError("Player (guidlow %d) have problems with transport guid (%u). Teleport to default race/class locations.", - guid,transGUID); + if(!m_transport) + { + sLog.outError("Player (guidlow %d) have problems with transport guid (%u). Teleport to default race/class locations.", + guid,transGUID); - RelocateToHomebind(); + RelocateToHomebind(mapId); - m_movementInfo.t_x = 0.0f; - m_movementInfo.t_y = 0.0f; - m_movementInfo.t_z = 0.0f; - m_movementInfo.t_o = 0.0f; + m_movementInfo.t_x = 0.0f; + m_movementInfo.t_y = 0.0f; + m_movementInfo.t_z = 0.0f; + m_movementInfo.t_o = 0.0f; - transGUID = 0; + transGUID = 0; + } } } - else // not transport case + else if (!taxi_nodes.empty()) // Taxi Flight path loaded from db { - MapEntry const* mapEntry = sMapStore.LookupEntry(GetMapId()); - // client without expansion support - if(GetSession()->Expansion() < mapEntry->Expansion()) + // There are no flightpaths in instances + assert (!instanceId); + + if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes,GetTeam())) + { + // problems with taxi path loading + TaxiNodesEntry const* nodeEntry = NULL; + if(uint32 node_id = m_taxi.GetTaxiSource()) + nodeEntry = sTaxiNodesStore.LookupEntry(node_id); + + if(!nodeEntry) // don't know taxi start node, to homebind + { + sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); + RelocateToHomebind(mapId); + } + else // have start node, to it + { + sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow()); + mapId = nodeEntry->map_id; + Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f); + } + } + // Taxi path loading succesfull + else if(uint32 node_id = m_taxi.GetTaxiSource()) { - sLog.outDebug("Player %s using client without required expansion tried login at non accessible map %u", GetName(), GetMapId()); - RelocateToHomebind(); + // save source node as recall coord to prevent recall and fall from sky + TaxiNodesEntry const* nodeEntry = sTaxiNodesStore.LookupEntry(node_id); + assert(nodeEntry); // checked in m_taxi.LoadTaxiDestinationsFromString + Relocate(nodeEntry->x,nodeEntry->y,nodeEntry->z,0); + mapId = nodeEntry->map_id; + // flight will started later } } - - // In some old saves players' instance id are not correctly ordered - // This fixes the crash. But it is not needed for a new db - if(InstanceSave *pSave = GetInstanceSave(GetMapId())) - if(pSave->GetInstanceId() != GetInstanceId()) - SetLocationInstanceId(pSave->GetInstanceId()); + // Map could be changed before + mapEntry = sMapStore.LookupEntry(mapId); + // client without expansion support + if(GetSession()->Expansion() < mapEntry->Expansion()) + { + sLog.outDebug("Player %s using client without required expansion tried login at non accessible map %u", GetName(), mapId); + RelocateToHomebind(mapId); + instanceId = 0; + } // NOW player must have valid map // load the player's map here if it's not already loaded - Map *map = MapManager::Instance().CreateMap(GetMapId(), this); + Map *map = MapManager::Instance().CreateMap(mapId, this, instanceId); if (!map) { - AreaTrigger const* at = objmgr.GetGoBackTrigger(GetMapId()); + instanceId = 0; + AreaTrigger const* at = objmgr.GetGoBackTrigger(mapId); if(at) { - SetLocationMapId(at->target_mapId); + sLog.outError("Player (guidlow %d) is teleported to gobacktrigger (Map: %u X: %f Y: %f Z: %f O: %f).",guid,mapId,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); Relocate(at->target_X, at->target_Y, at->target_Z, GetOrientation()); - sLog.outError("Player (guidlow %d) is teleported to gobacktrigger (Map: %u X: %f Y: %f Z: %f O: %f).",guid,GetMapId(),GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + mapId = at->target_mapId; } else { - RelocateToHomebind(); - sLog.outError("Player (guidlow %d) is teleported to home (Map: %u X: %f Y: %f Z: %f O: %f).",guid,GetMapId(),GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + sLog.outError("Player (guidlow %d) is teleported to home (Map: %u X: %f Y: %f Z: %f O: %f).",guid,mapId,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + RelocateToHomebind(mapId); } - map = MapManager::Instance().CreateMap(GetMapId(), this); + map = MapManager::Instance().CreateMap(mapId, this, 0); if(!map) { - sLog.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - delete result; - return false; - - /*SetMapId(info->mapId); + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); + mapId = info->mapId; Relocate(info->positionX,info->positionY,info->positionZ,0.0f); - - map = GetMap(); - if(!map) + sLog.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + map = MapManager::Instance().CreateMap(mapId, this, 0); + if (!map) { - sLog.outError("ERROR: Player (guidlow %d) have invalid coordinates (X: %f Y: %f Z: %f O: %f). Teleport to default race/class locations.",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); - sLog.outError("CRASH."); - assert(false); - }*/ + sLog.outError("ERROR: Player (guidlow %d) has invalid default map coordinates (X: %f Y: %f Z: %f O: %f). or instance couldn't be created",guid,GetPositionX(),GetPositionY(),GetPositionZ(),GetOrientation()); + delete result; + return false; + } } } - SetMap(map); - // 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(instanceId && !sInstanceSaveManager.GetInstanceSave(instanceId)) { - AreaTrigger const* at = objmgr.GetMapEntranceTrigger(GetMapId()); + AreaTrigger const* at = objmgr.GetMapEntranceTrigger(mapId); if(at) Relocate(at->target_X, at->target_Y, at->target_Z, at->target_Orientation); else - sLog.outError("Player %s(GUID: %u) logged in to a reset instance (map: %u) and there is no area-trigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), GetMapId()); + { + sLog.outError("Player %s(GUID: %u) logged in to a reset instance (map: %u) and there is no area-trigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), mapId); + RelocateToHomebind(mapId); + instanceId = 0; + } } + SetMap(map); + + // randomize first save time in range [CONFIG_INTERVAL_SAVE] around [CONFIG_INTERVAL_SAVE] + // this must help in case next save after mass player load after server startup + m_nextSave = urand(m_nextSave/2,m_nextSave*3/2); + SaveRecallPosition(); time_t now = time(NULL); @@ -14863,8 +14879,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(m_deathExpireTime > now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP) m_deathExpireTime = now+MAX_DEATH_COUNT*DEATH_EXPIRE_STEP-1; - std::string taxi_nodes = fields[38].GetCppString(); - delete result; // clear channel spell data (if saved at channel spell casting) @@ -14950,46 +14964,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) SetUInt32Value(PLAYER_CHOSEN_TITLE, 0); } - // Not finish taxi flight path - if(!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes,GetTeam())) - { - // problems with taxi path loading - TaxiNodesEntry const* nodeEntry = NULL; - if(uint32 node_id = m_taxi.GetTaxiSource()) - nodeEntry = sTaxiNodesStore.LookupEntry(node_id); - - if(!nodeEntry) // don't know taxi start node, to homebind - { - sLog.outError("Character %u have wrong data in taxi destination list, teleport to homebind.",GetGUIDLow()); - RelocateToHomebind(); - } - else // have start node, to it - { - sLog.outError("Character %u have too short taxi destination list, teleport to original node.",GetGUIDLow()); - SetLocationMapId(nodeEntry->map_id); - Relocate(nodeEntry->x, nodeEntry->y, nodeEntry->z,0.0f); - } - - //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(); - } - else if(uint32 node_id = m_taxi.GetTaxiSource()) - { - // save source node as recall coord to prevent recall and fall from sky - TaxiNodesEntry const* nodeEntry = sTaxiNodesStore.LookupEntry(node_id); - assert(nodeEntry); // checked in m_taxi.LoadTaxiDestinationsFromString - m_recallMap = nodeEntry->map_id; - m_recallX = nodeEntry->x; - m_recallY = nodeEntry->y; - m_recallZ = nodeEntry->z; - - // flight will started later - } - // has to be called after last Relocate() in Player::LoadFromDB SetFallInformation(0, GetPositionZ()); @@ -21412,3 +21386,15 @@ void Player::SendClearCooldown( uint32 spell_id, Unit* target ) data << uint64(target->GetGUID()); SendDirectMessage(&data); } + +void Player::ResetMap() +{ + // this may be called during Map::Update + // after decrement+unlink, ++m_mapRefIter will continue correctly + // when the first element of the list is being removed + // nocheck_prev will return the padding element of the RefManager + // instead of NULL in the case of prev + GetMap()->UpdateIteratorBack(this); + Unit::ResetMap(); + GetMapRef().unlink(); +} diff --git a/src/game/Player.h b/src/game/Player.h index 49d4c1346b9..c8fbe96049f 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2032,7 +2032,7 @@ class TRINITY_DLL_SPEC Player : public Unit float m_homebindX; float m_homebindY; float m_homebindZ; - void RelocateToHomebind() { SetLocationMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); } + void RelocateToHomebind(uint32 & newMap) { newMap = m_homebindMapId; Relocate(m_homebindX,m_homebindY,m_homebindZ); } // currently visible objects at player client typedef std::set<uint64> ClientGUIDs; @@ -2122,6 +2122,10 @@ class TRINITY_DLL_SPEC Player : public Unit GridReference<Player> &GetGridRef() { return m_gridRef; } MapReference &GetMapRef() { return m_mapRef; } + // Set map to player and add reference + void SetMap(Map * map) {Unit::SetMap(map); m_mapRef.link(map, this);} + void ResetMap(); + bool isAllowedToLoot(Creature* creature); DeclinedName const* GetDeclinedNames() const { return m_declinedname; } diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 254cb416cf5..2dca13cd08a 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -5501,8 +5501,7 @@ void Spell::EffectScriptEffect(uint32 effIndex) // normal DB scripted effect sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id); - if (m_caster->FindMap()) - m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); + m_caster->GetMap()->ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget); } void Spell::EffectSanctuary(uint32 /*i*/) diff --git a/src/game/Transports.cpp b/src/game/Transports.cpp index b2a89805ea9..25248b7b9d2 100644 --- a/src/game/Transports.cpp +++ b/src/game/Transports.cpp @@ -106,7 +106,7 @@ void MapManager::LoadTransports() m_TransportsByMap[*i].insert(t); //If we someday decide to use the grid to track transports, here: - t->SetMap(MapManager::Instance().CreateMap(mapid, t)); + t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0)); //t->GetMap()->Add<GameObject>((GameObject *)t); ++count; @@ -459,8 +459,12 @@ void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) //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); + //yes, you're right + + ResetMap(); + Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0); SetMap(newMap); + assert (GetMap()); if(oldMap != newMap) { |