void WorldSession::HandleGuildAcceptOpcode(WorldPacket& /*recvPacket*/) { Guild *guild; Player *player = GetPlayer(); sLog.outDebug("WORLD: Received CMSG_GUILD_ACCEPT"); guild = objmgr.GetGuildById(player->GetGuildIdInvited()); if(!guild || player->GetGuildId()) return; // not let enemies sign guild charter if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && player->GetTeam() != objmgr.GetPlayerTeamByGUID(guild->GetLeader())) return; if(!guild->AddMember(GetPlayer()->GetGUID(),guild->GetLowestRank())) return; // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_JOIN_GUILD, GetPlayer()->GetGUIDLow(), 0, 0); WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size data << (uint8)GE_JOINED; data << (uint8)1; // strings count data << player->GetName(); guild->BroadcastPacket(&data); sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); }
void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite) { WorldPacket data(SMSG_CALENDAR_EVENT_INVITE_ALERT); data << uint64(calendarEvent.GetEventId()); data << calendarEvent.GetTitle(); data.AppendPackedTime(calendarEvent.GetEventTime()); data << uint32(calendarEvent.GetFlags()); data << uint32(calendarEvent.GetType()); data << int32(calendarEvent.GetDungeonId()); data << uint64(invite.GetInviteId()); Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId()); data << uint64(guild ? guild->GetGUID() : 0); data << uint8(invite.GetStatus()); data << uint8(invite.GetRank()); data.appendPackGUID(calendarEvent.GetCreatorGUID()); data.appendPackGUID(invite.GetSenderGUID()); if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement()) { if (Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId())) guild->BroadcastPacket(&data); } else if (Player* player = ObjectAccessor::FindPlayer(invite.GetInviteeGUID())) player->SendDirectMessage(&data); }
void WorldSession::HandleGuildPromoteOpcode(WorldPacket& recvPacket) { sLog.outDebug("WORLD: Received CMSG_GUILD_PROMOTE"); std::string plName; recvPacket >> plName; if(!normalizePlayerName(plName)) return; Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_PROMOTE)) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } uint64 plGuid; MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); if(!slot) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); return; } if(plGuid == GetPlayer()->GetGUID()) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_NAME_INVALID); return; } //allow to promote only to lower rank than member's rank //guildmaster's rank = 0 //GetPlayer()->GetRank() + 1 is highest rank that current player can promote to if(GetPlayer()->GetRank() + 1 >= slot->RankId) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S); return; } uint32 newRankId = slot->RankId - 1; //when promoting player, rank is decreased WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_PROMOTION; data << (uint8)3; // strings count data << GetPlayer()->GetName(); data << plName; data << guild->GetRankName(newRankId); guild->BroadcastPacket(&data); guild->ChangeRank(plGuid, newRankId); // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_PROMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); }
void WorldSession::HandleGuildRenameRequest(WorldPacket& recvPacket) { uint32 lenght; std::string newName; lenght = recvPacket.ReadBits(8); newName = recvPacket.ReadString(lenght); Guild* pGuild = GetPlayer()->GetGuild(); if(pGuild) { PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_GUILD_NAME); _guildRenameCallback.SetParam(newName); stmt->setUInt32(1,pGuild->GetId()); stmt->setString(0,newName); _guildRenameCallback.SetFutureResult(CharacterDatabase.AsyncQuery(stmt)); WorldPacket data(SMSG_GUILD_FLAGGED_FOR_RENAME,1); data.WriteBit(true); // it may send false also, but we don't know how to handle exeptions by the DB layer data.FlushBits(); pGuild->BroadcastPacket(&data); } }
void WorldSession::HandleGuildRemoveOpcode(WorldPacket& recvPacket) { std::string plName; //sLog.outDebug("WORLD: Received CMSG_GUILD_REMOVE"); recvPacket >> plName; if(!normalizePlayerName(plName)) return; Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_REMOVE)) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } uint64 plGuid; MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); if(!slot) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); return; } if(slot->RankId == GR_GUILDMASTER) { SendGuildCommandResult(GUILD_QUIT_S, "", GUILD_LEADER_LEAVE); return; } //do not allow to kick player with same or higher rights if(GetPlayer()->GetRank() >= slot->RankId) { SendGuildCommandResult(GUILD_QUIT_S, plName, GUILD_RANK_TOO_HIGH_S); return; } guild->DelMember(plGuid); // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_UNINVITE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), 0); WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size data << (uint8)GE_REMOVED; data << (uint8)2; // strings count data << plName; data << GetPlayer()->GetName(); guild->BroadcastPacket(&data); }
void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) { std::string name; Player *oldLeader = GetPlayer(); Guild *guild; //sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER"); recvPacket >> name; if(!normalizePlayerName(name)) return; guild = objmgr.GetGuildById(oldLeader->GetGuildId()); if (!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if( oldLeader->GetGUID() != guild->GetLeader()) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } uint64 newLeaderGUID; MemberSlot* slot = guild->GetMemberSlot(name, newLeaderGUID); if (!slot) { SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); return; } guild->SetLeader(newLeaderGUID); guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER); WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size data << (uint8)GE_LEADER_CHANGED; data << (uint8)2; // strings count data << oldLeader->GetName(); data << name.c_str(); guild->BroadcastPacket(&data); //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); }
void WorldSession::HandleGuildLeaveOpcode(WorldPacket& /*recvPacket*/) { std::string plName; Guild *guild; //sLog.outDebug("WORLD: Received CMSG_GUILD_LEAVE"); guild = objmgr.GetGuildById(_player->GetGuildId()); if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if(_player->GetGUID() == guild->GetLeader() && guild->GetMemberSize() > 1) { SendGuildCommandResult(GUILD_QUIT_S, "", GUILD_LEADER_LEAVE); return; } if(_player->GetGUID() == guild->GetLeader()) { guild->Disband(); return; } plName = _player->GetName(); guild->DelMember(_player->GetGUID()); // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_LEAVE_GUILD, _player->GetGUIDLow(), 0, 0); WorldPacket data(SMSG_GUILD_EVENT, (2+10)); // guess size data << (uint8)GE_LEFT; data << (uint8)1; // strings count data << plName; guild->BroadcastPacket(&data); //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); SendGuildCommandResult(GUILD_QUIT_S, guild->GetName(), GUILD_PLAYER_NO_MORE_IN_GUILD); }
/// %Log the player out void WorldSession::LogoutPlayer(bool Save) { // finish pending transfers before starting the logout while(_player && _player->IsBeingTeleported()) HandleMoveWorldportAckOpcode(); m_playerLogout = true; if (_player) { 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->getHostilRefManager().deleteReferences(); _player->BuildPlayerRepop(); _player->RepopAtGraveyard(); } else if (!_player->getAttackers().empty()) { _player->CombatStop(); _player->getHostilRefManager().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((Player*)owner); } 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->RemoveSpellsCausingAura(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->TeleportTo(_player->m_homebindMapId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ, _player->GetOrientation()); 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); } } ///- 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 loginDatabase.PExecute("UPDATE account SET online = 0 WHERE id = '%u'", GetAccountId()); ///- 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->LoadPlayerStatsByGuid(_player->GetGUID()); guild->UpdateLogoutTime(_player->GetGUID()); WorldPacket data(SMSG_GUILD_EVENT, (1+1+12+8)); // name limited to 12 in character table. data<<(uint8)GE_SIGNED_OFF; data<<(uint8)1; data<<_player->GetName(); data<<_player->GetGUID(); guild->BroadcastPacket(&data); } ///- 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->RemoveFromGroup(); ///- 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(_player->IsInWorld()) _player->GetMap()->Remove(_player, false); // RemoveFromWorld does cleanup that requires the player to be in the accessor ObjectAccessor::Instance().RemoveObject(_player); ///- Send update to group if(_player->GetGroup()) _player->GetGroup()->SendUpdate(); ///- Broadcast a logout message to the player's friends sSocialMgr.SendFriendStatus(_player, FRIEND_OFFLINE, _player->GetGUIDLow(), true); ///- Delete the player object _player->CleanupsBeforeDelete(); // do some cleanup before deleting to prevent crash at crossreferences to already deleted data sSocialMgr.RemovePlayerSocial (_player->GetGUIDLow ()); delete _player; _player = NULL; ///- 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'", GetAccountId()); sLog.outDebug( "SESSION: Sent SMSG_LOGOUT_COMPLETE Message" ); } m_playerLogout = false; m_playerRecentlyLogout = true; LogoutRequest(0); }
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) { sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE"); std::string plName; recvPacket >> plName; if(!normalizePlayerName(plName)) return; Guild* guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE)) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } uint64 plGuid; MemberSlot* slot = guild->GetMemberSlot(plName, plGuid); if (!slot) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); return; } if(plGuid == GetPlayer()->GetGUID()) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_NAME_INVALID); return; } //do not allow to demote same or higher rank if(GetPlayer()->GetRank() >= slot->RankId) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_RANK_TOO_HIGH_S); return; } //do not allow to demote lowest rank if(slot->RankId >= guild->GetLowestRank()) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_ALREADY_LOWEST_RANK_S); return; } uint32 newRankId = slot->RankId + 1; //when demoting player, rank is increased guild->ChangeRank(plGuid, newRankId); // Put record into guildlog guild->LogGuildEvent(GUILD_EVENT_LOG_DEMOTE_PLAYER, GetPlayer()->GetGUIDLow(), GUID_LOPART(plGuid), newRankId); WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_DEMOTION; data << (uint8)3; // strings count data << GetPlayer()->GetName(); data << plName; data << guild->GetRankName(slot->RankId); guild->BroadcastPacket(&data); }
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { uint64 playerGuid = holder->GetGuid(); Player* pCurrChar = new Player(this); // for send server info and strings (config) ChatHandler chH = ChatHandler(pCurrChar); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } pCurrChar->GetMotionMaster()->Initialize(); SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128); for (int i = 0; i < 32; i++) data << uint32(0); SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ((nextpos= str_motd.find('@',pos)) != std::string::npos) { if (nextpos != pos) { data << str_motd.substr(pos,nextpos-pos); ++linecount; } pos = nextpos+1; } if (pos<str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket(&data); DEBUG_LOG("WORLD: Sent motd (SMSG_MOTD)"); // send server info if (sWorld.getConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1) chH.PSendSysMessage(_FULLVERSION); DEBUG_LOG("WORLD: Sent server info"); } { // active game events info std::string active_events = sGameEventMgr.getActiveEventsString(); ChatHandler(this).SendSysMessage(active_events.c_str());//ChatHandler::FillMessageData(&data, this, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, GetPlayer()->GetGUID(), active_events, NULL); } QueryResultAutoPtr resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if (resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); } else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if (pCurrChar->GetGuildId() != 0) { Guild* guild = sGuildMgr.GetGuildById(pCurrChar->GetGuildId()); if (guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)"); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG("WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)"); // Increment online members of the guild guild->IncOnlineMemberCount(); } else { // remove wrong guild data sLog.outLog(LOG_DEFAULT, "ERROR: Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } if (!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if (!pCurrChar->getCinematic()) { pCurrChar->setCinematic(true); if(ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) { pCurrChar->SendCinematicStart(rEntry->CinematicSequence); // send new char string if not empty if (!sWorld.GetNewCharString().empty()) chH.PSendSysMessage(sWorld.GetNewCharString().c_str()); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { // normal delayed teleport protection not applied (and this correct) for this case (Player object just created) AreaTrigger const* at = sObjectMgr.GetGoBackTrigger(pCurrChar->GetMapId()); if (at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportToHomebind(); } sObjectAccessor.AddPlayer(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->GetSocial()->SendSocialList(); pCurrChar->SendInitialPacketsAfterAddToMap(); static SqlStatementID setCharOnline; static SqlStatementID setAccountOnline; SqlStatement stmt = RealmDataDatabase.CreateStatement(setCharOnline, "UPDATE characters SET online = 1 WHERE guid = ?"); stmt.PExecute(pCurrChar->GetGUIDLow()); stmt = AccountsDatabase.CreateStatement(setAccountOnline, "UPDATE account SET online = 1 WHERE account_id = ?"); stmt.PExecute(GetAccountId()); pCurrChar->SetInGameTime(WorldTimer::getMSTime()); // announce group about member online (must be after add to player list to receive announce to self) if (Group *group = pCurrChar->GetGroup()) { //pCurrChar->groupInfo.group->SendInit(this); // useless group->CheckLeader(pCurrChar->GetGUID(), false); //check leader login group->SendUpdate(); } // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if (pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } if (uint32 sourceNode = pCurrChar->m_taxi.GetTaxiSource()) { sLog.outDebug("WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow()); uint32 MountId = sObjectMgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam()); uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath(); // search appropriate start path node uint32 startNode = 0; TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path]; float distPrev = MAP_SIZE*MAP_SIZE; float distNext = (nodeList[0].x-pCurrChar->GetPositionX())*(nodeList[0].x-pCurrChar->GetPositionX())+ (nodeList[0].y-pCurrChar->GetPositionY())*(nodeList[0].y-pCurrChar->GetPositionY())+ (nodeList[0].z-pCurrChar->GetPositionZ())*(nodeList[0].z-pCurrChar->GetPositionZ()); for (uint32 i = 1; i < nodeList.size(); ++i) { TaxiPathNodeEntry const& node = nodeList[i]; TaxiPathNodeEntry const& prevNode = nodeList[i-1]; // skip nodes at another map if (node.mapid != pCurrChar->GetMapId()) continue; distPrev = distNext; distNext = (node.x-pCurrChar->GetPositionX())*(node.x-pCurrChar->GetPositionX())+ (node.y-pCurrChar->GetPositionY())*(node.y-pCurrChar->GetPositionY())+ (node.z-pCurrChar->GetPositionZ())*(node.z-pCurrChar->GetPositionZ()); float distNodes = (node.x-prevNode.x)*(node.x-prevNode.x)+ (node.y-prevNode.y)*(node.y-prevNode.y)+ (node.z-prevNode.z)*(node.z-prevNode.z); if (distNext + distPrev < distNodes) { startNode = i; break; } } SendDoFlight(MountId, path, startNode); } // Load pet if any and player is alive and not in taxi flight if (pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING)) pCurrChar->SetFFAPvP(true); if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); SendNotification(LANG_RESET_TALENTS); } // show time before shutdown if shutdown planned. if (sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if (sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if (pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); pCurrChar->CreateCharmAI(); std::string IP_str = GetRemoteAddress(); sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Login Character:[%s] (guid:%u)", GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); m_playerLoading = false; sWorld.ModifyLoggedInCharsCount(_player->GetTeamId(), 1); delete holder; }
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { uint64 playerGuid = holder->GetGuid(); Player* pCurrChar = new Player(this); // for send server info and strings (config) ChatHandler chH = ChatHandler(pCurrChar); // "GetAccountId() == db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if (!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } pCurrChar->GetMotionMaster()->Initialize(); SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data(SMSG_LOGIN_VERIFY_WORLD, 20); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); data.Initialize(SMSG_ACCOUNT_DATA_TIMES, 128); for (int i = 0; i < 32; i++) data << uint32(0); SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ((nextpos= str_motd.find('@',pos)) != std::string::npos) { if (nextpos != pos) { data << str_motd.substr(pos,nextpos-pos); ++linecount; } pos = nextpos+1; } if (pos<str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket(&data); DEBUG_LOG("WORLD: Sent motd (SMSG_MOTD)"); // send server info if (sWorld.getConfig(CONFIG_ENABLE_SINFO_LOGIN) == 1) chH.PSendSysMessage(_FULLVERSION); DEBUG_LOG("WORLD: Sent server info"); } QueryResult_AutoPtr resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if (resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); } else if (pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if (pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if (guild) { data.Initialize(SMSG_GUILD_EVENT, (1+1+guild->GetMOTD().size()+1)); data << uint8(GE_MOTD); data << uint8(1); data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG("WORLD: Sent guild-motd (SMSG_GUILD_EVENT)"); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG("WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)"); // Increment online members of the guild guild->IncOnlineMemberCount(); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member of invalid guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } if (!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if (!pCurrChar->getCinematic()) { pCurrChar->setCinematic(1); if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) { pCurrChar->SendCinematicStart(rEntry->CinematicSequence); // send new char string if not empty if (!sWorld.GetNewCharString().empty()) chH.PSendSysMessage("%s", sWorld.GetNewCharString().c_str()); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { // normal delayed teleport protection not applied (and this correct) for this case (Player object just created) AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); if (at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportToHomebind(); } ObjectAccessor::Instance().AddObject(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->GetSocial()->SendSocialList(); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); //LoginDatabase.PExecute("UPDATE account SET active_realm_id = %d WHERE id = '%u'", realmID, GetAccountId()); pCurrChar->SetInGameTime(getMSTime()); // announce group about member online (must be after add to player list to receive announce to self) if (Group *group = pCurrChar->GetGroup()) group->SendUpdate(); // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if (pCurrChar->getRace() == RACE_NIGHTELF) { pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) } pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } pCurrChar->ContinueTaxiFlight(); // Load pet if any and player is alive and not in taxi flight if (pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource() == 0) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if (sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING)) pCurrChar->SetFFAPvP(true); if (pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if (pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); SendNotification(LANG_RESET_TALENTS); } // show time before shutdown if shutdown planned. if (sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); // ImpConfig - Max weapon skill when logging in if (sWorld.getConfig(CONFIG_ALWAYS_MAXSKILL)) pCurrChar->UpdateSkillsToMaxSkillsForLevel(); if (sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); //Reputations if "StartAllReputation" is enabled if (sWorld.getConfig(CONFIG_START_ALL_REP)) { pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(942),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(935),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(936),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(1011),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(970),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(967),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(989),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(932),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(934),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(1038),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(1077),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(990),42999); // Factions depending on team, like cities and some more stuff switch(pCurrChar->GetTeam()) { case ALLIANCE: pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(72),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(47),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(69),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(930),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(730),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(978),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(54),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(946),42999); break; case HORDE: pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(76),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(68),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(81),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(911),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(729),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(941),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(530),42999); pCurrChar->SetFactionReputation(sFactionStore.LookupEntry(947),42999); break; default: break; } } if (pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); m_playerLoading = false; //Hook for OnLogin Event sScriptMgr.OnLogin(pCurrChar); delete holder; }
void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data ) { m_playerLoading = true; uint64 playerGuid = 0; DEBUG_LOG( "WORLD: Recvd Player Logon Message" ); recv_data >> playerGuid; Player* plr = new Player(this); ASSERT(plr); plr->SetSession(this); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!plr->LoadFromDB(GUID_LOPART(playerGuid))) { m_playerLoading = false; return; } //plr->_RemoveAllItemMods(); //set a count of unread mails: QueryResult *resultMails = sDatabase.PQuery("SELECT COUNT(id) FROM `mail` WHERE `receiver` = '%u' AND `checked` = 0", GUID_LOPART(playerGuid)); if (resultMails) { Field *fieldMail = resultMails->Fetch(); plr->unReadMails = fieldMail[0].GetUInt8(); delete resultMails; } else plr->unReadMails = 0; SetPlayer(plr); WorldPacket data( SMSG_ACCOUNT_DATA_MD5, (80) ); for(int i = 0; i < 80; i++) data << uint8(0); SendPacket(&data); Player *pCurrChar = GetPlayer(); pCurrChar->LoadIgnoreList(); pCurrChar->SendFriendlist(); pCurrChar->SendIgnorelist(); sChatHandler.FillSystemMessageData(&data, this, sWorld.GetMotd()); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MESSAGECHAT)" ); if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<(uint8)0<<(uint8)0<<(uint8)0; guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetUInt32Value(PLAYER_GUILDID,0); pCurrChar->SetUInt32ValueInDB(PLAYER_GUILDID,0,pCurrChar->GetGUID()); } } // home bind stuff Field *fields; QueryResult *result7 = sDatabase.PQuery("SELECT COUNT(`guid`) FROM `character_homebind` WHERE `guid` = '%u'", GUID_LOPART(playerGuid)); if (result7) { int cnt; fields = result7->Fetch(); cnt = fields[0].GetUInt32(); if ( cnt > 0 ) { QueryResult *result4 = sDatabase.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `character_homebind` WHERE `guid` = '%u'", GUID_LOPART(playerGuid)); assert(result4); fields = result4->Fetch(); data.Initialize (SMSG_BINDPOINTUPDATE, 5*4); data << fields[2].GetFloat() << fields[3].GetFloat() << fields[4].GetFloat(); data << fields[0].GetUInt32(); data << fields[1].GetUInt32(); SendPacket (&data); DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n",fields[0].GetUInt32(),fields[1].GetUInt32(),fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat()); delete result4; } else { int plrace = GetPlayer()->getRace(); int plclass = GetPlayer()->getClass(); QueryResult *result5 = sDatabase.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `playercreateinfo` WHERE `race` = '%u' AND `class` = '%u'", plrace, plclass); assert(result5); fields = result5->Fetch(); // store and send homebind for player sDatabase.PExecute("INSERT INTO `character_homebind` (`guid`,`map`,`zone`,`position_x`,`position_y`,`position_z`) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GUID_LOPART(playerGuid), fields[0].GetUInt32(), fields[1].GetUInt32(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat()); data.Initialize (SMSG_BINDPOINTUPDATE, 5*4); data << fields[2].GetFloat() << fields[3].GetFloat() << fields[4].GetFloat(); data << fields[0].GetUInt32(); data << fields[1].GetUInt32(); SendPacket (&data); DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n",fields[0].GetUInt32(),fields[1].GetUInt32(),fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat()); delete result5; } delete result7; } data.Initialize( SMSG_TUTORIAL_FLAGS, 8*32 ); for (int i = 0; i < 8; i++) data << uint32( GetPlayer()->GetTutorialInt(i) ); SendPacket(&data); //sLog.outDebug( "WORLD: Sent tutorial flags." ); GetPlayer()->SendInitialSpells(); GetPlayer()->SendInitialActionButtons(); /*if(GetPlayer()->getClass() == CLASS_HUNTER || GetPlayer()->getClass() == CLASS_ROGUE) { uint32 shiftdata=0x01; for(uint8 i=0;i<32;i++) { if ( 522753 & shiftdata ) { data.Initialize(SMSG_SET_FLAT_SPELL_MODIFIER); data << uint8(i); data << uint8(5); data << uint16(1); data << uint16(0); SendPacket(&data); } shiftdata=shiftdata<<1; } }*/ data.Initialize(SMSG_INITIALIZE_FACTIONS, (4+64*5)); data << uint32 (0x00000040); for(uint32 a=0; a<64; a++) { if(GetPlayer()->FactionIsInTheList(a)) { std::list<struct Factions>::iterator itr; for(itr = GetPlayer()->factions.begin(); itr != GetPlayer()->factions.end(); ++itr) { if(itr->ReputationListID == a) { data << uint8 (itr->Flags); data << uint32 (itr->Standing); break; } } } else { data << uint8 (0x00); data << uint32 (0x00000000); } } SendPacket(&data); GetPlayer()->UpdateHonor(); data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); time_t gameTime = sWorld.GetGameTime(); struct tm *lt = localtime(&gameTime); uint32 xmitTime = (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; data << xmitTime; data << (uint32)0x3C888889; //(float)0.017f; SendPacket( &data ); //Show cinematic at the first time that player login if( !GetPlayer()->getCinematic() ) { GetPlayer()->setCinematic(1); ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(GetPlayer()->getRace()); if(rEntry) { data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); data << uint32(rEntry->startmovie); SendPacket( &data ); } } QueryResult *result = sDatabase.PQuery("SELECT `guildid`,`rank` FROM `guild_member` WHERE `guid` = '%u'",pCurrChar->GetGUIDLow()); if(result) { Field *fields = result->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete result; } MapManager::Instance().GetMap(pCurrChar->GetMapId())->Add(pCurrChar); ObjectAccessor::Instance().InsertPlayer(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); if (pCurrChar->m_transport) { Transport* curTrans = pCurrChar->m_transport; pCurrChar->TeleportTo(curTrans->GetMapId(), curTrans->GetPositionX(), curTrans->GetPositionY(), curTrans->GetPositionZ(), curTrans->GetOrientation(), true, false); } sDatabase.PExecute("UPDATE `character` SET `online` = 1 WHERE `guid` = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE `account` SET `online` = 1 WHERE `id` = '%u'", GetAccountId()); plr->SetInGameTime( getMSTime() ); data.Initialize(SMSG_FRIEND_STATUS, 19); data<<uint8(FRIEND_ONLINE); data<<pCurrChar->GetGUID(); data<<uint8(1); data<<pCurrChar->GetAreaId(); data<<pCurrChar->getLevel(); data<<pCurrChar->getClass(); pCurrChar->BroadcastPacketToFriendListers(&data); // setting new speed if dead if ( pCurrChar->m_deathState == DEAD ) { pCurrChar->SetMovement(MOVE_WATER_WALK); if (pCurrChar->getRace() == RACE_NIGHTELF) { pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); } else { pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); } } pCurrChar->LoadEnchant(); pCurrChar->_LoadSpellCooldowns(); // Place charcter in world (and load zone) before some object loading pCurrChar->LoadCorpse(); pCurrChar->LoadPet(); // show time before shutdown if shudown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); result = sDatabase.PQuery("SELECT `leaderGuid` FROM `raidgroup_member` WHERE `memberGuid`='%u'", GUID_LOPART(pCurrChar->GetGUID())); if(result) { uint64 leaderGuid = MAKE_GUID((*result)[0].GetUInt32(),HIGHGUID_PLAYER); delete result; pCurrChar->groupInfo.group = objmgr.GetGroupByLeader(leaderGuid); if(pCurrChar->groupInfo.group) { pCurrChar->groupInfo.group->SendInit(this); pCurrChar->groupInfo.group->SendUpdate(); } } if(pCurrChar->isGameMaster()) SendNotification("GM mode is ON"); m_playerLoading = false; }
void WorldSession::HandleGuildLeaderOpcode(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket, 1); std::string name; Player *newLeader; uint64 newLeaderGUID; uint32 newLeaderGuild; Player *oldLeader = GetPlayer(); Guild *guild; //sLog.outDebug("WORLD: Received CMSG_GUILD_LEADER"); recvPacket >> name; if(name.empty()) return; normalizePlayerName(name); //CharacterDatabase.escape_string(name); // prevent SQL injection - normal name don't must changed by this call newLeader = ObjectAccessor::Instance().FindPlayerByName(name.c_str()); if(newLeader) { newLeaderGUID = newLeader->GetGUID(); newLeaderGuild = newLeader->GetGuildId(); } else { newLeaderGUID = objmgr.GetPlayerGUIDByName(name); newLeaderGuild = Player::GetGuildIdFromDB(newLeaderGUID); } guild = objmgr.GetGuildById(oldLeader->GetGuildId()); if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } else if(!newLeaderGUID) { SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_FOUND); return; } if(oldLeader->GetGuildId() != newLeaderGuild) { SendGuildCommandResult(GUILD_INVITE_S, name, GUILD_PLAYER_NOT_IN_GUILD_S); return; } if(oldLeader->GetGUID() != guild->GetLeader()) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } guild->SetLeader(newLeaderGUID); guild->ChangeRank(oldLeader->GetGUID(), GR_OFFICER); WorldPacket data(SMSG_GUILD_EVENT, (2+20)); // guess size data << (uint8)GE_LEADER_CHANGED; data << (uint8)2; data << oldLeader->GetName(); data << name.c_str(); guild->BroadcastPacket(&data); //sLog.outDebug("WORLD: Sent (SMSG_GUILD_EVENT)"); }
void WorldSession::HandleGuildDemoteOpcode(WorldPacket& recvPacket) { CHECK_PACKET_SIZE(recvPacket, 1); std::string plName; uint64 plGuid; uint32 plGuildId; uint32 plRankId; Player *player; Guild *guild; //sLog.outDebug("WORLD: Received CMSG_GUILD_DEMOTE"); recvPacket >> plName; if(plName.empty()) return; normalizePlayerName(plName); //CharacterDatabase.escape_string(plName); // prevent SQL injection - normal name don't must changed by this call player = ObjectAccessor::Instance().FindPlayerByName(plName.c_str()); guild = objmgr.GetGuildById(GetPlayer()->GetGuildId()); if(player) { plGuid = player->GetGUID(); plGuildId = player->GetGuildId(); plRankId = player->GetRank(); } else { plGuid = objmgr.GetPlayerGUIDByName(plName); plGuildId = Player::GetGuildIdFromDB(plGuid); plRankId = Player::GetRankFromDB(plGuid); } if(!guild) { SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_PLAYER_NOT_IN_GUILD); return; } if( !plGuid ) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_FOUND); return; } if(plGuid == GetPlayer()->GetGUID()) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_NAME_INVALID); return; } if(GetPlayer()->GetGuildId() != plGuildId) { SendGuildCommandResult(GUILD_INVITE_S, plName, GUILD_PLAYER_NOT_IN_GUILD_S); return; } if(!guild->HasRankRight(GetPlayer()->GetRank(), GR_RIGHT_DEMOTE)) { SendGuildCommandResult(GUILD_INVITE_S, "", GUILD_PERMISSIONS); return; } if((plRankId+1) >= guild->GetNrRanks() || plRankId <= this->GetPlayer()->GetRank()) return; guild->ChangeRank(plGuid, (plRankId+1)); WorldPacket data(SMSG_GUILD_EVENT, (2+30)); // guess size data << (uint8)GE_DEMOTION; data << (uint8)3; data << GetPlayer()->GetName(); data << plName; data << guild->GetRankName(plRankId+1); guild->BroadcastPacket(&data); }
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { uint64 playerGuid = holder->GetGuid(); Player* pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); data.Initialize( SMSG_ACCOUNT_DATA_TIMES, 128 ); for(int i = 0; i < 32; i++) data << uint32(0); SendPacket(&data); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos,nextpos-pos); ++linecount; } pos = nextpos+1; } if (pos<str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if(resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); // Increment online members of the guild guild->IncOnlineMemberCount(); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } if(!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if( !pCurrChar->getCinematic() ) { pCurrChar->setCinematic(1); ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()); if(rEntry) { data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); data << uint32(rEntry->startmovie); SendPacket( &data ); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); if(at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); } ObjectAccessor::Instance().AddObject(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->GetSocial()->SendSocialList(); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = '%u'", GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) if(Group *group = pCurrChar->GetGroup()) { //pCurrChar->groupInfo.group->SendInit(this); // useless group->SendUpdate(); } // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); //if (pCurrChar->getRace() == RACE_NIGHTELF) //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); //} //else //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); //} pCurrChar->SetMovement(MOVE_WATER_WALK); } if(uint32 sourceNode = pCurrChar->m_taxi.GetTaxiSource()) { sLog.outDebug( "WORLD: Restart character %u taxi flight", pCurrChar->GetGUIDLow() ); uint32 MountId = objmgr.GetTaxiMount(sourceNode, pCurrChar->GetTeam()); uint32 path = pCurrChar->m_taxi.GetCurrentTaxiPath(); // search appropriate start path node uint32 startNode = 0; TaxiPathNodeList const& nodeList = sTaxiPathNodesByPath[path]; float distPrev = MAP_SIZE*MAP_SIZE; float distNext = (nodeList[0].x-pCurrChar->GetPositionX())*(nodeList[0].x-pCurrChar->GetPositionX())+ (nodeList[0].y-pCurrChar->GetPositionY())*(nodeList[0].y-pCurrChar->GetPositionY())+ (nodeList[0].z-pCurrChar->GetPositionZ())*(nodeList[0].z-pCurrChar->GetPositionZ()); for(uint32 i = 1; i < nodeList.size(); ++i) { TaxiPathNode const& node = nodeList[i]; TaxiPathNode const& prevNode = nodeList[i-1]; // skip nodes at another map if(node.mapid != pCurrChar->GetMapId()) continue; distPrev = distNext; distNext = (node.x-pCurrChar->GetPositionX())*(node.x-pCurrChar->GetPositionX())+ (node.y-pCurrChar->GetPositionY())*(node.y-pCurrChar->GetPositionY())+ (node.z-pCurrChar->GetPositionZ())*(node.z-pCurrChar->GetPositionZ()); float distNodes = (node.x-prevNode.x)*(node.x-prevNode.x)+ (node.y-prevNode.y)*(node.y-prevNode.y)+ (node.z-prevNode.z)*(node.z-prevNode.z); if(distNext + distPrev < distNodes) { startNode = i; break; } } SendDoFlight( MountId, path, startNode ); } // Load pet if any and player is alive and not in taxi flight if(pCurrChar->isAlive() && pCurrChar->m_taxi.GetTaxiSource()==0) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) pCurrChar->SetFlag(PLAYER_FLAGS,PLAYER_FLAGS_FFA_PVP); if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); SendNotification(LANG_RESET_TALENTS); } // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if(pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUIDLow()); m_playerLoading = false; delete holder; }
void WorldSession::HandlePlayerLogin(LoginQueryHolder * holder) { uint64 playerGuid = holder->GetGuid(); Player* pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } else SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); data.Initialize( SMSG_ACCOUNT_DATA_MD5, 128 ); for(int i = 0; i < 32; i++) data << uint32(0); SendPacket(&data); pCurrChar->SendFriendlist(); pCurrChar->SendIgnorelist(); // added in 2.2.0 data.Initialize(SMSG_VOICE_SYSTEM_STATUS, 2); data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos,nextpos-pos); linecount++; } pos = nextpos+1; } if (pos<str_motd.length()) { data << str_motd.substr(pos); linecount++; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetUInt32Value(PLAYER_GUILDID,0); pCurrChar->SetUInt32ValueInDB(PLAYER_GUILDID,0,pCurrChar->GetGUID()); } } pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if( !pCurrChar->getCinematic() ) { pCurrChar->setCinematic(1); ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace()); if(rEntry) { data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); data << uint32(rEntry->startmovie); SendPacket( &data ); } } //QueryResult *result = CharacterDatabase.PQuery("SELECT `guildid`,`rank` FROM `guild_member` WHERE `guid` = '%u'",pCurrChar->GetGUIDLow()); QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if(resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if (!MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->AddInstanced(pCurrChar)) { // TODO : Teleport to zone-in area } MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->Add(pCurrChar); ObjectAccessor::Instance().AddObject(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE `character` SET `online` = 1 WHERE `guid` = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE `account` SET `online` = 1 WHERE `id` = '%u'", GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) if(pCurrChar->GetGroup()) { //pCurrChar->groupInfo.group->SendInit(this); // useless pCurrChar->GetGroup()->SendUpdate(); } // friend status data.Initialize(SMSG_FRIEND_STATUS, 19); data<<uint8(FRIEND_ONLINE); data<<pCurrChar->GetGUID(); data<<uint8(1); data<<pCurrChar->GetAreaId(); data<<pCurrChar->getLevel(); data<<pCurrChar->getClass(); pCurrChar->BroadcastPacketToFriendListers(&data, true, holder->GetResult(PLAYER_LOGIN_QUERY_BROADCASTTOFRIENDLISTERS)); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead //if ( pCurrChar->m_deathState == DEAD ) if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); //if (pCurrChar->getRace() == RACE_NIGHTELF) //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); //} //else //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); //} pCurrChar->SetMovement(MOVE_WATER_WALK); } // Load pet if any and player is alive if(pCurrChar->isAlive()) pCurrChar->LoadPet(); // Apply at_login requests if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification("Spells has been reset."); } if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); SendNotification("Talents has been reset."); } // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(pCurrChar->isGameMaster()) SendNotification("GM mode is ON"); std::string IP_str = _socket ? _socket->GetRemoteAddress().c_str() : "-"; sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)",GetAccountId(),IP_str.c_str(),pCurrChar->GetName() ,pCurrChar->GetGUID()); m_playerLoading = false; delete holder; }
void WorldSession::HandlePlayerLogin(LoginQueryHolder *holder) { uint64 playerGuid = holder->GetGuid(); Player *pCurrChar = new Player(this); pCurrChar->GetMotionMaster()->Initialize(); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!pCurrChar->LoadFromDB(GUID_LOPART(playerGuid), holder)) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete pCurrChar; // delete it manually delete holder; // delete all unprocessed queries m_playerLoading = false; return; } SetPlayer(pCurrChar); pCurrChar->SendDungeonDifficulty(false); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << pCurrChar->GetMapId(); data << pCurrChar->GetPositionX(); data << pCurrChar->GetPositionY(); data << pCurrChar->GetPositionZ(); data << pCurrChar->GetOrientation(); SendPacket(&data); // load player specific part before send times LoadAccountData(holder->GetResult(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA),PER_CHARACTER_CACHE_MASK); SendAccountDataTimes(PER_CHARACTER_CACHE_MASK); data.Initialize(SMSG_FEATURE_SYSTEM_STATUS, 2); // added in 2.2.0 data << uint8(2); // unknown value data << uint8(0); // enable(1)/disable(0) voice chat interface in client SendPacket(&data); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; std::string str_motd = sWorld.GetMotd(); std::string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != std::string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos, nextpos-pos); ++linecount; } pos = nextpos + 1; } if (pos < str_motd.length()) { data << str_motd.substr(pos); ++linecount; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } //QueryResult *result = CharacterDatabase.PQuery("SELECT guildid,rank FROM guild_member WHERE guid = '%u'",pCurrChar->GetGUIDLow()); QueryResult *resultGuild = holder->GetResult(PLAYER_LOGIN_QUERY_LOADGUILD); if(resultGuild) { Field *fields = resultGuild->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete resultGuild; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); // Increment online members of the guild guild->IncOnlineMemberCount(); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetInGuild(0); } } data.Initialize(SMSG_LEARNED_DANCE_MOVES, 4+4); data << uint32(0); data << uint32(0); SendPacket(&data); if(!pCurrChar->isAlive()) pCurrChar->SendCorpseReclaimDelay(true); pCurrChar->SendInitialPacketsBeforeAddToMap(); //Show cinematic at the first time that player login if( !pCurrChar->getCinematic() ) { pCurrChar->setCinematic(1); if(ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(pCurrChar->getClass())) { if (cEntry->CinematicSequence) pCurrChar->SendCinematicStart(cEntry->CinematicSequence); else if (ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(pCurrChar->getRace())) pCurrChar->SendCinematicStart(rEntry->CinematicSequence); } } if (!pCurrChar->GetMap()->Add(pCurrChar)) { AreaTrigger const* at = objmgr.GetGoBackTrigger(pCurrChar->GetMapId()); if(at) pCurrChar->TeleportTo(at->target_mapId, at->target_X, at->target_Y, at->target_Z, pCurrChar->GetOrientation()); else pCurrChar->TeleportTo(pCurrChar->m_homebindMapId, pCurrChar->m_homebindX, pCurrChar->m_homebindY, pCurrChar->m_homebindZ, pCurrChar->GetOrientation()); } ObjectAccessor::Instance().AddObject(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); pCurrChar->SendInitialPacketsAfterAddToMap(); CharacterDatabase.PExecute("UPDATE characters SET online = 1 WHERE guid = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE account SET active_realm_id = %d WHERE id = '%u'", realmID, GetAccountId()); pCurrChar->SetInGameTime( getMSTime() ); // announce group about member online (must be after add to player list to receive announce to self) if(Group *group = pCurrChar->GetGroup()) { //pCurrChar->groupInfo.group->SendInit(this); // useless group->SendUpdate(); } // friend status sSocialMgr.SendFriendStatus(pCurrChar, FRIEND_ONLINE, pCurrChar->GetGUIDLow(), true); // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead if (pCurrChar->m_deathState != ALIVE) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) pCurrChar->SetMovement(MOVE_WATER_WALK); } pCurrChar->ContinueTaxiFlight(); // reset for all pets before pet loading if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_PET_TALENTS)) Pet::resetTalentsForAllPetsOf(pCurrChar); // Load pet if any (if player not alive and in taxi flight or another then pet will remember as temporary unsummoned) pCurrChar->LoadPet(); // Set FFA PvP for non GM in non-rest mode if(sWorld.IsFFAPvPRealm() && !pCurrChar->isGameMaster() && !pCurrChar->HasFlag(PLAYER_FLAGS,PLAYER_FLAGS_RESTING) ) pCurrChar->SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_FFA_PVP); if(pCurrChar->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP)) pCurrChar->SetContestedPvP(); // Apply at_login requests if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_SPELLS)) { pCurrChar->resetSpells(); SendNotification(LANG_RESET_SPELLS); } if(pCurrChar->HasAtLoginFlag(AT_LOGIN_RESET_TALENTS)) { pCurrChar->resetTalents(true); pCurrChar->SendTalentsInfoData(false); // original talents send already in to SendInitialPacketsBeforeAddToMap, resend reset state SendNotification(LANG_RESET_TALENTS); } // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(sWorld.getConfig(CONFIG_ALL_TAXI_PATHS)) pCurrChar->SetTaxiCheater(true); if(pCurrChar->isGameMaster()) SendNotification(LANG_GM_ON); std::string IP_str = GetRemoteAddress(); sLog.outChar("Account: %d (IP: %s) Login Character:[%s] (guid:%u)", GetAccountId(), IP_str.c_str(), pCurrChar->GetName(), pCurrChar->GetGUIDLow()); if(!pCurrChar->IsStandState() && !pCurrChar->hasUnitState(UNIT_STAT_STUNNED)) pCurrChar->SetStandState(UNIT_STAND_STATE_STAND); m_playerLoading = false; delete holder; }
void WorldSession::HandlePlayerLoginOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8); m_playerLoading = true; uint64 playerGuid = 0; DEBUG_LOG( "WORLD: Recvd Player Logon Message" ); recv_data >> playerGuid; Player* plr = new Player(this); // "GetAccountId()==db stored account id" checked in LoadFromDB (prevent login not own character using cheating tools) if(!plr->LoadFromDB(GUID_LOPART(playerGuid))) { KickPlayer(); // disconnect client, player no set to session and it will not deleted or saved at kick delete plr; // delete it manually m_playerLoading = false; return; } //plr->_RemoveAllItemMods(); //set a count of unread mails time_t cTime = time(NULL); QueryResult *resultMails = sDatabase.PQuery("SELECT COUNT(id) FROM `mail` WHERE `receiver` = '%u' AND `checked` = 0 AND `deliver_time` <= '" I64FMTD "'", GUID_LOPART(playerGuid),(uint64)cTime); if (resultMails) { Field *fieldMail = resultMails->Fetch(); plr->unReadMails = fieldMail[0].GetUInt8(); delete resultMails; } // store nearest delivery time (it > 0 and if it < current then at next player update SendNewMaill will be called) resultMails = sDatabase.PQuery("SELECT MIN(`deliver_time`) FROM `mail` WHERE `receiver` = '%u' AND `checked` = 0", GUID_LOPART(playerGuid)); if (resultMails) { Field *fieldMail = resultMails->Fetch(); plr->m_nextMailDelivereTime = (time_t)fieldMail[0].GetUInt64(); delete resultMails; } SetPlayer(plr); Player *pCurrChar = GetPlayer(); pCurrChar->SendDungeonDifficulty(); WorldPacket data( SMSG_LOGIN_VERIFY_WORLD, 20 ); data << plr->GetMapId(); data << plr->GetPositionX(); data << plr->GetPositionY(); data << plr->GetPositionZ(); data << plr->GetOrientation(); SendPacket(&data); data.Initialize( SMSG_ACCOUNT_DATA_MD5, 128 ); for(int i = 0; i < 32; i++) data << uint32(0); SendPacket(&data); pCurrChar->LoadIgnoreList(); pCurrChar->SendFriendlist(); pCurrChar->SendIgnorelist(); // Send MOTD { data.Initialize(SMSG_MOTD, 50); // new in 2.0.1 data << (uint32)0; uint32 linecount=0; string str_motd = sWorld.GetMotd(); string::size_type pos, nextpos; pos = 0; while ( (nextpos= str_motd.find('@',pos)) != string::npos ) { if (nextpos != pos) { data << str_motd.substr(pos,nextpos-pos); linecount++; } pos = nextpos+1; } if (pos<str_motd.length()) { data << str_motd.substr(pos); linecount++; } data.put(0, linecount); SendPacket( &data ); DEBUG_LOG( "WORLD: Sent motd (SMSG_MOTD)" ); } if(pCurrChar->GetGuildId() != 0) { Guild* guild = objmgr.GetGuildById(pCurrChar->GetGuildId()); if(guild) { data.Initialize(SMSG_GUILD_EVENT, (2+guild->GetMOTD().size()+1)); data << (uint8)GE_MOTD; data << (uint8)1; data << guild->GetMOTD(); SendPacket(&data); DEBUG_LOG( "WORLD: Sent guild-motd (SMSG_GUILD_EVENT)" ); data.Initialize(SMSG_GUILD_EVENT, (5+10)); // we guess size data<<(uint8)GE_SIGNED_ON; data<<(uint8)1; data<<pCurrChar->GetName(); data<<pCurrChar->GetGUID(); guild->BroadcastPacket(&data); DEBUG_LOG( "WORLD: Sent guild-signed-on (SMSG_GUILD_EVENT)" ); } else { // remove wrong guild data sLog.outError("Player %s (GUID: %u) marked as member not existed guild (id: %u), removing guild membership for player.",pCurrChar->GetName(),pCurrChar->GetGUIDLow(),pCurrChar->GetGuildId()); pCurrChar->SetUInt32Value(PLAYER_GUILDID,0); pCurrChar->SetUInt32ValueInDB(PLAYER_GUILDID,0,pCurrChar->GetGUID()); } } // rest_start // home bind stuff { QueryResult *result4 = sDatabase.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `character_homebind` WHERE `guid` = '%u'", GUID_LOPART(playerGuid)); if (result4) { Field *fields = result4->Fetch(); _player->m_homebindMapId = fields[0].GetUInt32(); _player->m_homebindZoneId = fields[1].GetUInt16(); _player->m_homebindX = fields[2].GetFloat(); _player->m_homebindY = fields[3].GetFloat(); _player->m_homebindZ = fields[4].GetFloat(); delete result4; } else { int plrace = GetPlayer()->getRace(); int plclass = GetPlayer()->getClass(); QueryResult *result5 = sDatabase.PQuery("SELECT `map`,`zone`,`position_x`,`position_y`,`position_z` FROM `playercreateinfo` WHERE `race` = '%u' AND `class` = '%u'", plrace, plclass); if(!result5) { sLog.outErrorDb("Table `playercreateinfo` not have data for race %u class %u , character can't be loaded.",plrace, plclass); LogoutPlayer(false); // without save return; } Field *fields = result5->Fetch(); // store and send homebind for player _player->m_homebindMapId = fields[0].GetUInt32(); _player->m_homebindZoneId = fields[1].GetUInt16(); _player->m_homebindX = fields[2].GetFloat(); _player->m_homebindY = fields[3].GetFloat(); _player->m_homebindZ = fields[4].GetFloat(); sDatabase.PExecute("INSERT INTO `character_homebind` (`guid`,`map`,`zone`,`position_x`,`position_y`,`position_z`) VALUES ('%u', '%u', '%u', '%f', '%f', '%f')", GUID_LOPART(playerGuid), _player->m_homebindMapId, (uint32)_player->m_homebindZoneId, _player->m_homebindX, _player->m_homebindY, _player->m_homebindZ); delete result5; } data.Initialize (SMSG_BINDPOINTUPDATE, 5*4); data << _player->m_homebindX << _player->m_homebindY << _player->m_homebindZ; data << (uint32) _player->m_homebindMapId; data << (uint32) _player->m_homebindZoneId; SendPacket (&data); DEBUG_LOG("Setting player home position: mapid is: %u, zoneid is %u, X is %f, Y is %f, Z is %f\n", _player->m_homebindMapId,_player->m_homebindZoneId,_player->m_homebindX,_player->m_homebindY, _player->m_homebindZ); } data.Initialize( SMSG_TUTORIAL_FLAGS, 8*32 ); for (int i = 0; i < 8; i++) data << uint32( GetPlayer()->GetTutorialInt(i) ); SendPacket(&data); //sLog.outDebug( "WORLD: Sent tutorial flags." ); pCurrChar->_LoadSpellCooldowns(); GetPlayer()->SendInitialSpells(); GetPlayer()->SendInitialActionButtons(); GetPlayer()->SendInitialReputations(); /*if(GetPlayer()->getClass() == CLASS_HUNTER || GetPlayer()->getClass() == CLASS_ROGUE) { uint32 shiftdata=0x01; for(uint8 i=0;i<32;i++) { if ( 522753 & shiftdata ) { data.Initialize(SMSG_SET_FLAT_SPELL_MODIFIER); data << uint8(i); data << uint8(5); data << uint16(1); data << uint16(0); SendPacket(&data); } shiftdata=shiftdata<<1; } }*/ //Show cinematic at the first time that player login if( !GetPlayer()->getCinematic() ) { GetPlayer()->setCinematic(1); ChrRacesEntry const* rEntry = sChrRacesStore.LookupEntry(GetPlayer()->getRace()); if(rEntry) { data.Initialize( SMSG_TRIGGER_CINEMATIC,4 ); data << uint32(rEntry->startmovie); SendPacket( &data ); } } pCurrChar->SendInitWorldStates(); pCurrChar->CastSpell(pCurrChar, 836, true); // LOGINEFFECT data.Initialize(SMSG_LOGIN_SETTIMESPEED, 8); time_t gameTime = sWorld.GetGameTime(); struct tm *lt = localtime(&gameTime); uint32 xmitTime = (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min; data << xmitTime; data << (float)0.017f; // game speed SendPacket( &data ); GetPlayer()->UpdateHonorFields(); QueryResult *result = sDatabase.PQuery("SELECT `guildid`,`rank` FROM `guild_member` WHERE `guid` = '%u'",pCurrChar->GetGUIDLow()); if(result) { Field *fields = result->Fetch(); pCurrChar->SetInGuild(fields[0].GetUInt32()); pCurrChar->SetRank(fields[1].GetUInt32()); delete result; } else if(pCurrChar->GetGuildId()) // clear guild related fields in case wrong data about non existed membership { pCurrChar->SetInGuild(0); pCurrChar->SetRank(0); } if (!MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->AddInstanced(pCurrChar)) { // TODO : Teleport to zone-in area } MapManager::Instance().GetMap(pCurrChar->GetMapId(), pCurrChar)->Add(pCurrChar); ObjectAccessor::Instance().InsertPlayer(pCurrChar); //sLog.outDebug("Player %s added to Map.",pCurrChar->GetName()); if (pCurrChar->m_transport) { Transport* curTrans = pCurrChar->m_transport; pCurrChar->TeleportTo(curTrans->GetMapId(), curTrans->GetPositionX(), curTrans->GetPositionY(), curTrans->GetPositionZ(), curTrans->GetOrientation(), true, false); } sDatabase.PExecute("UPDATE `character` SET `online` = 1 WHERE `guid` = '%u'", pCurrChar->GetGUIDLow()); loginDatabase.PExecute("UPDATE `account` SET `online` = 1 WHERE `id` = '%u'", GetAccountId()); plr->SetInGameTime( getMSTime() ); // set some aura effects after add player to map if(pCurrChar->HasAuraType(SPELL_AURA_MOD_STUN)) pCurrChar->SetMovement(MOVE_ROOT); if(pCurrChar->HasAuraType(SPELL_AURA_MOD_ROOT)) { WorldPacket data(SMSG_FORCE_MOVE_ROOT, 10); data.append(pCurrChar->GetPackGUID()); data << (uint32)2; pCurrChar->SendMessageToSet(&data,true); } // announce group about member online (must be after add to player list to receive announce to self) if(pCurrChar->groupInfo.group) { //pCurrChar->groupInfo.group->SendInit(this); // useless pCurrChar->groupInfo.group->SendUpdate(); } // friend status data.Initialize(SMSG_FRIEND_STATUS, 19); data<<uint8(FRIEND_ONLINE); data<<pCurrChar->GetGUID(); data<<uint8(1); data<<pCurrChar->GetAreaId(); data<<pCurrChar->getLevel(); data<<pCurrChar->getClass(); pCurrChar->BroadcastPacketToFriendListers(&data); pCurrChar->SendEnchantmentDurations(); // must be after add to map // Place character in world (and load zone) before some object loading pCurrChar->LoadCorpse(); // setting Ghost+speed if dead //if ( pCurrChar->m_deathState == DEAD ) if ( pCurrChar->m_deathState != ALIVE ) { // not blizz like, we must correctly save and load player instead... if(pCurrChar->getRace() == RACE_NIGHTELF) pCurrChar->CastSpell(pCurrChar, 20584, true, 0);// auras SPELL_AURA_INCREASE_SPEED(+speed in wisp form), SPELL_AURA_INCREASE_SWIM_SPEED(+swim speed in wisp form), SPELL_AURA_TRANSFORM (to wisp form) pCurrChar->CastSpell(pCurrChar, 8326, true, 0); // auras SPELL_AURA_GHOST, SPELL_AURA_INCREASE_SPEED(why?), SPELL_AURA_INCREASE_SWIM_SPEED(why?) //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+41, 8326); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURA+42, 20584); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAFLAGS+6, 238); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURALEVELS+11, 514); //pCurrChar->SetUInt32Value(UNIT_FIELD_AURAAPPLICATIONS+11, 65535); //pCurrChar->SetUInt32Value(UNIT_FIELD_DISPLAYID, 1825); //if (pCurrChar->getRace() == RACE_NIGHTELF) //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f*1.2f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f*1.2f, true); //} //else //{ // pCurrChar->SetSpeed(MOVE_RUN, 1.5f, true); // pCurrChar->SetSpeed(MOVE_SWIM, 1.5f, true); //} pCurrChar->SetMovement(MOVE_WATER_WALK); } // Load pet if any and player is alive if(pCurrChar->isAlive()) pCurrChar->LoadPet(); // show time before shutdown if shutdown planned. if(sWorld.IsShutdowning()) sWorld.ShutdownMsg(true,pCurrChar); if(pCurrChar->isGameMaster()) SendNotification("GM mode is ON"); m_playerLoading = false; pCurrChar->SendAllowMove(); data.Initialize(SMSG_UNKNOWN_811, 4); data << uint32(0); SendPacket(&data); }