diff --git a/src/game/BattleGround.cpp b/src/game/BattleGround.cpp index 9a69a69c8..07658b7c2 100644 --- a/src/game/BattleGround.cpp +++ b/src/game/BattleGround.cpp @@ -849,9 +849,7 @@ void BattleGround::RemovePlayerAtLeave(uint64 guid, bool Transport, bool SendPac plr->SetBGTeam(0); if(Transport) - { - plr->TeleportTo(plr->GetBattleGroundEntryPointMap(), plr->GetBattleGroundEntryPointX(), plr->GetBattleGroundEntryPointY(), plr->GetBattleGroundEntryPointZ(), plr->GetBattleGroundEntryPointO()); - } + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); // Log sLog.outDetail("BATTLEGROUND: Removed player %s from BattleGround.", plr->GetName()); diff --git a/src/game/BattleGroundHandler.cpp b/src/game/BattleGroundHandler.cpp index 388d68d1e..26ed16dce 100644 --- a/src/game/BattleGroundHandler.cpp +++ b/src/game/BattleGroundHandler.cpp @@ -462,7 +462,7 @@ void WorldSession::HandleBattleGroundPlayerPortOpcode( WorldPacket &recv_data ) // bg->AddPlayer(_player,team); sLog.outDebug("Battleground: player %s (%u) joined battle for bg %u, bgtype %u, queue type %u.",_player->GetName(),_player->GetGUIDLow(),bg->GetInstanceID(),bg->GetTypeID(),bgQueueTypeId); break; - case 0: // leave queue + case 0: // leave queue queueSlot = _player->GetBattleGroundQueueIndex(bgQueueTypeId); /* if player leaves rated arena match before match start, it is counted as he played but he lost diff --git a/src/game/Level1.cpp b/src/game/Level1.cpp index 76c4b871d..0d2f24e6c 100644 --- a/src/game/Level1.cpp +++ b/src/game/Level1.cpp @@ -382,6 +382,8 @@ bool ChatHandler::HandleNamegoCommand(const char* args) // all's well, set bg id // when porting out from the bg, it will be reset to 0 chr->SetBattleGroundId(m_session->GetPlayer()->GetBattleGroundId()); + // remember current position as entry point for return at bg end teleportation + chr->SetBattleGroundEntryPoint(chr->GetMapId(),chr->GetPositionX(),chr->GetPositionY(),chr->GetPositionZ(),chr->GetOrientation()); } else if(pMap->IsDungeon()) { @@ -498,6 +500,8 @@ bool ChatHandler::HandleGonameCommand(const char* args) // all's well, set bg id // when porting out from the bg, it will be reset to 0 _player->SetBattleGroundId(chr->GetBattleGroundId()); + // remember current position as entry point for return at bg end teleportation + _player->SetBattleGroundEntryPoint(_player->GetMapId(),_player->GetPositionX(),_player->GetPositionY(),_player->GetPositionZ(),_player->GetOrientation()); } else if(cMap->IsDungeon() && cMap->Instanceable()) { diff --git a/src/game/Map.cpp b/src/game/Map.cpp index 9244b6d27..f6cd24481 100644 --- a/src/game/Map.cpp +++ b/src/game/Map.cpp @@ -1887,12 +1887,14 @@ void BattleGroundMap::UnloadAll(bool pForce) { while(HavePlayers()) { - Player * plr = m_mapRefManager.getFirst()->getSource(); - if(plr) (plr)->TeleportTo(plr->m_homebindMapId, plr->m_homebindX, plr->m_homebindY, plr->m_homebindZ, plr->GetOrientation()); - // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. - // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop - // note that this remove is not needed if the code works well in other places - plr->GetMapRef().unlink(); + if(Player * plr = m_mapRefManager.getFirst()->getSource()) + { + plr->TeleportTo(plr->GetBattleGroundEntryPoint()); + // TeleportTo removes the player from this map (if the map exists) -> calls BattleGroundMap::Remove -> invalidates the iterator. + // just in case, remove the player from the list explicitly here as well to prevent a possible infinite loop + // note that this remove is not needed if the code works well in other places + plr->GetMapRef().unlink(); + } } Map::UnloadAll(pForce); diff --git a/src/game/MapManager.h b/src/game/MapManager.h index cb4c469a6..677c26120 100644 --- a/src/game/MapManager.h +++ b/src/game/MapManager.h @@ -94,6 +94,11 @@ class MANGOS_DLL_DECL MapManager : public MaNGOS::SingletonGetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) return false; - } InitPrimaryProffesions(); // to max set before any spell loaded + // init saved position, and fix it later if problematic uint32 transGUID = fields[24].GetUInt32(); Relocate(fields[6].GetFloat(),fields[7].GetFloat(),fields[8].GetFloat(),fields[10].GetFloat()); SetMapId(fields[9].GetUInt32()); @@ -14147,9 +14144,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) if(!IsPositionValid()) { 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()); - - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); transGUID = 0; @@ -14159,24 +14154,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_movementInfo.t_o = 0.0f; } - // load the player's map here if it's not already loaded - Map *map = GetMap(); - // 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(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId())) - { - AreaTrigger const* at = objmgr.GetMapEntranceTrigger(GetMapId()); - 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 aretrigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), GetMapId()); - } - - SaveRecallPosition(); - if (transGUID != 0) { m_movementInfo.t_x = fields[20].GetFloat(); @@ -14194,8 +14171,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); - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; @@ -14224,8 +14200,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) sLog.outError("ERROR: Player (guidlow %d) have invalid transport guid (%u). Teleport to default race/class locations.", guid,transGUID); - SetMapId(info->mapId); - Relocate(info->positionX,info->positionY,info->positionZ,0.0f); + RelocateToHomebind(); m_movementInfo.t_x = 0.0f; m_movementInfo.t_y = 0.0f; @@ -14236,6 +14211,26 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) } } + // NOW player must have valid map + // load the player's map here if it's not already loaded + Map *map = GetMap(); + + // 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(GetInstanceId() && !sInstanceSaveManager.GetInstanceSave(GetInstanceId())) + { + AreaTrigger const* at = objmgr.GetMapEntranceTrigger(GetMapId()); + 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 aretrigger leading to this map. Thus he can't be ported back to the entrance. This _might_ be an exploit attempt.", GetName(), GetGUIDLow(), GetMapId()); + } + + SaveRecallPosition(); + time_t now = time(NULL); time_t logoutTime = time_t(fields[16].GetUInt64()); @@ -14382,9 +14377,6 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) m_social = sSocialMgr.LoadFromDB(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSOCIALLIST), GetGUIDLow()); - if(!_LoadHomeBind(holder->GetResult(PLAYER_LOGIN_QUERY_LOADHOMEBIND))) - return false; - // check PLAYER_CHOSEN_TITLE compatibility with PLAYER__FIELD_KNOWN_TITLES // note: PLAYER__FIELD_KNOWN_TITLES updated at quest status loaded if(uint32 curTitle = GetUInt32Value(PLAYER_CHOSEN_TITLE)) @@ -14404,8 +14396,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder ) 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()); - SetMapId(m_homebindMapId); - Relocate( m_homebindX, m_homebindY, m_homebindZ,0.0f); + RelocateToHomebind(); SaveRecallPosition(); // save as recall also to prevent recall and fall from sky } else // have start node, to it @@ -15432,6 +15423,13 @@ void Player::ConvertInstancesToGroup(Player *player, Group *group, uint64 player bool Player::_LoadHomeBind(QueryResult *result) { + PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); + if(!info) + { + sLog.outError("Player have incorrect race/class pair. Can't be loaded."); + return false; + } + bool ok = false; //QueryResult *result = CharacterDatabase.PQuery("SELECT map,zone,position_x,position_y,position_z FROM character_homebind WHERE guid = '%u'", GUID_LOPART(playerGuid)); if (result) @@ -15456,9 +15454,6 @@ bool Player::_LoadHomeBind(QueryResult *result) if(!ok) { - PlayerInfo const *info = objmgr.GetPlayerInfo(getRace(), getClass()); - if(!info) return false; - m_homebindMapId = info->mapId; m_homebindZoneId = info->zoneId; m_homebindX = info->positionX; diff --git a/src/game/Player.h b/src/game/Player.h index 65aee5262..534456e40 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -1943,18 +1943,10 @@ class MANGOS_DLL_SPEC Player : public Unit return true; return false; } - uint32 GetBattleGroundEntryPointMap() const { return m_bgEntryPointMap; } - float GetBattleGroundEntryPointX() const { return m_bgEntryPointX; } - float GetBattleGroundEntryPointY() const { return m_bgEntryPointY; } - float GetBattleGroundEntryPointZ() const { return m_bgEntryPointZ; } - float GetBattleGroundEntryPointO() const { return m_bgEntryPointO; } + WorldLocation const& GetBattleGroundEntryPoint() const { return m_bgEntryPoint; } void SetBattleGroundEntryPoint(uint32 Map, float PosX, float PosY, float PosZ, float PosO ) { - m_bgEntryPointMap = Map; - m_bgEntryPointX = PosX; - m_bgEntryPointY = PosY; - m_bgEntryPointZ = PosZ; - m_bgEntryPointO = PosO; + m_bgEntryPoint = WorldLocation(Map,PosX,PosY,PosZ,PosO); } void SetBGTeam(uint32 team) { m_bgTeam = team; } @@ -2049,6 +2041,7 @@ class MANGOS_DLL_SPEC Player : public Unit float m_homebindX; float m_homebindY; float m_homebindZ; + void RelocateToHomebind() { SetMapId(m_homebindMapId); Relocate(m_homebindX,m_homebindY,m_homebindZ); } // currently visible objects at player client typedef std::set ClientGUIDs; @@ -2161,11 +2154,7 @@ class MANGOS_DLL_SPEC Player : public Unit uint32 invitedToInstance; }; BgBattleGroundQueueID_Rec m_bgBattleGroundQueueID[PLAYER_MAX_BATTLEGROUND_QUEUES]; - uint32 m_bgEntryPointMap; - float m_bgEntryPointX; - float m_bgEntryPointY; - float m_bgEntryPointZ; - float m_bgEntryPointO; + WorldLocation m_bgEntryPoint; std::set m_bgAfkReporter; uint8 m_bgAfkReportedCount; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 28cff7f43..a1fd1f711 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7253" + #define REVISION_NR "7254" #endif // __REVISION_NR_H__