void WorldSession::LogoutPlayer(bool Save) { Player* pPlayer = GetPlayer(); if (_loggingOut) return; _loggingOut = true; if (_player != NULL) { _player->SetFaction(_player->GetInitialFactionId()); objmgr.RemovePlayer(_player); _player->ok_to_remove = true; sHookInterface.OnLogout(pPlayer); if (_player->DuelingWith) _player->DuelingWith->EndDuel(DUEL_WINNER_RETREAT); if (_player->m_currentLoot && _player->IsInWorld()) { Object* obj = _player->GetMapMgr()->_GetObject(_player->m_currentLoot); if (obj != NULL) { switch (obj->getObjectTypeId()) { case TYPEID_UNIT: static_cast <Creature*>(obj)->loot.looters.erase(_player->getGuidLow()); break; case TYPEID_GAMEOBJECT: GameObject* go = static_cast<GameObject*>(obj); if (!go->IsLootable()) break; GameObject_Lootable* pLGO = static_cast<GameObject_Lootable*>(go); pLGO->loot.looters.erase(_player->getGuidLow()); break; } } } #ifndef GM_TICKET_MY_MASTER_COMPATIBLE GM_Ticket* ticket = objmgr.GetGMTicketByPlayer(_player->getGuid()); if (ticket != NULL) { // Send status change to gm_sync_channel Channel* chn = channelmgr.GetChannel(sWorld.getGmClientChannel().c_str(), _player); if (chn) { std::stringstream ss; ss << "GmTicket:" << GM_TICKET_CHAT_OPCODE_ONLINESTATE; ss << ":" << ticket->guid; ss << ":0"; chn->Say(_player, ss.str().c_str(), NULL, true); } } #endif // part channels _player->CleanupChannels(); auto transport = _player->GetTransport(); if (transport != nullptr) { transport->RemovePassenger(_player); } // cancel current spell for (uint8_t i = 0; i < CURRENT_SPELL_MAX; ++i) { if (_player->getCurrentSpell(CurrentSpellType(i)) != nullptr) _player->interruptSpellWithSpellType(CurrentSpellType(i)); } _player->Social_TellFriendsOffline(); // Decrement the global player count sWorld.decrementPlayerCount(_player->GetTeam()); if (_player->m_bgIsQueued) BattlegroundManager.RemovePlayerFromQueues(_player); // Repop or Resurrect and remove from battlegrounds if (_player->m_bg) { if (pPlayer->getDeathState() == JUST_DIED) pPlayer->RemoteRevive(); if (pPlayer->getDeathState() != ALIVE) pPlayer->ResurrectPlayer(); _player->m_bg->RemovePlayer(_player, true); } else if (_player->IsDead() && _player->getDeathState() == JUST_DIED) _player->RepopRequestedPlayer(); // Issue a message telling all guild members that this player signed // off #if VERSION_STRING != Cata if (_player->IsInGuild()) { Guild* pGuild = _player->m_playerInfo->guild; if (pGuild != NULL) pGuild->LogGuildEvent(GE_SIGNED_OFF, 1, _player->GetName()); } #endif _player->GetItemInterface()->EmptyBuyBack(); _player->GetItemInterface()->removeLootableItems(); // Save HP/Mana _player->load_health = _player->getHealth(); _player->load_mana = _player->GetPower(POWER_TYPE_MANA); _player->summonhandler.RemoveAllSummons(); _player->DismissActivePets(); // _player->SaveAuras(); if (Save) _player->SaveToDB(false); // Dismounting with RemoveAllAuras may in certain cases add a player // aura, // which can result in a nice crash during shutdown. Therefore let's // dismount on logout. // Ofc if the player was mounted on login they will be still mounted // ;) _player->Dismount(); _player->RemoveAllAuras(); if (_player->IsInWorld()) _player->RemoveFromWorld(); _player->m_playerInfo->m_loggedInPlayer = NULL; if (_player->m_playerInfo->m_Group != NULL) _player->m_playerInfo->m_Group->Update(); // Remove the "player locked" flag, to allow movement on next login GetPlayer()->removeUnitFlags(UNIT_FLAG_LOCK_PLAYER); // Save Honor Points // _player->SaveHonorFields(); // Update any dirty account_data fields. bool dirty = false; if (worldConfig.server.useAccountData) { std::stringstream ss; ss << "UPDATE account_data SET "; for (uint32 ui = 0; ui < 8; ui++) { if (sAccountData[ui].bIsDirty) { if (dirty) ss << ","; ss << "uiconfig" << ui << "=\""; if (sAccountData[ui].data) { CharacterDatabase.EscapeLongString(sAccountData[ui].data, sAccountData[ui].sz, ss); // ss.write(sAccountData[ui].data,sAccountData[ui].sz); } ss << "\""; dirty = true; sAccountData[ui].bIsDirty = false; } } if (dirty) { ss << " WHERE acct=" << _accountId << ";"; CharacterDatabase.ExecuteNA(ss.str().c_str()); } } delete _player; _player = NULL; OutPacket(SMSG_LOGOUT_COMPLETE, 0, NULL); LOG_DEBUG("SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); } _loggingOut = false; SetLogoutTimer(0); }
void WorldSession::LogoutPlayer(bool Save) { Player* pPlayer = GetPlayer(); if( _loggingOut ) return; _loggingOut = true; if( _player != NULL ) { sHookInterface.OnLogout( pPlayer ); if( _player->DuelingWith ) _player->EndDuel( DUEL_WINNER_RETREAT ); if( _player->m_currentLoot && _player->IsInWorld() ) { Object* obj = _player->GetMapMgr()->_GetObject( _player->m_currentLoot ); if( obj != NULL ) obj->m_loot.looters.erase(_player->GetLowGUID()); } // part channels _player->CleanupChannels(); if( _player->m_CurrentTransporter != NULL ) _player->m_CurrentTransporter->RemovePlayer( _player ); // cancel current spell if( _player->m_currentSpell != NULL ) _player->m_currentSpell->cancel(); _player->Social_TellFriendsOffline(); if( _player->GetTeam() == 1 ) { if( sWorld.HordePlayers ) sWorld.HordePlayers--; } else { if( sWorld.AlliancePlayers ) sWorld.AlliancePlayers--; } if( _player->m_bg ) _player->m_bg->RemovePlayer( _player, true ); if( _player->m_bgIsQueued ) BattlegroundManager.RemovePlayerFromQueues( _player ); //Duel Cancel on Leave if( _player->DuelingWith != NULL ) _player->EndDuel( DUEL_WINNER_RETREAT ); //Issue a message telling all guild members that this player signed off if( _player->IsInGuild() ) { Guild* pGuild = _player->m_playerInfo->guild; if( pGuild != NULL ) pGuild->LogGuildEvent( GUILD_EVENT_HASGONEOFFLINE, 1, _player->GetName() ); } _player->GetItemInterface()->EmptyBuyBack(); sLfgMgr.RemovePlayerFromLfgQueues( _player ); // Save HP/Mana _player->load_health = _player->GetUInt32Value( UNIT_FIELD_HEALTH ); _player->load_mana = _player->GetUInt32Value( UNIT_FIELD_POWER1 ); objmgr.RemovePlayer( _player ); _player->ok_to_remove = true; if( _player->GetSummon() != NULL ) _player->GetSummon()->Remove( false, true, false ); //_player->SaveAuras(); if( Save ) _player->SaveToDB(false); _player->RemoveAllAuras(); if( _player->IsInWorld() ) _player->RemoveFromWorld(); _player->m_playerInfo->m_loggedInPlayer = NULL; if( _player->m_playerInfo->m_Group != NULL ) _player->m_playerInfo->m_Group->Update(); // Remove the "player locked" flag, to allow movement on next login GetPlayer()->RemoveFlag( UNIT_FIELD_FLAGS, UNIT_FLAG_LOCK_PLAYER ); // Save Honor Points //_player->SaveHonorFields(); // Update any dirty account_data fields. bool dirty = false; if( sWorld.m_useAccountData ) { std::stringstream ss; ss << "UPDATE account_data SET "; for(uint32 ui=0;ui<8;ui++) { if(sAccountData[ui].bIsDirty) { if(dirty) ss <<","; ss << "uiconfig"<< ui <<"=\""; if(sAccountData[ui].data) { CharacterDatabase.EscapeLongString(sAccountData[ui].data, sAccountData[ui].sz, ss); //ss.write(sAccountData[ui].data,sAccountData[ui].sz); } ss << "\""; dirty = true; sAccountData[ui].bIsDirty = false; } } if(dirty) { ss <<" WHERE acct="<< _accountId <<";"; CharacterDatabase.ExecuteNA(ss.str().c_str()); } } delete _player; _player = NULL; OutPacket(SMSG_LOGOUT_COMPLETE, 0, NULL); DEBUG_LOG( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); } _loggingOut = false; SetLogoutTimer(0); }
void WorldSession::LogoutPlayer(bool Save) { if(_loggingOut) return; _loggingOut = true; if (_player) { if(_player->m_currentLoot) { switch(_player->m_currentLoot->GetTypeId()) { case TYPEID_UNIT: ((Creature*)_player->m_currentLoot)->loot.looters.erase(_player); break; case TYPEID_GAMEOBJECT: ((GameObject*)_player->m_currentLoot)->loot.looters.erase(_player); break; } } if(_player->m_CurrentTransporter) _player->m_CurrentTransporter->RemovePlayer(_player); for(uint32 x=0;x<4;x++) { if(_player->m_TotemSlots[x]) _player->m_TotemSlots[x]->TotemExpire(); if(_player->m_ObjectSlots[x]) _player->m_ObjectSlots[x]->Expire(); } // cancel current spell if(_player->m_currentSpell) _player->m_currentSpell->cancel(); sSocialMgr.LoggedOut(_player); // messages if(HasPermissions()) { sWorld.BroadcastExtendedMessage(this, "[SM:GMLOGOUT]%s", _player->GetName()); } if(_player->GetTeam() == 1) sWorld.HordePlayers--; else sWorld.AlliancePlayers--; // send info sWorld.BroadcastExtendedMessage(0, "[SM:INFO:%u:%u]", sWorld.HordePlayers, sWorld.AlliancePlayers); //Duel Cancel on Leave if(_player->DuelingWith != NULL) _player->EndDuel(DUEL_WINNER_RETREAT); // wipe our attacker list and target list _player->clearAttackers(true); //Issue a message telling all guild members that this player signed off if(_player->IsInGuild()) { Guild *pGuild = objmgr.GetGuild( _player->GetGuildId() ); if(pGuild) { //Update Offline info pGuild->GuildMemberLogoff(_player); WorldPacket data(SMSG_GUILD_EVENT, 11+strlen(_player->GetName())); data << uint8(GUILD_EVENT_HASGONEOFFLINE); data << uint8(0x01); data << _player->GetName(); data << _player->GetGUID(); pGuild->SendMessageToGuild(0,&data,G_MSGTYPE_ALL); } } _player->GetItemInterface()->EmptyBuyBack(); // Remove from BG if(_player->GetCurrentBattleground() != NULL) { _player->GetCurrentBattleground()->RemovePlayer(_player, false, false, false); } // Remove ourself from a group if (_player->InGroup()) { Group *group = _player->GetGroup(); if(group) group->RemovePlayer(_player); } for(int i=0;i<3;++i) { if(_player->LfgDungeonId[i] != 0) sLfgMgr.RemoveFromLfgQueue(_player,_player->LfgDungeonId[i]); } if(Save) { // Save the player _player->SaveToDB(); } std::stringstream ss1; ss1 << "UPDATE characters SET online = 0 where guid = " << _player->GetGUIDLow(); sDatabase.Execute(ss1.str().c_str()); if(_player->IsInWorld()) //hovering in char selection { // Relocate session to -1 map. Relocate(_player->m_mapMgr, NULL); sLog.outDebug( "SESSION: removing player from world" ); _player->RemoveFromWorld(); } // Remove the "player locked" flag, to allow movement on next login if ( GetPlayer( )->GetUInt32Value(UNIT_FIELD_FLAGS) & U_FIELD_FLAG_LOCK_PLAYER ) GetPlayer( )->RemoveFlag( UNIT_FIELD_FLAGS, U_FIELD_FLAG_LOCK_PLAYER ); _player->RemoveAllAuras(); if(_player->GetSummon() != NULL) { _player->GetSummon()->Remove(); } if(_player->critterPet) { _player->critterPet->m_BeingRemoved = true; if(_player->critterPet->IsInWorld()) _player->critterPet->RemoveFromWorld(); sObjHolder.Delete<Creature>(_player->critterPet); _player->critterPet = NULL; } // Update any dirty account_data fields. /*bool dirty=false; std::stringstream ss; ss << "UPDATE accounts SET "; for(uint32 ui=0;ui<8;ui++) { if(sAccountData[ui].bIsDirty) { if(dirty) ss <<","; ss << "uiconfig"<< ui <<"=\""; if(sAccountData[ui].data) ss.write(sAccountData[ui].data,sAccountData[ui].sz); ss << "\""; dirty=true; } } if(dirty) { ss <<" WHERE acct="<< _accountId <<";"; sLogonDatabase.Execute(ss.str().c_str()); }*/ sObjHolder.Delete(_player); _player = NULL; OutPacket(SMSG_LOGOUT_COMPLETE, 0, NULL); sLog.outDebug( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); } _loggingOut = false; SetLogoutTimer(0); }