void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0)); packet.WriteBit(queued); if (queued) packet.WriteBit(0); packet.WriteBit(1); // has account info packet.FlushBits(); // account info packet << uint32(0); // BillingTimeRemaining packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account packet << uint32(0); packet << uint8(Expansion()); // Unknown, these two show the same packet << uint32(0); // BillingTimeRested packet << uint8(0); // BillingPlanFlags packet << uint8(code); if (queued) packet << uint32(queuePos); // Queue position SendPacket(&packet); }
void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE,16); packet.WriteBit(false); //isQueued packet.WriteBit(true); //hasAccountInfo packet << uint32(0); // BillingTimeRemaining packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account packet << uint32(0); // Unk 4.3.2 packet << uint8(Expansion()); // Unknown, these two show the same packet << uint32(0); // BillingTimeRested packet << uint8(0); // BillingPlanFlags /* if (!shortForm) { packet << uint32(queuePos); // Queue position packet << uint8(0); // Unk 3.3.0 } */ packet << uint8(code); SendPacket(&packet); }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { QueryResult result = LoginDatabase.PQuery("SELECT class, expansion FROM realm_classes WHERE realmId = %u", realmID); QueryResult result2 = LoginDatabase.PQuery("SELECT race, expansion FROM realm_races WHERE realmId = %u", realmID); if (!result || !result2) { TC_LOG_ERROR(LOG_FILTER_GENERAL, "Unable to retrieve class or race data."); return; } WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + 4 + 1 + 1 + 1 + (queued ? 4 : 0)); packet.WriteBit(0); // Is in queue ? packet.WriteBit(0); // Has account data ? packet.WriteBits(0, 21); // Activate character template button packet.WriteBit(0); // Unknown packet.WriteBits(result2->GetRowCount(), 23); // Activation count for races packet.WriteBit(0); // Unknown packet.WriteBit(0); // Unknown packet.WriteBits(0, 21); // Unknown packet.WriteBit(0); // Unknown packet.WriteBits(result->GetRowCount(), 23); // Activation count for races packet.WriteBit(0); // Unknown packet.FlushBits(); packet << uint32(1); // Auth response ? do { Field* fields = result->Fetch(); packet << fields[1].GetUInt8(); packet << fields[0].GetUInt8(); }while(result->NextRow()); packet << uint32(0); // Unknown packet << uint32(0); // Unknown do { Field* fields = result2->Fetch(); packet << fields[1].GetUInt8(); packet << fields[0].GetUInt8(); }while(result2->NextRow()); packet << uint32(0); packet << uint32(0); packet << uint8(Expansion()); packet << uint8(Expansion()); packet << uint32(0); packet << uint32(0); SendPacket(&packet); }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { bool hasAccountData = true; WorldPacket packet(SMSG_AUTH_RESPONSE, 80); packet.WriteBit(hasAccountData); if (hasAccountData) { packet.WriteBits(MAX_CLASSES - 1, 23); packet.WriteBits(0, 21); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBits(MAX_PLAYABLE_RACES, 23); packet.WriteBit(0); packet.WriteBit(queued); if (queued) packet.WriteBit(1); if (queued) packet << uint32(queuePos); for (uint8 i = 0; i < MAX_PLAYABLE_RACES; ++i) { packet << uint8(raceExpansionInfo[i].expansion); packet << uint8(raceExpansionInfo[i].raceOrClass); } for (uint8 i = 0; i < MAX_CLASSES - 1; ++i) { packet << uint8(classExpansionInfo[i].raceOrClass); packet << uint8(classExpansionInfo[i].expansion); } packet << uint32(0); packet << uint8(Expansion()); packet << uint32(Expansion()); packet << uint32(0); packet << uint8(Expansion()); packet << uint32(0); packet << uint32(0); packet << uint32(0); } packet << uint8(code); SendPacket(&packet); }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { QueryResult classresult = LoginDatabase.PQuery("SELECT class, expansion FROM realm_classes WHERE realmId = %u", realmID); QueryResult raceresult = LoginDatabase.PQuery("SELECT race, expansion FROM realm_races WHERE realmId = %u", realmID); if (!classresult || !raceresult) { sLog->outError(LOG_FILTER_GENERAL, "AuthHandler SendAuthResponse could not get db realm_classes and realm_races"); return; } WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0)); packet << uint8(code); packet.WriteBit(queued); // IsInQueue packet.WriteBit(1); // has account info // account info packet.WriteBits(0, 21); // Activate character template windows/button packet.WriteBits(raceresult->GetRowCount(), 23); // Activation count for races packet.WriteBit(0); packet.WriteBits(classresult->GetRowCount(), 23); // Activation count for classes packet.WriteBit(0); packet.FlushBits(); do { Field* fields = classresult->Fetch(); packet << fields[0].GetUInt8(); packet << fields[1].GetUInt8(); } while (classresult->NextRow()); do { Field* fields = raceresult->Fetch(); packet << fields[1].GetUInt8(); packet << fields[0].GetUInt8(); } while (raceresult->NextRow()); packet << uint8(Expansion()); // Unknown, these two show the same packet << uint8(Expansion()); // Unknown, these two show the same packet << uint8(0); packet << uint32(0); packet << uint32(0); packet << uint32(0); SendPacket(&packet); }
void RA_PWMClass::ExpansionWrite() { for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ ) { Expansion(a,ExpansionChannel[a]); } }
// Initialize a CFontDescription object with the attributes that // make a font unique. BOOL CTextStyle::GetFontDescription(CFontDescription* pFontDescription) { BOOL fResult = FALSE; // Get the typeface number. int nTypeface = ((PMGFontServer*)(Database()->get_font_server()))->font_record_to_face(Font()); if (nTypeface != -1) { // Compute the style (bold, italic) of the typeface. int nFontStyle = 0; if (Bold()) { nFontStyle |= FONT_STYLE_Bold; } if (Italic()) { nFontStyle |= FONT_STYLE_Italic; } // Initialize the font description. pFontDescription->m_nTypeface = typeface_for_fstyle(nTypeface, (FONT_STYLE)nFontStyle); pFontDescription->m_lPointSize = Size(); pFontDescription->m_lHorizontalExpansion = Expansion(); pFontDescription->m_Fill = Fill(); pFontDescription->m_Outline = Outline(); pFontDescription->m_Shadow = Shadow(); fResult = TRUE; } return fResult; }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { // Should be done at server's start QueryResult classResult = WorldDatabase.Query("SELECT class, expansion FROM aa_classes"); QueryResult raceResult = WorldDatabase.Query("SELECT race, expansion FROM aa_races"); WorldPacket packet(SMSG_AUTH_RESPONSE); // BitPack packet.WriteBit(1); // HasAccountData packet.WriteBit(0); // Unknown, 5.0.4 packet.WriteBits(classResult->GetRowCount(), 25); // Activation count for races packet.WriteBits(0, 22); // Activate character template windows/button packet.WriteBits(raceResult->GetRowCount(), 25); // Activation count for classes packet.WriteBit(0); // IsInQueue packet.FlushBits(); packet << uint8(0); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA, 4 - MoP; must be set in database manually for each account packet << uint8(Expansion()); do { Field* fields = classResult->Fetch(); packet << uint8(fields[0].GetUInt8()); packet << uint8(fields[1].GetUInt8()); } while(classResult->NextRow()); packet << uint32(0); packet << uint32(0); // BillingTimeRemaining packet << uint32(0); // BillingTimeRested do { Field* fields = raceResult->Fetch(); packet << uint8(fields[0].GetUInt8()); packet << uint8(fields[1].GetUInt8()); } while(raceResult->NextRow()); packet << uint8(Expansion()); // Unknown, these two show the same packet << uint8(code); // Unknown - 4.3.2 SendPacket(&packet); }
void RA_PWMClass::ExpansionSetPercent(byte p) { // loop through all 6 channels and send the value for ( byte a = 0; a < PWM_EXPANSION_CHANNELS; a++ ) { Expansion(a, p); } }
void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 2 + 1); packet << uint8(code); packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // | 0 - normal | 1 - TBC | 2 - WOTLK | 3 - CATA | packet << uint8(Expansion()); // Server Expansion if (!shortForm) { packet << uint32(queuePos); // Queue position packet << uint8(0); // Unk 3.3.0 } SendPacket(&packet); }
void WorldSession::SendAuthResponse(uint8 AuthCode, bool shortForm, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + (shortForm ? 0 : (4 + 1))); packet << uint8(AuthCode); packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // payed expansion packet << uint8(Expansion()); // server expansion if (!shortForm) { packet << uint32(queuePos); // Queue position packet << uint8(0); // Unk 3.3.0 } SendPacket(&packet); }
void WorldSession::SendAuthOk() const { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1); packet << uint8(AUTH_OK); packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // 0 - normal, 1 - TBC. Must be set in database manually for each account. SendPacket(packet, true); }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 /*bits*/ + 4 + 1 + 4 + 1 + 4 + 1 + 1 + (queued ? 4 : 0)); packet.WriteBit(1); // has account data packet.WriteBits(MAX_CLASSES - 1, 25); // Activation count for classes packet.WriteBit(0); packet.WriteBit(0); packet.WriteBits(0, 22); // Activate character template windows/button packet.WriteBits(MAX_PLAYABLE_RACES, 25); // Activation count for races packet.WriteBit(queued); // IsInQueue if (queued) { packet.WriteBit(false); // unk packet << uint32(queuePos); } // account info for (int i = 0; i < MAX_PLAYABLE_RACES; ++i) { packet << uint8(raceExpansionInfo[i].expansion); packet << uint8(raceExpansionInfo[i].raceOrClass); } packet << uint32(0); // billing time remaining packet << uint32(0); // unk packet << uint8(0); // unk packet << uint8(Expansion()); // Unknown, these two show the same packet << uint8(Expansion()); // Unknown, these two show the same for (int i = 0; i < MAX_CLASSES - 1; ++i) { packet << uint8(classExpansionInfo[i].raceOrClass); packet << uint8(classExpansionInfo[i].expansion); } packet << uint32(0); packet << uint8(code); SendPacket(&packet); }
void WorldSession::SendAuthQueued() const { // The 1st SMSG_AUTH_RESPONSE needs to contain other info too. WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + 4); packet << uint8(AUTH_WAIT_QUEUE); packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account packet << uint32(sWorld.GetQueuedSessionPos(this)); // position in queue SendPacket(packet, true); }
void WorldSession::SendAuthResponse(uint8 code, bool shortForm, uint32 queuePos) { WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1 + (shortForm ? 0 : (4 + 1))); packet << uint8(code); packet << uint32(0); // BillingTimeRemaining packet << uint8(0); // BillingPlanFlags packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, must be set in database manually for each account if (!shortForm) { packet << uint32(queuePos); // Queue position packet << uint8(0); // Unk 3.3.0 } SendPacket(&packet); }
void CTextStyle::FromOldStyle(const TextStyle& style) { // Set some defaults. SetDefault(); // Copy the style information over. Font(style.get_face()); Size(MakeFixed(style.get_size(), style.get_size_fraction())); BaseSize(MakeFixed(style.get_base_size(), style.get_base_size_fraction())); Expansion(DivFixed(MakeFixed(style.get_base_size(), style.get_base_size_fraction()), MakeFixed(FONT_EXPANSION_UNIT))); Fill(style.get_pattern(), style.get_color()); Outline(style.get_outline(), style.get_color()); Shadow(style.get_shadow(), style.get_color()); m_Character.m_nEffectsVersion = 1; XFlipped(style.get_xflipped()); YFlipped(style.get_yflipped()); // Color(style.get_color()); Alignment(style.get_line_alignment()); VerticalAlignment(style.get_vertical_alignment()); // Left and right margin should be zero (default) unless set by user. // This fixes a problem converting old warp text boxes - they should // always have zero margins! LeftMargin(0); RightMargin(0); // LeftMargin(PageToInches(style.get_left_margin())); // RightMargin(PageToInches(style.get_right_margin())); LeadingType(LEADING_lines); Leading(MakeFixed(0.875)); Underline(style.UnderlineStyle()); // Update our metrics. UpdateFontMetrics(); }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,1+1+1+1+1+1+1+1+1+1); std::string name; uint8 race_,class_; recv_data >> name; // recheck with known string size CHECK_PACKET_SIZE(recv_data,(name.size()+1)+1+1+1+1+1+1+1+1+1); recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if(GetSecurity() == SEC_PLAYER) { if(uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch(team) { case ALLIANCE: disabled = mask & (1<<0); break; case HORDE: disabled = mask & (1<<1); break; } if(disabled) { data << (uint8)CHAR_CREATE_DISABLED; SendPacket( &data ); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if( !classEntry || !raceEntry ) { data << (uint8)CHAR_CREATE_FAILED; SendPacket( &data ); sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->addon > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; sLog.outError("Not Expansion 1 account:[%d] but tried to Create character with expansion 1 race (%u)",GetAccountId(),race_); SendPacket( &data ); return; } // prevent character creating Expansion class without Expansion account // TODO: use possible addon field in ChrClassesEntry in next dbc version if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT) { data << (uint8)CHAR_CREATE_EXPANSION; sLog.outError("Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); SendPacket( &data ); return; } // prevent character creating with invalid name if(!normalizePlayerName(name)) { data << (uint8)CHAR_NAME_INVALID_CHARACTER; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); return; } // check name limitations if(!ObjectMgr::IsValidName(name,true)) { data << (uint8)CHAR_NAME_INVALID_CHARACTER; SendPacket( &data ); return; } if(GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } if(objmgr.GetPlayerGUIDByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); return; } QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); if ( resultacct ) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); delete resultacct; if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) { data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); return; } } QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); uint8 charcount = 0; if ( result ) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) { data << (uint8)CHAR_CREATE_SERVER_LIMIT; SendPacket( &data ); return; } } bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; if(!AllowTwoSideAccounts || skipCinematics == 1) { QueryResult *result2 = CharacterDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 race = field[0].GetUInt32(); // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 team=0; if(race > 0) team = Player::TeamForRace(race); if(team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); delete result2; return; } } if (skipCinematics == 1) { // TODO: check if cinematic already shown? (already logged in?; cinematic field) while (race_ != race && result2->NextRow()) { field = result2->Fetch(); race = field[0].GetUInt32(); } have_same_race = race_ == race; } delete result2; } } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player * pNewChar = new Player(this); if(!pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) { // Player not create (race/class problem?) delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } if(have_same_race && skipCinematics == 1 || skipCinematics == 2) pNewChar->setCinematic(1); // not show intro // Player created, save it now pNewChar->SaveToDB(); charcount+=1; loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); delete pNewChar; // created only to call SaveToDB() data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); std::string IP_str = GetRemoteAddress(); sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); sLog.outChar("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { std::string name; uint8 race_, class_; recv_data >> name; recv_data >> race_; recv_data >> class_; // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if(GetSecurity() == SEC_PLAYER) { if(uint32 mask = sWorld.getConfig(CONFIG_UINT32_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; Team team = Player::TeamForRace(race_); switch(team) { case ALLIANCE: disabled = mask & (1 << 0); break; case HORDE: disabled = mask & (1 << 1); break; } if(disabled) { data << (uint8)CHAR_CREATE_DISABLED; SendPacket( &data ); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if( !classEntry || !raceEntry ) { data << (uint8)CHAR_CREATE_FAILED; SendPacket( &data ); sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->expansion > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_); SendPacket( &data ); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << (uint8)CHAR_NAME_NO_NAME; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name]", GetAccountId()); return; } // check name limitations uint8 res = ObjectMgr::CheckPlayerName(name, true); if (res != CHAR_NAME_SUCCESS) { data << uint8(res); SendPacket( &data ); return; } if (GetSecurity() == SEC_PLAYER && sObjectMgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } if (sObjectMgr.GetPlayerGuidByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); return; } QueryResult *resultacct = LoginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%u'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); delete resultacct; if (acctcharcount >= sWorld.getConfig(CONFIG_UINT32_CHARACTERS_PER_ACCOUNT)) { data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); return; } } QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%u'", GetAccountId()); uint8 charcount = 0; if ( result ) { Field *fields = result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= sWorld.getConfig(CONFIG_UINT32_CHARACTERS_PER_REALM)) { data << (uint8)CHAR_CREATE_SERVER_LIMIT; SendPacket( &data ); return; } } bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; CinematicsSkipMode skipCinematics = CinematicsSkipMode(sWorld.getConfig(CONFIG_UINT32_SKIP_CINEMATICS)); bool have_same_race = false; if(!AllowTwoSideAccounts || skipCinematics == CINEMATICS_SKIP_SAME_RACE) { QueryResult *result2 = CharacterDatabase.PQuery("SELECT race FROM characters WHERE account = '%u' %s", GetAccountId(), (skipCinematics == CINEMATICS_SKIP_SAME_RACE) ? "" : "LIMIT 1"); if(result2) { Team team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 acc_race = field[0].GetUInt32(); // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { if (acc_race == 0 || Player::TeamForRace(acc_race) != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); delete result2; return; } } // search same race for cinematic or same class if need // TODO: check if cinematic already shown? (already logged in?; cinematic field) while (skipCinematics == CINEMATICS_SKIP_SAME_RACE && !have_same_race) { if(!result2->NextRow()) break; field = result2->Fetch(); acc_race = field[0].GetUInt32(); have_same_race = race_ == acc_race; } delete result2; } } Player *pNewChar = new Player(this); if (!pNewChar->Create(sObjectMgr.GeneratePlayerLowGuid(), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId)) { // Player not create (race/class problem?) delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } if ((have_same_race && skipCinematics == CINEMATICS_SKIP_SAME_RACE) || skipCinematics == CINEMATICS_SKIP_ALL) pNewChar->setCinematic(1); // not show intro pNewChar->SetAtLoginFlag(AT_LOGIN_FIRST); // First login // Player created, save it now pNewChar->SaveToDB(); charcount += 1; LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%u' AND realmid = '%u'", GetAccountId(), realmID); LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); std::string IP_str = GetRemoteAddress(); BASIC_LOG("Account: %d (IP: %s) Create Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); sLog.outChar("Account: %d (IP: %s) Create Character:[%s] (guid: %u)", GetAccountId(), IP_str.c_str(), name.c_str(), pNewChar->GetGUIDLow()); delete pNewChar; // created only to call SaveToDB() }
void WorldSession::HandleCharCreateOpcode(WorldPacket & recv_data) { CHECK_PACKET_SIZE(recv_data, 1+1+1+1+1+1+1+1+1+1); std::string name; uint8 race_, class_; recv_data >> name; // recheck with known string size CHECK_PACKET_SIZE(recv_data, (name.size()+1)+1+1+1+1+1+1+1+1+1); recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if (!HasPermissions(PERM_GMT)) { if (uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch (team) { case ALLIANCE: disabled = mask & (1<<0); break; case HORDE: disabled = mask & (1<<1); break; } if (disabled) { data << uint8(CHAR_CREATE_DISABLED); SendPacket(&data); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if (!classEntry || !raceEntry) { data << uint8(CHAR_CREATE_FAILED); SendPacket(&data); sLog.outLog(LOG_DEFAULT, "ERROR: Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->addon > Expansion()) { data << uint8(CHAR_CREATE_EXPANSION); sLog.outLog(LOG_DEFAULT, "ERROR: Expansion %u account:[%d] tried to Create character with expansion %u race (%u)",Expansion(),GetAccountId(),raceEntry->addon,race_); SendPacket(&data); return; } // prevent character creating Expansion class without Expansion account // TODO: use possible addon field in ChrClassesEntry in next dbc version if (Expansion() < 2 && class_ == CLASS_DEATH_KNIGHT) { data << uint8(CHAR_CREATE_EXPANSION); sLog.outLog(LOG_DEFAULT, "ERROR: Not Expansion 2 account:[%d] but tried to Create character with expansion 2 class (%u)",GetAccountId(),class_); SendPacket(&data); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket(&data); sLog.outLog(LOG_DEFAULT, "ERROR: Account:[%d] but tried to Create character with empty [name] ",GetAccountId()); return; } // check name limitations if (!ObjectMgr::IsValidName(name,true)) { data << uint8(CHAR_NAME_INVALID_CHARACTER); SendPacket(&data); return; } if (!HasPermissions(PERM_GMT) && sObjectMgr.IsReservedName(name)) { data << uint8(CHAR_NAME_RESERVED); SendPacket(&data); return; } if (sObjectMgr.GetPlayerGUIDByName(name)) { data << uint8(CHAR_CREATE_NAME_IN_USE); SendPacket(&data); return; } QueryResultAutoPtr resultacct = AccountsDatabase.PQuery("SELECT SUM(characters_count) FROM realm_characters WHERE account_id = '%u'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) { data << uint8(CHAR_CREATE_ACCOUNT_LIMIT); SendPacket(&data); return; } } QueryResultAutoPtr result = RealmDataDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%u'", GetAccountId()); uint8 charcount = 0; if (result) { Field *fields=result->Fetch(); charcount = fields[0].GetUInt8(); if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) { data << uint8(CHAR_CREATE_SERVER_LIMIT); SendPacket(&data); return; } } bool AllowTwoSideAccounts = !sWorld.IsPvPRealm() || sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || HasPermissions(PERM_GMT); uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; if (!AllowTwoSideAccounts || skipCinematics == 1) { QueryResultAutoPtr result2 = RealmDataDatabase.PQuery("SELECT DISTINCT race FROM characters WHERE account = '%u' %s", GetAccountId(),skipCinematics == 1 ? "" : "LIMIT 1"); if (result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 race = field[0].GetUInt32(); // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 team=0; if (race > 0) team = Player::TeamForRace(race); if (team != team_) { data << uint8(CHAR_CREATE_PVP_TEAMS_VIOLATION); SendPacket(&data); return; } } if (skipCinematics == 1) { // TODO: check if cinematic already shown? (already logged in?; cinematic field) while (race_ != race && result2->NextRow()) { field = result2->Fetch(); race = field[0].GetUInt32(); } have_same_race = race_ == race; } } } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player * pNewChar = new Player(this); if (!pNewChar->Create(sObjectMgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId)) { // Player not create (race/class problem?) delete pNewChar; data << uint8(CHAR_CREATE_ERROR); SendPacket(&data); return; } if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) pNewChar->setCinematic(true); // not show intro // Player created, save it now pNewChar->SaveToDB(); charcount += 1; // direct to be sure that character count has proper value (also should fix possible multi char create in some cases) static SqlStatementID updateRealmChars; SqlStatement stmt = AccountsDatabase.CreateStatement(updateRealmChars, "UPDATE realm_characters SET characters_count = ? WHERE account_id = ? AND realm_id = ?"); stmt.addUInt8(charcount); stmt.addUInt32(GetAccountId()); stmt.addUInt32(realmID); stmt.Execute(); delete pNewChar; // created only to call SaveToDB() data << uint8(CHAR_CREATE_SUCCESS); SendPacket(&data); std::string IP_str = GetRemoteAddress(); sLog.outDetail("Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); sLog.outLog(LOG_CHAR, "Account: %d (IP: %s) Create Character:[%s]",GetAccountId(),IP_str.c_str(),name.c_str()); }
void Simplex::OneCall() { // calcola l,h e centroide Initialize(); Reflection(); double ystar = EvalFunction(m_Pstar); double y_l = EvalFunction(m_P[m_l]); double y_h = EvalFunction(m_P[m_h]); // il punto riflesso sta sotto y_l if (ystar < y_l) { Expansion(); // espansione riuscita if (EvalFunction(m_Pstarstar) < y_l) { m_P[m_h]->SetPoint(m_Pstarstar); return; } // espansione fallita else { m_P[m_h]->SetPoint(m_Pstar); return; } } // il punto riflesso non sta sotto y_l else { // calcola se il punto riflesso è maggiore di tutti gli altri int counter = 0; for (int i = 0; i < 3; i++) { if ( ystar > EvalFunction(m_P[i]) ) {counter++;} } // il punto non è maggiore di tutti gli i != h if (counter < 2) { m_P[m_h]->SetPoint(m_Pstar); return; } // il punto è maggiore di tutti gli i (!)= h else { // se non è maggiore di h, sostituisco h if (counter < 3) { m_P[m_h]->SetPoint(m_Pstar); y_h = EvalFunction(m_P[m_h]); } Contraction(); // il punto contratto non è maggiore di y_h if (EvalFunction(m_Pstarstar) <= y_h) { m_P[m_h]->SetPoint(m_Pstarstar); return; } // il punto contratto è maggiore di y_h else { double x_point_l = m_P[m_l]->GetX(); double y_point_l = m_P[m_l]->GetY(); for (int i = 0; i < 3; i++) { m_P[i]->SetX(0.5*(m_P[i]->GetX() + x_point_l)); m_P[i]->SetY(0.5*(m_P[i]->GetY() + y_point_l)); } return; } } } }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { QueryResult result = LoginDatabase.PQuery("SELECT class, expansion FROM realm_classes WHERE realmId = %u", realmID); QueryResult result2 = LoginDatabase.PQuery("SELECT race, expansion FROM realm_races WHERE realmId = %u", realmID); if (!result || !result2) { TC_LOG_ERROR(LOG_FILTER_GENERAL, "Unable to retrieve class or race data."); return; } WorldPacket packet(SMSG_AUTH_RESPONSE, 80); packet.WriteBit(queued); packet.WriteBit(code == AUTH_OK); if (code == AUTH_OK) { packet.WriteBits(0, 21); packet.WriteBit(0); packet.WriteBits(result->GetRowCount(), 23); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBits(0, 21); packet.WriteBit(0); packet.WriteBits(result2->GetRowCount(), 23); packet.WriteBit(0); packet.FlushBits(); } if (queued) { packet.WriteBit(0); packet << uint32(queuePos); // Queue position packet.FlushBits(); } if (code == AUTH_OK) { do { Field* fields = result->Fetch(); packet << fields[0].GetUInt8(); packet << fields[1].GetUInt8(); } while (result->NextRow()); packet << uint32(0); do { Field* fields = result2->Fetch(); packet << fields[1].GetUInt8(); packet << fields[0].GetUInt8(); } while (result2->NextRow()); packet << uint32(0); // BillingTimeRemaining packet << uint32(0); // BillingTimeRested packet << uint8(Expansion()); // 0 - normal, 1 - TBC, 2 - WOTLK, 3 - CATA; must be set in database manually for each account packet << uint8(Expansion()); // Unknown, these two show the same packet << uint32(0); packet << uint32(0); } packet << uint8(code); SendPacket(&packet); }
void WorldSession::HandleCharCreateOpcode( WorldPacket & recv_data ) { std::string name; uint8 race_, class_; recv_data >> name; recv_data >> race_; recv_data >> class_; WorldPacket data(SMSG_CHAR_CREATE, 1); // returned with diff.values in all cases if(GetSecurity() == SEC_PLAYER) { if(uint32 mask = sWorld.getConfig(CONFIG_CHARACTERS_CREATING_DISABLED)) { bool disabled = false; uint32 team = Player::TeamForRace(race_); switch(team) { case ALLIANCE: disabled = mask & (1 << 0); break; case HORDE: disabled = mask & (1 << 1); break; } if(disabled) { data << (uint8)CHAR_CREATE_DISABLED; SendPacket( &data ); return; } } } ChrClassesEntry const* classEntry = sChrClassesStore.LookupEntry(class_); ChrRacesEntry const* raceEntry = sChrRacesStore.LookupEntry(race_); if( !classEntry || !raceEntry ) { data << (uint8)CHAR_CREATE_FAILED; SendPacket( &data ); sLog.outError("Class: %u or Race %u not found in DBC (Wrong DBC files?) or Cheater?", class_, race_); return; } // prevent character creating Expansion race without Expansion account if (raceEntry->expansion > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION; sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u race (%u)", Expansion(), GetAccountId(), raceEntry->expansion, race_); SendPacket( &data ); return; } // prevent character creating Expansion class without Expansion account if (classEntry->expansion > Expansion()) { data << (uint8)CHAR_CREATE_EXPANSION_CLASS; sLog.outError("Expansion %u account:[%d] tried to Create character with expansion %u class (%u)", Expansion(), GetAccountId(), classEntry->expansion, class_); SendPacket( &data ); return; } // prevent character creating with invalid name if (!normalizePlayerName(name)) { data << (uint8)CHAR_NAME_NO_NAME; SendPacket( &data ); sLog.outError("Account:[%d] but tried to Create character with empty [name]", GetAccountId()); return; } // check name limitations uint8 res = ObjectMgr::CheckPlayerName(name, true); if (res != CHAR_NAME_SUCCESS) { data << uint8(res); SendPacket( &data ); return; } if (GetSecurity() == SEC_PLAYER && objmgr.IsReservedName(name)) { data << (uint8)CHAR_NAME_RESERVED; SendPacket( &data ); return; } if (objmgr.GetPlayerGUIDByName(name)) { data << (uint8)CHAR_CREATE_NAME_IN_USE; SendPacket( &data ); return; } QueryResult *resultacct = loginDatabase.PQuery("SELECT SUM(numchars) FROM realmcharacters WHERE acctid = '%d'", GetAccountId()); if (resultacct) { Field *fields=resultacct->Fetch(); uint32 acctcharcount = fields[0].GetUInt32(); delete resultacct; if (acctcharcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_ACCOUNT)) { data << (uint8)CHAR_CREATE_ACCOUNT_LIMIT; SendPacket( &data ); return; } } QueryResult *result = CharacterDatabase.PQuery("SELECT COUNT(guid) FROM characters WHERE account = '%d'", GetAccountId()); uint8 charcount = 0; if ( result ) { Field *fields = result->Fetch(); charcount = fields[0].GetUInt8(); delete result; if (charcount >= sWorld.getConfig(CONFIG_CHARACTERS_PER_REALM)) { data << (uint8)CHAR_CREATE_SERVER_LIMIT; SendPacket( &data ); return; } } // speedup check for heroic class disabled case uint32 heroic_free_slots = sWorld.getConfig(CONFIG_HEROIC_CHARACTERS_PER_REALM); if(heroic_free_slots == 0 && GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); return; } // speedup check for heroic class disabled case uint32 req_level_for_heroic = sWorld.getConfig(CONFIG_MIN_LEVEL_FOR_HEROIC_CHARACTER_CREATING); if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && req_level_for_heroic > sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL)) { data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; SendPacket( &data ); return; } bool AllowTwoSideAccounts = sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_ACCOUNTS) || GetSecurity() > SEC_PLAYER; uint32 skipCinematics = sWorld.getConfig(CONFIG_SKIP_CINEMATICS); bool have_same_race = false; // if 0 then allowed creating without any characters bool have_req_level_for_heroic = (req_level_for_heroic==0); if(!AllowTwoSideAccounts || skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) { QueryResult *result2 = CharacterDatabase.PQuery("SELECT level,race,class FROM characters WHERE account = '%u' %s", GetAccountId(), (skipCinematics == 1 || class_ == CLASS_DEATH_KNIGHT) ? "" : "LIMIT 1"); if(result2) { uint32 team_= Player::TeamForRace(race_); Field* field = result2->Fetch(); uint8 acc_race = field[1].GetUInt32(); if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[2].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { if(heroic_free_slots > 0) --heroic_free_slots; if(heroic_free_slots == 0) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); return; } } if(!have_req_level_for_heroic) { uint32 acc_level = field[0].GetUInt32(); if(acc_level >= req_level_for_heroic) have_req_level_for_heroic = true; } } // need to check team only for first character // TODO: what to if account already has characters of both races? if (!AllowTwoSideAccounts) { uint32 acc_team = 0; if(acc_race > 0) acc_team = Player::TeamForRace(acc_race); if(acc_team != team_) { data << (uint8)CHAR_CREATE_PVP_TEAMS_VIOLATION; SendPacket( &data ); delete result2; return; } } // search same race for cinematic or same class if need // TODO: check if cinematic already shown? (already logged in?; cinematic field) while ((skipCinematics == 1 && !have_same_race) || class_ == CLASS_DEATH_KNIGHT) { if(!result2->NextRow()) break; field = result2->Fetch(); acc_race = field[1].GetUInt32(); if(!have_same_race) have_same_race = race_ == acc_race; if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT) { uint8 acc_class = field[2].GetUInt32(); if(acc_class == CLASS_DEATH_KNIGHT) { if(heroic_free_slots > 0) --heroic_free_slots; if(heroic_free_slots == 0) { data << (uint8)CHAR_CREATE_UNIQUE_CLASS_LIMIT; SendPacket( &data ); return; } } if(!have_req_level_for_heroic) { uint32 acc_level = field[0].GetUInt32(); if(acc_level >= req_level_for_heroic) have_req_level_for_heroic = true; } } } delete result2; } } if(GetSecurity() == SEC_PLAYER && class_ == CLASS_DEATH_KNIGHT && !have_req_level_for_heroic) { data << (uint8)CHAR_CREATE_LEVEL_REQUIREMENT; SendPacket( &data ); return; } // extract other data required for player creating uint8 gender, skin, face, hairStyle, hairColor, facialHair, outfitId; recv_data >> gender >> skin >> face; recv_data >> hairStyle >> hairColor >> facialHair >> outfitId; Player *pNewChar = new Player(this); if(!pNewChar->Create( objmgr.GenerateLowGuid(HIGHGUID_PLAYER), name, race_, class_, gender, skin, face, hairStyle, hairColor, facialHair, outfitId )) { // Player not create (race/class problem?) delete pNewChar; data << (uint8)CHAR_CREATE_ERROR; SendPacket( &data ); return; } if ((have_same_race && skipCinematics == 1) || skipCinematics == 2) pNewChar->setCinematic(1); // not show intro // Player created, save it now pNewChar->SaveToDB(); charcount += 1; loginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", GetAccountId(), realmID); loginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charcount, GetAccountId(), realmID); delete pNewChar; // created only to call SaveToDB() data << (uint8)CHAR_CREATE_SUCCESS; SendPacket( &data ); std::string IP_str = GetRemoteAddress(); sLog.outBasic("Account: %d (IP: %s) Create Character:[%s]", GetAccountId(), IP_str.c_str(), name.c_str()); sLog.outChar("Account: %d (IP: %s) Create Character:[%s]", GetAccountId(), IP_str.c_str(), name.c_str()); }
void WorldSession::SendAuthResponse(uint8 code, bool queued, uint32 queuePos) { QueryResult classResult = LoginDatabase.PQuery("SELECT class, expansion FROM realm_classes WHERE realmId = %u", realmID); QueryResult raceResult = LoginDatabase.PQuery("SELECT race, expansion FROM realm_races WHERE realmId = %u", realmID); if (!classResult || !raceResult) { TC_LOG_ERROR("network", "Unable to retrieve class or race data."); return; } TC_LOG_ERROR("network", "SMSG_AUTH_RESPONSE"); WorldPacket packet(SMSG_AUTH_RESPONSE, 80); packet << uint8(code); // Auth response ? packet.WriteBit(code == AUTH_OK); if (code == AUTH_OK) { packet.WriteBits(0, 21); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBits(classResult->GetRowCount(), 23); packet.WriteBits(raceResult->GetRowCount(), 23); packet.WriteBit(0); packet.WriteBit(0); packet.WriteBits(0, 21); } packet.WriteBit(queued); if (queued) packet.WriteBit(1); // Unknown packet.FlushBits(); if (queued) packet << uint32(0); // Unknown if (code == AUTH_OK) { packet << uint32(0); packet << uint8(Expansion()); packet << uint8(Expansion()); do { Field* fields = raceResult->Fetch(); packet << fields[0].GetUInt8(); packet << fields[1].GetUInt8(); } while (raceResult->NextRow()); packet << uint32(0); packet << uint32(0); packet << uint32(0); do { Field* fields = classResult->Fetch(); packet << fields[0].GetUInt8(); packet << fields[1].GetUInt8(); } while (classResult->NextRow()); packet << uint32(0); } SendPacket(&packet); }