void WorldPvPTF::HandleObjectiveComplete(ObjectGuidSet m_sPlayersSet, uint32 uiEventId) { for (uint8 i = 0; i < MAX_TF_TOWERS; ++i) { for (uint8 j = 0; j < 4; ++j) { if (uiEventId == aTerokkarTowerEvents[i][j].uiEventEntry) { for (ObjectGuidSet::iterator itr = m_sPlayersSet.begin(); itr != m_sPlayersSet.end(); ++itr) { if (!(*itr)) continue; Player* pPlayer = sObjectMgr.GetPlayer(*itr); if (!pPlayer) continue; pPlayer->AreaExploredOrEventHappens(pPlayer->GetTeam() == ALLIANCE ? QUEST_SPIRITS_OF_AUCHINDOUM_ALLY : QUEST_SPIRITS_OF_AUCHINDOUM_HORDE); } } } } }
/// %Log the player out void WorldSession::LogoutPlayer(bool Save) { // finish pending transfers before starting the logout while(_player && _player->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); m_playerLogout = true; m_playerSave = Save; if (_player) { // Playerbot mod: log out all player bots owned by this toon if (GetPlayer()->GetPlayerbotMgr()) GetPlayer()->GetPlayerbotMgr()->LogoutAllBots(); sLog.outChar("Account: %d (IP: %s) Logout Character:[%s] (guid: %u)", GetAccountId(), GetRemoteAddress().c_str(), _player->GetName() ,_player->GetGUIDLow()); if (ObjectGuid lootGuid = GetPlayer()->GetLootGuid()) DoLootRelease(lootGuid); ///- 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 (GetPlayer()->GetDeathTimer()) { GetPlayer()->getHostileRefManager().deleteReferences(); GetPlayer()->BuildPlayerRepop(); GetPlayer()->RepopAtGraveyard(); } else if (GetPlayer()->IsInCombat() && GetPlayer()->GetMap()) { GetPlayer()->CombatStop(); GetPlayer()->getHostileRefManager().setOnlineOfflineState(false); GetPlayer()->RemoveAllAurasOnDeath(); // build set of player who attack _player or who have pet attacking of _player std::set<Player*> aset; ObjectGuidSet attackers = GetPlayer()->GetMap()->GetAttackersFor(GetPlayer()->GetObjectGuid()); for (ObjectGuidSet::const_iterator itr = attackers.begin(); itr != attackers.end();) { Unit* attacker = GetPlayer()->GetMap()->GetUnit(*itr++); if (!attacker) continue; Unit* owner = attacker->GetOwner(); // including player controlled case if(owner) { if(owner->GetTypeId() == TYPEID_PLAYER) aset.insert((Player*)owner); } else if(attacker->GetTypeId() == TYPEID_PLAYER) aset.insert((Player*)(attacker)); } GetPlayer()->SetPvPDeath(!aset.empty()); GetPlayer()->KillPlayer(); GetPlayer()->BuildPlayerRepop(); GetPlayer()->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(GetPlayer(),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 = GetPlayer()->GetBattleGround()) bg->HandleKillPlayer(GetPlayer(),*aset.begin()); } else if(GetPlayer()->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION)) { // this will kill character by SPELL_AURA_SPIRIT_OF_REDEMPTION GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_MOD_SHAPESHIFT); //GetPlayer()->SetDeathPvP(*); set at SPELL_AURA_SPIRIT_OF_REDEMPTION apply time GetPlayer()->KillPlayer(); GetPlayer()->BuildPlayerRepop(); GetPlayer()->RepopAtGraveyard(); } else if (GetPlayer()->HasPendingBind()) { GetPlayer()->RepopAtGraveyard(); GetPlayer()->SetPendingBind(NULL, 0); } //drop a flag if player is carrying it if(BattleGround *bg = GetPlayer()->GetBattleGround()) bg->EventPlayerLoggedOut(GetPlayer()); ///- Teleport to home if the player is in an invalid instance if(!GetPlayer()->m_InstanceValid && !GetPlayer()->isGameMaster()) { GetPlayer()->TeleportToHomebind(); //this is a bad place to call for far teleport because we need player to be in world for successful logout //maybe we should implement delayed far teleport logout? } // FG: finish pending transfers after starting the logout // this should fix players beeing able to logout and login back with full hp at death position while(GetPlayer()->IsBeingTeleportedFar()) HandleMoveWorldportAckOpcode(); for (int i=0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i) { if(BattleGroundQueueTypeId bgQueueTypeId = GetPlayer()->GetBattleGroundQueueTypeId(i)) { GetPlayer()->RemoveBattleGroundQueueId(bgQueueTypeId); sBattleGroundMgr.m_BattleGroundQueues[ bgQueueTypeId ].RemovePlayer(GetPlayer()->GetObjectGuid(), true); } } ///- Reset the online field in the account table // no point resetting online in character table here as Player::SaveToDB() will set it to 1 since player has not been removed from world at this stage // No SQL injection as AccountID is uint32 if (!GetPlayer()->GetPlayerbotAI()) { static SqlStatementID id; SqlStatement stmt = LoginDatabase.CreateStatement(id, "UPDATE account SET active_realm_id = ? WHERE id = ?"); stmt.PExecute(uint32(0), GetAccountId()); } ///- If the player is in a guild, update the guild roster and broadcast a logout message to other guild members if (Guild* guild = sGuildMgr.GetGuildById(GetPlayer()->GetGuildId())) { if (MemberSlot* slot = guild->GetMemberSlot(GetPlayer()->GetObjectGuid())) { slot->SetMemberStats(GetPlayer()); slot->UpdateLogoutTime(); } guild->BroadcastEvent(GE_SIGNED_OFF, GetPlayer()->GetObjectGuid(), GetPlayer()->GetName()); } ///- Remove pet GetPlayer()->RemovePet(PET_SAVE_AS_CURRENT); GetPlayer()->InterruptNonMeleeSpells(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) GetPlayer()->SaveToDB(); ///- Leave all channels before player delete... GetPlayer()->CleanupChannels(); // LFG cleanup sLFGMgr.Leave(GetPlayer()); ///- If the player is in a group (or invited), remove him. If the group if then only 1 person, disband the group. GetPlayer()->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(GetPlayer()->GetGroup() && !GetPlayer()->GetGroup()->isRaidGroup() && m_Socket) GetPlayer()->RemoveFromGroup(); ///- Send update to group if(GetPlayer()->GetGroup()) GetPlayer()->GetGroup()->SendUpdate(); ///- Broadcast a logout message to the player's friends sSocialMgr.SendFriendStatus(GetPlayer(), FRIEND_OFFLINE, GetPlayer()->GetObjectGuid(), true); sSocialMgr.RemovePlayerSocial (GetPlayer()->GetGUIDLow ()); // Playerbot - remember player GUID for update SQL below uint32 guid = GetPlayer()->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 if (GetPlayer()->IsInWorld()) { Map* _map = GetPlayer()->GetMap(); _map->Remove(GetPlayer(), true); } else { GetPlayer()->CleanupsBeforeDelete(); if (GetPlayer()->GetMap()) GetPlayer()->GetMap()->DeleteFromWorld(GetPlayer()); else { sObjectAccessor.RemoveObject(GetPlayer()); delete GetPlayer(); } } SetPlayer(NULL); // deleted in Remove/DeleteFromWorld call ///- Send the 'logout complete' packet to the client WorldPacket data( SMSG_LOGOUT_COMPLETE, 0 ); SendPacket( &data ); static SqlStatementID updChars; // Playerbot mod: commented out above and do this one instead SqlStatement stmt = CharacterDatabase.CreateStatement(updChars, "UPDATE characters SET online = 0 WHERE guid = ?"); stmt.PExecute(guid); DEBUG_LOG( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); } m_playerLogout = false; m_playerSave = false; m_playerRecentlyLogout = true; LogoutRequest(0); }
void UpdateData::AddOutOfRangeGUID(ObjectGuidSet& guids) { m_outOfRangeGUIDs.insert(guids.begin(),guids.end()); }