Index: src/game/ArenaTeam.cpp===================================================================--- src/game/ArenaTeam.cpp (revision 5306)+++ src/game/ArenaTeam.cpp (working copy)@@ -88,11 +88,21 @@ std::string plName; uint8 plClass;+ if(GetMembersSize() >= GetType() * 2)+ {+ // arena team is full (can't have more than type * 2 players!)+ // return false+ return false;+ }+ if(!objmgr.GetPlayerNameByGUID(PlayerGuid, plName)) // player doesnt exist return false; // player already in arenateam of that size- if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetSlot()) != 0)+ if(Player::GetArenaTeamIdFromDB(PlayerGuid, GetType()) != 0)+ {+ sLog.outError("Arena::AddMember() : player already in this sized team"); return false;+ } // remove all player signs from another petitions // this will be prevent attempt joining player to many arenateams and corrupt arena team data integrityIndex: src/game/ArenaTeamHandler.cpp===================================================================--- src/game/ArenaTeamHandler.cpp (revision 5306)+++ src/game/ArenaTeamHandler.cpp (working copy)@@ -111,7 +111,7 @@ return; }- if(player->getLevel() != 70)+ if(player->getLevel() < 70) { //SendArenaTeamCommandResult(ARENA_TEAM_INVITE_SS,"",Invitedname,ARENA_TEAM_PLAYER_NOT_FOUND_S); // can't find related opcode@@ -148,6 +148,14 @@ return; }+ if(arenateam->GetMembersSize() >= arenateam->GetType() * 2)+ {+ // should send an "arena team is full" or the likes message, I just don't know the proper values so... ERR_INTERNAL+// SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_INTERNAL);+ SendNotification("Your arena team is full, %s cannot join it.", player->GetName());+ return;+ }+ sLog.outDebug("Player %s Invited %s to Join his ArenaTeam", GetPlayer()->GetName(), Invitedname.c_str()); player->SetArenaTeamIdInvited(GetPlayer()->GetArenaTeamId(team_slot));Index: src/game/PetitionsHandler.cpp===================================================================--- src/game/PetitionsHandler.cpp (revision 5306)+++ src/game/PetitionsHandler.cpp (working copy)@@ -49,9 +49,6 @@ { CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4);- if(_player->GetGuildId())- return;- sLog.outDebug("Received opcode CMSG_PETITION_BUY"); //recv_data.hexlike();@@ -95,6 +92,11 @@ uint32 type = 0; if(pCreature->isTabardDesigner()) {+ // if tabard designer, then trying to buy a guild charter.+ // do not let if already in guild.+ if(_player->GetGuildId())+ return;+ charterid = GUILD_CHARTER; cost = GUILD_CHARTER_COST; type = 9;@@ -102,7 +104,7 @@ else { // TODO: find correct opcode- if(_player->getLevel() != 70)+ if(_player->getLevel() < 70) { SendNotification(objmgr.GetMangosString(LANG_ARENA_ONE_TOOLOW, GetSessionLocaleIndex()), 70); return;@@ -188,10 +190,31 @@ charter->SetState(ITEM_CHANGED, _player); _player->SendNewItem(charter, 1, true, false);+ // a petition is invalid, if both the owner and the type matches+ QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);++ std::ostringstream ssInvalidPetitionGUIDs;++ if (result)+ {++ do+ {+ Field *fields = result->Fetch();+ ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";+ } while (result->NextRow());++ delete result;+ }++ // delete petitions with the same guid as this one+ ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";++ sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str()); CharacterDatabase.escape_string(name); CharacterDatabase.BeginTransaction();- CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u' OR petitionguid = '%u' and type = '%u'", _player->GetGUIDLow(), charter->GetGUIDLow(),type);- CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u' or petitionguid = '%u'", _player->GetGUIDLow(), charter->GetGUIDLow());+ CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());+ CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str()); CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')", _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type); CharacterDatabase.CommitTransaction();@@ -205,9 +228,6 @@ sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES"); //recv_data.hexlike();- if(_player->GetGuildId())- return;- uint8 signs = 0; uint64 petitionguid; recv_data >> petitionguid; // petition guid@@ -215,14 +235,18 @@ // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?) uint32 petitionguid_low = GUID_LOPART(petitionguid);- QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", petitionguid_low);+ QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low); if(!result) { sLog.outError("any petition on server..."); return; }-+ Field *fields = result->Fetch();+ uint32 type = fields[1].GetUInt32(); delete result;+ // if guild petition and has guild => error, return;+ if(type==9 && _player->GetGuildId())+ return; result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);@@ -317,13 +341,14 @@ { data << uint32(9); data << uint32(9);+ data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition } else { data << type-1; data << type-1;+ data << type; // bypass client - side limitation, a different value is needed here for each petition }- data << uint32(0); // 4 data << uint32(0); // 5 data << uint32(0); // 6 data << uint32(0); // 7@@ -457,13 +482,20 @@ return; }+ if(type != 9 && _player->getLevel() < 70)+ {+ // player is too low level to join an arena team+ SendNotification("You must be level 70 to join an arena team!");+ return;+ }+ signs += 1; if(signs > type) // client signs maximum return; //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account //not allow sign another player from already sign player account- result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u'", GetAccountId());+ result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid)); if(result) {@@ -638,16 +670,29 @@ } else {- for(uint8 i = 0; i < 3; i++)+ uint32 type_slot;+ switch(type) {- if(_player->GetArenaTeamId(i))- {+ case ARENA_TEAM_2v2:+ type_slot = 0;+ break;+ case ARENA_TEAM_3v3:+ type_slot = 1;+ break;+ case ARENA_TEAM_5v5:+ type_slot = 2;+ break;+ default:+ type_slot = 0;+ break;+ }+ if(_player->GetArenaTeamId(type_slot))+ { //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4); //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild //_player->GetSession()->SendPacket(&data); SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM); return;- } } }@@ -735,6 +780,7 @@ ArenaTeam* at = new ArenaTeam; if(!at->create(_player->GetGUID(), type, name)) {+ sLog.outError("PetitionsHandler: arena team create failed."); delete at; delete result; return;@@ -748,11 +794,13 @@ // register team and add captain objmgr.AddArenaTeam(at);+ sLog.outDebug("PetitonsHandler: arena team added to objmrg"); // add members for(uint8 i = 0; i < signs; ++i) { Field* fields = result->Fetch();+ sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64()); at->AddMember(fields[0].GetUInt64()); result->NextRow(); }@@ -820,21 +868,21 @@ data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry data << uint32(16161); // charter display id data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost- data << uint32(0); // unknown+ data << uint32(2); // unknown data << uint32(2); // required signs? // 3v3 data << uint32(2); // index data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry data << uint32(16161); // charter display id data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost- data << uint32(0); // unknown+ data << uint32(3); // unknown data << uint32(3); // required signs? // 5v5 data << uint32(3); // index data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry data << uint32(16161); // charter display id data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost- data << uint32(0); // unknown+ data << uint32(5); // unknown data << uint32(5); // required signs? } //for(uint8 i = 0; i < count; i++)Index: src/game/Player.cpp===================================================================--- src/game/Player.cpp (revision 5306)+++ src/game/Player.cpp (working copy)@@ -5659,27 +5659,33 @@ return 0; }-uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 slot)+uint32 Player::GetArenaTeamIdFromDB(uint64 guid, uint8 type) { // need fix it! QueryResult *result = CharacterDatabase.PQuery("SELECT arenateamid FROM arena_team_member WHERE guid='%u'", GUID_LOPART(guid)); if(result) {- uint32 id = (*result)[0].GetUInt32();+ // init id to 0, check the arena type before assigning a value to id+ uint32 id = 0; do { QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM arena_team WHERE arenateamid='%u'", id); if(result2) {- uint8 dbslot = (*result2)[0].GetUInt32();+ uint8 dbtype = (*result2)[0].GetUInt32(); delete result2;- if(dbslot == slot)+ if(dbtype == type)+ {+ // if the type matches, we've found the id+ id = (*result)[0].GetUInt32(); break;+ } } } while(result->NextRow()); delete result; return id; }+ // no arenateam for the specified guid, return 0 return 0; }@@ -14894,11 +14900,15 @@ void Player::RemovePetitionsAndSigns(uint64 guid, uint32 type) {- QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid,petitionguid FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid));+ QueryResult *result = NULL;+ if(type==10)+ result = CharacterDatabase.PQuery("SELECT ownerguid,petitionguid FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid));+ else+ result = CharacterDatabase.PQuery("SELECT ownerguid,petitionguid FROM petition_sign WHERE playerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); if(result) {- do- {+ do // this part effectively does nothing, since the deletion / modification only takes place _after_ the PetitionQuery. Though I don't know if the result remains intact if I execute the delete query beforehand.+ { // and SendPetitionQueryOpcode reads data from the DB Field *fields = result->Fetch(); uint64 ownerguid = MAKE_GUID(fields[0].GetUInt32(), HIGHGUID_PLAYER); uint64 petitionguid = MAKE_GUID(fields[1].GetUInt32(), HIGHGUID_ITEM);@@ -14912,15 +14922,23 @@ delete result;- CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid));+ if(type==10)+ CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u'", GUID_LOPART(guid));+ else+ CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE playerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type); } CharacterDatabase.BeginTransaction(); if(type == 10)+ { CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u'", GUID_LOPART(guid));+ CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u'", GUID_LOPART(guid));+ } else+ { CharacterDatabase.PExecute("DELETE FROM petition WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type);- CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u'", GUID_LOPART(guid));+ CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE ownerguid = '%u' AND type = '%u'", GUID_LOPART(guid), type);+ } CharacterDatabase.CommitTransaction(); }