[6982] Implemented gmlevel-based command security
[getmangos.git] / src / game / PetitionsHandler.cpp
blob712d8bc36dafc033f7749f013b74fa8ce84d3570
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "Common.h"
20 #include "Language.h"
21 #include "WorldPacket.h"
22 #include "WorldSession.h"
23 #include "World.h"
24 #include "ObjectMgr.h"
25 #include "Log.h"
26 #include "Opcodes.h"
27 #include "Guild.h"
28 #include "ArenaTeam.h"
29 #include "MapManager.h"
30 #include "GossipDef.h"
31 #include "SocialMgr.h"
33 /*enum PetitionType // dbc data
35 PETITION_TYPE_GUILD = 1,
36 PETITION_TYPE_ARENA_TEAM = 3
37 };*/
39 // Charters ID in item_template
40 #define GUILD_CHARTER 5863
41 #define GUILD_CHARTER_COST 1000 // 10 S
42 #define ARENA_TEAM_CHARTER_2v2 23560
43 #define ARENA_TEAM_CHARTER_2v2_COST 800000 // 80 G
44 #define ARENA_TEAM_CHARTER_3v3 23561
45 #define ARENA_TEAM_CHARTER_3v3_COST 1200000 // 120 G
46 #define ARENA_TEAM_CHARTER_5v5 23562
47 #define ARENA_TEAM_CHARTER_5v5_COST 2000000 // 200 G
49 void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
51 CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4);
53 sLog.outDebug("Received opcode CMSG_PETITION_BUY");
54 //recv_data.hexlike();
56 uint64 guidNPC;
57 uint64 unk1, unk3, unk4, unk5, unk6, unk7;
58 uint32 unk2;
59 std::string name;
60 uint16 unk8;
61 uint8 unk9;
62 uint32 unk10; // selected index
63 uint32 unk11;
64 recv_data >> guidNPC; // NPC GUID
65 recv_data >> unk1; // 0
66 recv_data >> unk2; // 0
67 recv_data >> name; // name
69 // recheck
70 CHECK_PACKET_SIZE(recv_data, 8+8+4+(name.size()+1)+5*8+2+1+4+4);
72 recv_data >> unk3; // 0
73 recv_data >> unk4; // 0
74 recv_data >> unk5; // 0
75 recv_data >> unk6; // 0
76 recv_data >> unk7; // 0
77 recv_data >> unk8; // 0
78 recv_data >> unk9; // 0
79 recv_data >> unk10; // index
80 recv_data >> unk11; // 0
81 sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
83 // prevent cheating
84 Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guidNPC,UNIT_NPC_FLAG_PETITIONER);
85 if (!pCreature)
87 sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
88 return;
91 // remove fake death
92 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
93 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
95 uint32 charterid = 0;
96 uint32 cost = 0;
97 uint32 type = 0;
98 if(pCreature->isTabardDesigner())
100 // if tabard designer, then trying to buy a guild charter.
101 // do not let if already in guild.
102 if(_player->GetGuildId())
103 return;
105 charterid = GUILD_CHARTER;
106 cost = GUILD_CHARTER_COST;
107 type = 9;
109 else
111 // TODO: find correct opcode
112 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
114 SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
115 return;
118 switch(unk10)
120 case 1:
121 charterid = ARENA_TEAM_CHARTER_2v2;
122 cost = ARENA_TEAM_CHARTER_2v2_COST;
123 type = 2; // 2v2
124 break;
125 case 2:
126 charterid = ARENA_TEAM_CHARTER_3v3;
127 cost = ARENA_TEAM_CHARTER_3v3_COST;
128 type = 3; // 3v3
129 break;
130 case 3:
131 charterid = ARENA_TEAM_CHARTER_5v5;
132 cost = ARENA_TEAM_CHARTER_5v5_COST;
133 type = 5; // 5v5
134 break;
135 default:
136 sLog.outDebug("unknown selection at buy petition: %u", unk10);
137 return;
140 if(_player->GetArenaTeamId(unk10-1))
142 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
143 return;
147 if(type == 9)
149 if(objmgr.GetGuildByName(name))
151 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
152 return;
154 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
156 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
157 return;
160 else
162 if(objmgr.GetArenaTeamByName(name))
164 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
165 return;
167 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
169 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
170 return;
174 ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid);
175 if(!pProto)
177 _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
178 return;
181 if(_player->GetMoney() < cost)
182 { //player hasn't got enough money
183 _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
184 return;
187 ItemPosCountVec dest;
188 uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount );
189 if(msg != EQUIP_ERR_OK)
191 _player->SendBuyError(msg, pCreature, charterid, 0);
192 return;
195 _player->ModifyMoney(-(int32)cost);
196 Item *charter = _player->StoreNewItem(dest, charterid, true);
197 if(!charter)
198 return;
200 charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
201 // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
202 // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
203 charter->SetState(ITEM_CHANGED, _player);
204 _player->SendNewItem(charter, 1, true, false);
206 // a petition is invalid, if both the owner and the type matches
207 // we checked above, if this player is in an arenateam, so this must be
208 // datacorruption
209 QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);
211 std::ostringstream ssInvalidPetitionGUIDs;
213 if (result)
218 Field *fields = result->Fetch();
219 ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";
220 } while (result->NextRow());
222 delete result;
225 // delete petitions with the same guid as this one
226 ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";
228 sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
229 CharacterDatabase.escape_string(name);
230 CharacterDatabase.BeginTransaction();
231 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
232 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
233 CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')",
234 _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);
235 CharacterDatabase.CommitTransaction();
238 void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
240 CHECK_PACKET_SIZE(recv_data, 8);
242 // ok
243 sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
244 //recv_data.hexlike();
246 uint8 signs = 0;
247 uint64 petitionguid;
248 recv_data >> petitionguid; // petition guid
250 // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
251 uint32 petitionguid_low = GUID_LOPART(petitionguid);
253 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
254 if(!result)
256 sLog.outError("any petition on server...");
257 return;
259 Field *fields = result->Fetch();
260 uint32 type = fields[0].GetUInt32();
261 delete result;
263 // if guild petition and has guild => error, return;
264 if(type==9 && _player->GetGuildId())
265 return;
267 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);
269 // result==NULL also correct in case no sign yet
270 if(result)
271 signs = result->GetRowCount();
273 sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);
275 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
276 data << petitionguid; // petition guid
277 data << _player->GetGUID(); // owner guid
278 data << petitionguid_low; // guild guid (in mangos always same as GUID_LOPART(petitionguid)
279 data << signs; // sign's count
281 for(uint8 i = 1; i <= signs; i++)
283 Field *fields = result->Fetch();
284 uint64 plguid = fields[0].GetUInt64();
286 data << plguid; // Player GUID
287 data << (uint32)0; // there 0 ...
289 result->NextRow();
291 delete result;
292 SendPacket(&data);
295 void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data)
297 CHECK_PACKET_SIZE(recv_data, 4+8);
299 sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok
300 //recv_data.hexlike();
302 uint32 guildguid;
303 uint64 petitionguid;
304 recv_data >> guildguid; // in mangos always same as GUID_LOPART(petitionguid)
305 recv_data >> petitionguid; // petition guid
306 sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid);
308 SendPetitionQueryOpcode(petitionguid);
311 void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
313 uint64 ownerguid = 0;
314 uint32 type;
315 std::string name = "NO_NAME_FOR_GUID";
316 uint8 signs = 0;
318 QueryResult *result = CharacterDatabase.PQuery(
319 "SELECT ownerguid, name, "
320 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
321 " type "
322 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
324 if(result)
326 Field* fields = result->Fetch();
327 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
328 name = fields[1].GetCppString();
329 signs = fields[2].GetUInt8();
330 type = fields[3].GetUInt32();
331 delete result;
333 else
335 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
336 return;
339 WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
340 data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
341 data << ownerguid; // charter owner guid
342 data << name; // name (guild/arena team)
343 data << uint8(0); // 1
344 if(type == 9)
346 data << uint32(9);
347 data << uint32(9);
348 data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition
350 else
352 data << type-1;
353 data << type-1;
354 data << type; // bypass client - side limitation, a different value is needed here for each petition
356 data << uint32(0); // 5
357 data << uint32(0); // 6
358 data << uint32(0); // 7
359 data << uint32(0); // 8
360 data << uint16(0); // 9 2 bytes field
361 data << uint32(0); // 10
362 data << uint32(0); // 11
363 data << uint32(0); // 13 count of next strings?
364 data << uint32(0); // 14
365 if(type == 9)
366 data << uint32(0); // 15 0 - guild, 1 - arena team
367 else
368 data << uint32(1);
369 SendPacket(&data);
372 void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
374 CHECK_PACKET_SIZE(recv_data, 8+1);
376 sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok
377 //recv_data.hexlike();
379 uint64 petitionguid;
380 uint32 type;
381 std::string newname;
383 recv_data >> petitionguid; // guid
384 recv_data >> newname; // new name
386 Item *item = _player->GetItemByGuid(petitionguid);
387 if(!item)
388 return;
390 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
392 if(result)
394 Field* fields = result->Fetch();
395 type = fields[0].GetUInt32();
396 delete result;
398 else
400 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
401 return;
404 if(type == 9)
406 if(objmgr.GetGuildByName(newname))
408 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
409 return;
411 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
413 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
414 return;
417 else
419 if(objmgr.GetArenaTeamByName(newname))
421 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
422 return;
424 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
426 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
427 return;
431 std::string db_newname = newname;
432 CharacterDatabase.escape_string(db_newname);
433 CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'",
434 db_newname.c_str(), GUID_LOPART(petitionguid));
436 sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str());
437 WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
438 data << petitionguid;
439 data << newname;
440 SendPacket(&data);
443 void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
445 CHECK_PACKET_SIZE(recv_data, 8+1);
447 sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok
448 //recv_data.hexlike();
450 Field *fields;
451 uint64 petitionguid;
452 uint8 unk;
453 recv_data >> petitionguid; // petition guid
454 recv_data >> unk;
456 QueryResult *result = CharacterDatabase.PQuery(
457 "SELECT ownerguid, "
458 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
459 " type "
460 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
462 if(!result)
464 sLog.outError("any petition on server...");
465 return;
468 fields = result->Fetch();
469 uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
470 uint8 signs = fields[1].GetUInt8();
471 uint32 type = fields[2].GetUInt32();
473 delete result;
475 uint32 plguidlo = _player->GetGUIDLow();
476 if(GUID_LOPART(ownerguid) == plguidlo)
477 return;
479 // not let enemies sign guild charter
480 if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
482 if(type != 9)
483 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
484 else
485 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
486 return;
489 if(type != 9)
491 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
493 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
494 return;
497 uint8 slot = ArenaTeam::GetSlotByType(type);
498 if(slot >= MAX_ARENA_SLOT)
499 return;
501 if(_player->GetArenaTeamId(slot))
503 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
504 return;
507 if(_player->GetArenaTeamIdInvited())
509 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
510 return;
513 else
515 if(_player->GetGuildId())
517 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
518 return;
520 if(_player->GetGuildIdInvited())
522 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
523 return;
527 if(++signs > type) // client signs maximum
528 return;
530 //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
531 //not allow sign another player from already sign player account
532 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
534 if(result)
536 delete result;
537 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
538 data << petitionguid;
539 data << _player->GetGUID();
540 data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
542 // close at signer side
543 SendPacket(&data);
545 // update for owner if online
546 if(Player *owner = objmgr.GetPlayer(ownerguid))
547 owner->GetSession()->SendPacket(&data);
548 return;
551 CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
553 sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
555 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
556 data << petitionguid;
557 data << _player->GetGUID();
558 data << (uint32)PETITION_SIGN_OK;
560 // close at signer side
561 SendPacket(&data);
563 // update signs count on charter, required testing...
564 //Item *item = _player->GetItemByGuid(petitionguid));
565 //if(item)
566 // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
568 // update for owner if online
569 if(Player *owner = objmgr.GetPlayer(ownerguid))
570 owner->GetSession()->SendPacket(&data);
573 void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
575 CHECK_PACKET_SIZE(recv_data, 8);
577 sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok
578 //recv_data.hexlike();
580 uint64 petitionguid;
581 uint64 ownerguid;
582 recv_data >> petitionguid; // petition guid
583 sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
585 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
586 if(!result)
587 return;
589 Field *fields = result->Fetch();
590 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
591 delete result;
593 Player *owner = objmgr.GetPlayer(ownerguid);
594 if(owner) // petition owner online
596 WorldPacket data(MSG_PETITION_DECLINE, 8);
597 data << _player->GetGUID();
598 owner->GetSession()->SendPacket(&data);
602 void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
604 CHECK_PACKET_SIZE(recv_data, 4+8+8);
606 sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok
607 //recv_data.hexlike();
609 uint8 signs = 0;
610 uint64 petitionguid, plguid;
611 uint32 type, junk;
612 Player *player;
613 recv_data >> junk; // this is not petition type!
614 recv_data >> petitionguid; // petition guid
615 recv_data >> plguid; // player guid
617 player = ObjectAccessor::FindPlayer(plguid);
618 if (!player)
619 return;
621 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
622 if (!result)
623 return;
625 Field *fields = result->Fetch();
626 type = fields[0].GetUInt32();
627 delete result;
629 sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
631 if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
633 if(type != 9)
634 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
635 else
636 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
637 return;
640 if(type != 9)
642 if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
644 // player is too low level to join an arena team
645 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
646 return;
649 uint8 slot = ArenaTeam::GetSlotByType(type);
650 if(slot >= MAX_ARENA_SLOT)
651 return;
653 if(player->GetArenaTeamId(slot))
655 // player is already in an arena team
656 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
657 return;
660 if(player->GetArenaTeamIdInvited())
662 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
663 return;
666 else
668 if(player->GetGuildId())
670 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
671 return;
674 if(player->GetGuildIdInvited())
676 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
677 return;
681 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
682 // result==NULL also correct charter without signs
683 if(result)
684 signs = result->GetRowCount();
686 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
687 data << petitionguid; // petition guid
688 data << _player->GetGUID(); // owner guid
689 data << GUID_LOPART(petitionguid); // guild guid (in mangos always same as GUID_LOPART(petition guid)
690 data << signs; // sign's count
692 for(uint8 i = 1; i <= signs; i++)
694 Field *fields = result->Fetch();
695 uint64 plguid = fields[0].GetUInt64();
697 data << plguid; // Player GUID
698 data << (uint32)0; // there 0 ...
700 result->NextRow();
703 delete result;
704 player->GetSession()->SendPacket(&data);
707 void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
709 CHECK_PACKET_SIZE(recv_data, 8);
711 sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
712 //recv_data.hexlike();
714 WorldPacket data;
715 uint64 petitionguid;
717 uint32 ownerguidlo;
718 uint32 type;
719 std::string name;
721 recv_data >> petitionguid;
723 sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
725 // data
726 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
727 if(result)
729 Field *fields = result->Fetch();
730 ownerguidlo = fields[0].GetUInt32();
731 name = fields[1].GetCppString();
732 type = fields[2].GetUInt32();
733 delete result;
735 else
737 sLog.outError("petition table has broken data!");
738 return;
741 if(type == 9)
743 if(_player->GetGuildId())
745 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
746 data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
747 _player->GetSession()->SendPacket(&data);
748 return;
751 else
753 uint8 slot = ArenaTeam::GetSlotByType(type);
754 if(slot >= MAX_ARENA_SLOT)
755 return;
757 if(_player->GetArenaTeamId(slot))
759 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
760 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
761 //_player->GetSession()->SendPacket(&data);
762 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
763 return;
767 if(_player->GetGUIDLow() != ownerguidlo)
768 return;
770 // signs
771 uint8 signs;
772 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
773 if(result)
774 signs = result->GetRowCount();
775 else
776 signs = 0;
778 uint32 count;
779 //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
780 if(type == 9)
781 count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
782 else
783 count = type-1;
784 if(signs < count)
786 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
787 data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
788 SendPacket(&data);
789 delete result;
790 return;
793 if(type == 9)
795 if(objmgr.GetGuildByName(name))
797 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
798 delete result;
799 return;
802 else
804 if(objmgr.GetArenaTeamByName(name))
806 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
807 delete result;
808 return;
812 // and at last charter item check
813 Item *item = _player->GetItemByGuid(petitionguid);
814 if(!item)
816 delete result;
817 return;
820 // OK!
822 // delete charter item
823 _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);
825 if(type == 9) // create guild
827 Guild* guild = new Guild;
828 if(!guild->create(_player->GetGUID(), name))
830 delete guild;
831 delete result;
832 return;
835 // register guild and add guildmaster
836 objmgr.AddGuild(guild);
838 // add members
839 for(uint8 i = 0; i < signs; ++i)
841 Field* fields = result->Fetch();
842 guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
843 result->NextRow();
846 else // or arena team
848 ArenaTeam* at = new ArenaTeam;
849 if(!at->Create(_player->GetGUID(), type, name))
851 sLog.outError("PetitionsHandler: arena team create failed.");
852 delete at;
853 delete result;
854 return;
857 CHECK_PACKET_SIZE(recv_data, 8+5*4);
858 uint32 icon, iconcolor, border, bordercolor, backgroud;
859 recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
861 at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
863 // register team and add captain
864 objmgr.AddArenaTeam(at);
865 sLog.outDebug("PetitonsHandler: arena team added to objmrg");
867 // add members
868 for(uint8 i = 0; i < signs; ++i)
870 Field* fields = result->Fetch();
871 uint64 memberGUID = fields[0].GetUInt64();
872 sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
873 at->AddMember(memberGUID);
874 result->NextRow();
878 delete result;
880 CharacterDatabase.BeginTransaction();
881 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
882 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
883 CharacterDatabase.CommitTransaction();
885 // created
886 sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
888 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
889 data << (uint32)PETITION_TURN_OK;
890 SendPacket(&data);
893 void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
895 CHECK_PACKET_SIZE(recv_data, 8);
897 sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok
898 //recv_data.hexlike();
900 uint64 guid;
901 recv_data >> guid;
903 SendPetitionShowList(guid);
906 void WorldSession::SendPetitionShowList(uint64 guid)
908 Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_PETITIONER);
909 if (!pCreature)
911 sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
912 return;
915 // remove fake death
916 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
917 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
919 uint8 count = 0;
920 if(pCreature->isTabardDesigner())
921 count = 1;
922 else
923 count = 3;
925 WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
926 data << guid; // npc guid
927 data << count; // count
928 if(count == 1)
930 data << uint32(1); // index
931 data << uint32(GUILD_CHARTER); // charter entry
932 data << uint32(16161); // charter display id
933 data << uint32(GUILD_CHARTER_COST); // charter cost
934 data << uint32(0); // unknown
935 data << uint32(9); // required signs?
937 else
939 // 2v2
940 data << uint32(1); // index
941 data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
942 data << uint32(16161); // charter display id
943 data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
944 data << uint32(2); // unknown
945 data << uint32(2); // required signs?
946 // 3v3
947 data << uint32(2); // index
948 data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
949 data << uint32(16161); // charter display id
950 data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
951 data << uint32(3); // unknown
952 data << uint32(3); // required signs?
953 // 5v5
954 data << uint32(3); // index
955 data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
956 data << uint32(16161); // charter display id
957 data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
958 data << uint32(5); // unknown
959 data << uint32(5); // required signs?
961 //for(uint8 i = 0; i < count; i++)
963 // data << uint32(i); // index
964 // data << uint32(GUILD_CHARTER); // charter entry
965 // data << uint32(16161); // charter display id
966 // data << uint32(GUILD_CHARTER_COST+i); // charter cost
967 // data << uint32(0); // unknown
968 // data << uint32(9); // required signs?
970 SendPacket(&data);
971 sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");