/// WorldSession destructor WorldSession::~WorldSession() { //Playerbot mod: log out any PlayerBots owned in this WorldSession while(!m_playerBots.empty()) LogoutPlayerBot(m_playerBots.begin()->first, true); ///- unload player if not unloaded if (_player) LogoutPlayer (true); /// - If have unclosed socket, close it if (m_Socket) { m_Socket->CloseSocket (); m_Socket->RemoveReference (); m_Socket = NULL; } ///- empty incoming packet queue WorldPacket *packet = NULL; while (_recvQueue.next(packet)) delete packet; LoginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = %u;", GetAccountId()); }
void PlayerbotMgr::LogoutAllBots() { while (true) { PlayerBotMap::const_iterator itr = GetPlayerBotsBegin(); if (itr == GetPlayerBotsEnd()) break; Player* bot= itr->second; LogoutPlayerBot(bot->GetGUID()); } }
void PlayerbotMgr::LogoutAllBots() { while (true) { PlayerBotMap::const_iterator itr = GetPlayerBotsBegin(); if (itr == GetPlayerBotsEnd()) break; Player* bot = itr->second; LogoutPlayerBot(bot->GetObjectGuid()); } RemoveAllBotsFromGroup(); }
void PlayerbotMgr::LogoutAllBots() { while (true) { PlayerBotMap::const_iterator itr = GetPlayerBotsBegin(); if (itr == GetPlayerBotsEnd()) break; if (Player* bot = itr->second) { LogoutPlayerBot(bot->GetObjectGuid()); m_botCount--; } } RemoveAllBotsFromGroup(); ///-> If bot are logging out remove them group }
/// %Log the player out void WorldSession::LogoutPlayer(bool Save) { if (!_player) return; if (_player->IsMounted()) _player->Unmount(); // PlayerBot mod: log out all playerbots owned by this character //while(!m_playerBots.empty()) // LogoutPlayerBot(m_playerBots.begin()->first, Save); PlayerBotMap m_pBots; uint8 m_botCount = 0; for(PlayerBotMap::const_iterator itr = GetPlayerBotsBegin(); itr != GetPlayerBotsEnd(); ++itr) { Player *bot = itr->second; (m_pBots)[itr->first] = bot; ++m_botCount; } // Create a solo bind for player if player is currently in group in instance with all bots Group *m_Group = _player->GetGroup(); bool rebound = false; if(m_botCount > 0 && m_Group && m_botCount == m_Group->GetMembersCount()-1) if (InstanceSave *save = sInstanceSaveManager.GetInstanceSave(_player->GetInstanceId())) { _player->BindToInstance(save, false); save->SetCanReset(false); rebound = true; } for(PlayerBotMap::const_iterator itr2 = m_pBots.begin(); itr2 != m_pBots.end(); ++itr2) { Player *botPlayer = itr2->second; if (!botPlayer) continue; LogoutPlayerBot(botPlayer->GetGUID(), Save); } if (rebound) _player->m_InstanceValid = true; // finish pending transfers before starting the logout while (_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); m_playerLogout = true; m_playerSave = Save; if (_player) { sLFGMgr.Leave(_player); GetPlayer()->GetSession()->SendLfgUpdateParty(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); GetPlayer()->GetSession()->SendLfgUpdatePlayer(LFG_UPDATETYPE_REMOVED_FROM_QUEUE); GetPlayer()->GetSession()->SendLfgUpdateSearch(false); if (uint64 lguid = GetPlayer()->GetLootGUID()) DoLootRelease(lguid); ///- If the player just died before logging out, make him appear as a ghost //FIXME: logout must be delayed in case lost connection with client in time of combat if (_player->GetDeathTimer()) { _player->getHostileRefManager().deleteReferences(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } else if (!_player->getAttackers().empty()) { _player->CombatStop(); _player->getHostileRefManager().setOnlineOfflineState(false); _player->RemoveAllAurasOnDeath(); // build set of player who attack _player or who have pet attacking of _player std::set<Player*> aset; for (Unit::AttackerSet::const_iterator itr = _player->getAttackers().begin(); itr != _player->getAttackers().end(); ++itr) { Unit* owner = (*itr)->GetOwner(); // including player controlled case if (owner) { if (owner->GetTypeId() == TYPEID_PLAYER) aset.insert(owner->ToPlayer()); } else if ((*itr)->GetTypeId() == TYPEID_PLAYER) aset.insert((Player*)(*itr)); } _player->SetPvPDeath(!aset.empty()); _player->KillPlayer(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); // give honor to all attackers from set like group case for (std::set<Player*>::const_iterator itr = aset.begin(); itr != aset.end(); ++itr) (*itr)->RewardHonor(_player,aset.size()); // give bg rewards and update counters like kill by first from attackers // this can't be called for all attackers. if (!aset.empty()) if (BattleGround *bg = _player->GetBattleGround()) bg->HandleKillPlayer(_player,*aset.begin()); } else if (_player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) { // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION _player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT); //_player->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time _player->KillPlayer(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } //drop a flag if player is carrying it if (BattleGround *bg = _player->GetBattleGround()) bg->EventPlayerLoggedOut(_player); ///- Teleport to home if the player is in an invalid instance if ((!_player->m_InstanceValid && !_player->isGameMaster()) || (_player->IsPlayerbot() && _player->GetMap()->IsDungeon())) _player->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); sOutdoorPvPMgr.HandlePlayerLeaveZone(_player,_player->GetZoneId()); for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { if (BattleGroundQueueTypeId bgQueueTypeId = _player->GetBattleGroundQueueTypeId(i)) { _player->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(_player->GetGUID(), true); } } // Repop at GraveYard or other player far teleport will prevent saving player because of not present map // Teleport player immediately for correct player save while (_player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members Guild *guild = objmgr.GetGuildById(_player->GetGuildId()); if (guild) { guild->SetMemberStats(_player->GetGUID()); guild->UpdateLogoutTime(_player->GetGUID()); guild->BroadcastEvent(GE_SIGNED_OFF, _player->GetGUID(), 1, _player->GetName(), "", ""); } ///- Remove pet _player->RemovePet(NULL,PET_SAVE_AS_CURRENT, true); ///- empty buyback items and save the player in the database // some save parts only correctly work in case player present in map/player_lists (pets, etc) if (Save) { uint32 eslot; for (int j = BUYBACK_SLOT_START; j < BUYBACK_SLOT_END; ++j) { eslot = j - BUYBACK_SLOT_START; _player->SetUInt64Value(PLAYER_FIELD_VENDORBUYBACK_SLOT_1 + (eslot * 2), 0); _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_PRICE_1 + eslot, 0); _player->SetUInt32Value(PLAYER_FIELD_BUYBACK_TIMESTAMP_1 + eslot, 0); } _player->SaveToDB(); } ///- Leave all channels before player delete... _player->CleanupChannels(); ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. _player->UninviteFromGroup(); // remove player from the group if he is: // a) in group; b) not in raid group; c) logging out normally (not being kicked or disconnected) if ((_player->GetGroup() && !_player->GetGroup()->isRaidGroup() && m_Socket) || (_player->IsPlayerbot() && _player->GetGroup())) _player->RemoveFromGroup(); ///- Send update to group and reset stored max enchanting level if (_player->GetGroup()) { _player->GetGroup()->SendUpdate(); _player->GetGroup()->ResetMaxEnchantingLevel(); } ///- Broadcast a logout message to the player's friends sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ()); ///- Remove the player from the world // the player may not be in the world when logging out // e.g if he got disconnected during a transfer to another map // calls to GetMap in this case may cause crashes _player->CleanupsBeforeDelete(); sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow()); Map* _map = _player->GetMap(); uint32 guid = _player->GetGUIDLow(); _map->Remove(_player, true); SetPlayer(NULL); // deleted in Remove call ///- Send the 'logout complete' packet to the client WorldPacket data(SMSG_LOGOUT_COMPLETE, 0); SendPacket(&data); ///- Since each account can only have one online character at any given time, ensure all characters for active account are marked as offline //No SQL injection as AccountId is uint32 CharacterDatabase.PExecute("UPDATE characters SET online = 0 WHERE account = '%u'", guid); sLog.outDebug("SESSION: Sent SMSG_LOGOUT_COMPLETE Message"); } //Hook for OnLogout Event sScriptMgr.OnLogout(_player); m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; LogoutRequest(0); }
bool RandomPlayerbotMgr::ProcessBot(uint32 bot) { uint32 isValid = GetEventValue(bot, "add"); if (!isValid) { Player* player = GetPlayerBot(bot); if (!player || !player->GetGroup()) { sLog.outDetail("Bot %d expired", bot); SetEventValue(bot, "add", 0, 0); } return true; } if (!GetPlayerBot(bot)) { sLog.outDetail("Bot %d logged in", bot); AddPlayerBot(bot, 0); if (!GetEventValue(bot, "online")) { SetEventValue(bot, "online", 1, sPlayerbotAIConfig.minRandomBotInWorldTime); } return true; } Player* player = GetPlayerBot(bot); if (!player) return false; PlayerbotAI* ai = player->GetPlayerbotAI(); if (!ai) return false; if (player->GetGroup()) { sLog.outDetail("Skipping bot %d as it is in group", bot); return false; } if (player->IsDead()) { if (!GetEventValue(bot, "dead")) { sLog.outDetail("Setting dead flag for bot %d", bot); uint32 randomTime = urand(sPlayerbotAIConfig.minRandomBotReviveTime, sPlayerbotAIConfig.maxRandomBotReviveTime); SetEventValue(bot, "dead", 1, randomTime); SetEventValue(bot, "revive", 1, randomTime - 60); return false; } if (!GetEventValue(bot, "revive")) { sLog.outDetail("Reviving dead bot %d", bot); SetEventValue(bot, "dead", 0, 0); SetEventValue(bot, "revive", 0, 0); RandomTeleport(player, player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); return true; } return false; } uint32 randomize = GetEventValue(bot, "randomize"); if (!randomize) { sLog.outDetail("Randomizing bot %d", bot); Randomize(player); uint32 randomTime = urand(sPlayerbotAIConfig.minRandomBotRandomizeTime, sPlayerbotAIConfig.maxRandomBotRandomizeTime); ScheduleRandomize(bot, randomTime); return true; } uint32 logout = GetEventValue(bot, "logout"); if (!logout) { sLog.outDetail("Logging out bot %d", bot); LogoutPlayerBot(bot); SetEventValue(bot, "logout", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); return true; } uint32 teleport = GetEventValue(bot, "teleport"); if (!teleport) { sLog.outDetail("Random teleporting bot %d", bot); RandomTeleportForLevel(ai->GetBot()); SetEventValue(bot, "teleport", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); return true; } return false; }
bool RandomPlayerbotMgr::ProcessBot(uint32 bot) { uint32 isValid = GetEventValue(bot, "add"); if (!isValid) { Player* player = GetPlayerBot(bot); if (!player || !player->GetGroup()) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Bot %d expired", bot); SetEventValue(bot, "add", 0, 0); } return true; } if (!GetPlayerBot(bot)) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Bot %d logged in", bot); AddPlayerBot(bot, 0); if (!GetEventValue(bot, "online")) { SetEventValue(bot, "online", 1, sPlayerbotAIConfig.minRandomBotInWorldTime); } return true; } Player* player = GetPlayerBot(bot); if (!player) return false; PlayerbotAI* ai = player->GetPlayerbotAI(); if (!ai) return false; if (player->GetGroup()) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Skipping bot %d as it is in group", bot); return false; } if (player->isDead()) { if (!GetEventValue(bot, "dead")) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Setting dead flag for bot %d", bot); uint32 randomTime = urand(sPlayerbotAIConfig.minRandomBotReviveTime, sPlayerbotAIConfig.maxRandomBotReviveTime); SetEventValue(bot, "dead", 1, randomTime); SetEventValue(bot, "revive", 1, randomTime - 60); return false; } if (!GetEventValue(bot, "revive")) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Reviving dead bot %d", bot); SetEventValue(bot, "dead", 0, 0); SetEventValue(bot, "revive", 0, 0); RandomTeleport(player, player->GetMapId(), player->GetPositionX(), player->GetPositionY(), player->GetPositionZ()); return true; } return false; } if (player->GetGuild() && player->GetGuild()->GetLeaderGUID() == player->GetGUID()) { for (vector<Player*>::iterator i = players.begin(); i != players.end(); ++i) sGuildTaskMgr.Update(*i, player); } uint32 randomize = GetEventValue(bot, "randomize"); if (!randomize) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Randomizing bot %d", bot); Randomize(player); uint32 randomTime = urand(sPlayerbotAIConfig.minRandomBotRandomizeTime, sPlayerbotAIConfig.maxRandomBotRandomizeTime); ScheduleRandomize(bot, randomTime); return true; } uint32 logout = GetEventValue(bot, "logout"); if (!logout) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Logging out bot %d", bot); LogoutPlayerBot(bot); SetEventValue(bot, "logout", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); return true; } uint32 teleport = GetEventValue(bot, "teleport"); if (!teleport) { sLog->outMessage("playerbot", LOG_LEVEL_INFO, "Random teleporting bot %d", bot); RandomTeleportForLevel(ai->GetBot()); SetEventValue(bot, "teleport", 1, sPlayerbotAIConfig.maxRandomBotInWorldTime); return true; } return false; }