[7915] Implement more stricted checks and limitations at loading creature addon data.
[getmangos.git] / src / game / PetitionsHandler.cpp
blobe5da6cf848a0fb796195267b148f71a2ac15489f
1 /*
2 * Copyright (C) 2005-2009 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 "GossipDef.h"
30 #include "SocialMgr.h"
32 /*enum PetitionType // dbc data
34 PETITION_TYPE_GUILD = 1,
35 PETITION_TYPE_ARENA_TEAM = 3
36 };*/
38 // Charters ID in item_template
39 #define GUILD_CHARTER 5863
40 #define GUILD_CHARTER_COST 1000 // 10 S
41 #define ARENA_TEAM_CHARTER_2v2 23560
42 #define ARENA_TEAM_CHARTER_2v2_COST 800000 // 80 G
43 #define ARENA_TEAM_CHARTER_3v3 23561
44 #define ARENA_TEAM_CHARTER_3v3_COST 1200000 // 120 G
45 #define ARENA_TEAM_CHARTER_5v5 23562
46 #define ARENA_TEAM_CHARTER_5v5_COST 2000000 // 200 G
48 void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
50 CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4);
52 sLog.outDebug("Received opcode CMSG_PETITION_BUY");
53 //recv_data.hexlike();
55 uint64 guidNPC;
56 uint64 unk1, unk3, unk4, unk5, unk6, unk7;
57 uint32 unk2;
58 std::string name;
59 uint16 unk8;
60 uint8 unk9;
61 uint32 unk10; // selected index
62 uint32 unk11;
63 recv_data >> guidNPC; // NPC GUID
64 recv_data >> unk1; // 0
65 recv_data >> unk2; // 0
66 recv_data >> name; // name
68 // recheck
69 CHECK_PACKET_SIZE(recv_data, 8+8+4+(name.size()+1)+5*8+2+1+4+4);
71 recv_data >> unk3; // 0
72 recv_data >> unk4; // 0
73 recv_data >> unk5; // 0
74 recv_data >> unk6; // 0
75 recv_data >> unk7; // 0
76 recv_data >> unk8; // 0
77 recv_data >> unk9; // 0
78 recv_data >> unk10; // index
79 recv_data >> unk11; // 0
80 sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
82 // prevent cheating
83 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER);
84 if (!pCreature)
86 sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
87 return;
90 // remove fake death
91 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
92 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
94 uint32 charterid = 0;
95 uint32 cost = 0;
96 uint32 type = 0;
97 if(pCreature->isTabardDesigner())
99 // if tabard designer, then trying to buy a guild charter.
100 // do not let if already in guild.
101 if(_player->GetGuildId())
102 return;
104 charterid = GUILD_CHARTER;
105 cost = GUILD_CHARTER_COST;
106 type = 9;
108 else
110 // TODO: find correct opcode
111 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
113 SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
114 return;
117 switch(unk10)
119 case 1:
120 charterid = ARENA_TEAM_CHARTER_2v2;
121 cost = ARENA_TEAM_CHARTER_2v2_COST;
122 type = 2; // 2v2
123 break;
124 case 2:
125 charterid = ARENA_TEAM_CHARTER_3v3;
126 cost = ARENA_TEAM_CHARTER_3v3_COST;
127 type = 3; // 3v3
128 break;
129 case 3:
130 charterid = ARENA_TEAM_CHARTER_5v5;
131 cost = ARENA_TEAM_CHARTER_5v5_COST;
132 type = 5; // 5v5
133 break;
134 default:
135 sLog.outDebug("unknown selection at buy petition: %u", unk10);
136 return;
139 if(_player->GetArenaTeamId(unk10-1))
141 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
142 return;
146 if(type == 9)
148 if(objmgr.GetGuildByName(name))
150 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
151 return;
153 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
155 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
156 return;
159 else
161 if(objmgr.GetArenaTeamByName(name))
163 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
164 return;
166 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
168 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
169 return;
173 ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid);
174 if(!pProto)
176 _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
177 return;
180 if(_player->GetMoney() < cost)
181 { //player hasn't got enough money
182 _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
183 return;
186 ItemPosCountVec dest;
187 uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount );
188 if(msg != EQUIP_ERR_OK)
190 _player->SendBuyError(msg, pCreature, charterid, 0);
191 return;
194 _player->ModifyMoney(-(int32)cost);
195 Item *charter = _player->StoreNewItem(dest, charterid, true);
196 if(!charter)
197 return;
199 charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
200 // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
201 // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
202 charter->SetState(ITEM_CHANGED, _player);
203 _player->SendNewItem(charter, 1, true, false);
205 // a petition is invalid, if both the owner and the type matches
206 // we checked above, if this player is in an arenateam, so this must be
207 // datacorruption
208 QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);
210 std::ostringstream ssInvalidPetitionGUIDs;
212 if (result)
217 Field *fields = result->Fetch();
218 ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";
219 } while (result->NextRow());
221 delete result;
224 // delete petitions with the same guid as this one
225 ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";
227 sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
228 CharacterDatabase.escape_string(name);
229 CharacterDatabase.BeginTransaction();
230 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
231 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
232 CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')",
233 _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);
234 CharacterDatabase.CommitTransaction();
237 void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
239 CHECK_PACKET_SIZE(recv_data, 8);
241 // ok
242 sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
243 //recv_data.hexlike();
245 uint8 signs = 0;
246 uint64 petitionguid;
247 recv_data >> petitionguid; // petition guid
249 // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
250 uint32 petitionguid_low = GUID_LOPART(petitionguid);
252 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
253 if(!result)
255 sLog.outError("any petition on server...");
256 return;
258 Field *fields = result->Fetch();
259 uint32 type = fields[0].GetUInt32();
260 delete result;
262 // if guild petition and has guild => error, return;
263 if(type==9 && _player->GetGuildId())
264 return;
266 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);
268 // result==NULL also correct in case no sign yet
269 if(result)
270 signs = result->GetRowCount();
272 sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);
274 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
275 data << petitionguid; // petition guid
276 data << _player->GetGUID(); // owner guid
277 data << petitionguid_low; // guild guid (in mangos always same as GUID_LOPART(petitionguid)
278 data << signs; // sign's count
280 for(uint8 i = 1; i <= signs; ++i)
282 Field *fields2 = result->Fetch();
283 uint64 plguid = fields2[0].GetUInt64();
285 data << plguid; // Player GUID
286 data << (uint32)0; // there 0 ...
288 result->NextRow();
290 delete result;
291 SendPacket(&data);
294 void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data)
296 CHECK_PACKET_SIZE(recv_data, 4+8);
298 sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok
299 //recv_data.hexlike();
301 uint32 guildguid;
302 uint64 petitionguid;
303 recv_data >> guildguid; // in mangos always same as GUID_LOPART(petitionguid)
304 recv_data >> petitionguid; // petition guid
305 sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid);
307 SendPetitionQueryOpcode(petitionguid);
310 void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
312 uint64 ownerguid = 0;
313 uint32 type;
314 std::string name = "NO_NAME_FOR_GUID";
315 uint8 signs = 0;
317 QueryResult *result = CharacterDatabase.PQuery(
318 "SELECT ownerguid, name, "
319 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
320 " type "
321 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
323 if(result)
325 Field* fields = result->Fetch();
326 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
327 name = fields[1].GetCppString();
328 signs = fields[2].GetUInt8();
329 type = fields[3].GetUInt32();
330 delete result;
332 else
334 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
335 return;
338 WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
339 data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
340 data << ownerguid; // charter owner guid
341 data << name; // name (guild/arena team)
342 data << uint8(0); // 1
343 if(type == 9)
345 data << uint32(9);
346 data << uint32(9);
347 data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition
349 else
351 data << type-1;
352 data << type-1;
353 data << type; // bypass client - side limitation, a different value is needed here for each petition
355 data << uint32(0); // 5
356 data << uint32(0); // 6
357 data << uint32(0); // 7
358 data << uint32(0); // 8
359 data << uint16(0); // 9 2 bytes field
360 data << uint32(0); // 10
361 data << uint32(0); // 11
362 data << uint32(0); // 13 count of next strings?
363 data << uint32(0); // 14
364 if(type == 9)
365 data << uint32(0); // 15 0 - guild, 1 - arena team
366 else
367 data << uint32(1);
368 SendPacket(&data);
371 void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
373 CHECK_PACKET_SIZE(recv_data, 8+1);
375 sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok
376 //recv_data.hexlike();
378 uint64 petitionguid;
379 uint32 type;
380 std::string newname;
382 recv_data >> petitionguid; // guid
383 recv_data >> newname; // new name
385 Item *item = _player->GetItemByGuid(petitionguid);
386 if(!item)
387 return;
389 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
391 if(result)
393 Field* fields = result->Fetch();
394 type = fields[0].GetUInt32();
395 delete result;
397 else
399 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
400 return;
403 if(type == 9)
405 if(objmgr.GetGuildByName(newname))
407 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
408 return;
410 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
412 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
413 return;
416 else
418 if(objmgr.GetArenaTeamByName(newname))
420 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
421 return;
423 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
425 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
426 return;
430 std::string db_newname = newname;
431 CharacterDatabase.escape_string(db_newname);
432 CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'",
433 db_newname.c_str(), GUID_LOPART(petitionguid));
435 sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str());
436 WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
437 data << petitionguid;
438 data << newname;
439 SendPacket(&data);
442 void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
444 CHECK_PACKET_SIZE(recv_data, 8+1);
446 sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok
447 //recv_data.hexlike();
449 Field *fields;
450 uint64 petitionguid;
451 uint8 unk;
452 recv_data >> petitionguid; // petition guid
453 recv_data >> unk;
455 QueryResult *result = CharacterDatabase.PQuery(
456 "SELECT ownerguid, "
457 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
458 " type "
459 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
461 if(!result)
463 sLog.outError("any petition on server...");
464 return;
467 fields = result->Fetch();
468 uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
469 uint8 signs = fields[1].GetUInt8();
470 uint32 type = fields[2].GetUInt32();
472 delete result;
474 uint32 plguidlo = _player->GetGUIDLow();
475 if(GUID_LOPART(ownerguid) == plguidlo)
476 return;
478 // not let enemies sign guild charter
479 if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
481 if(type != 9)
482 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
483 else
484 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
485 return;
488 if(type != 9)
490 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
492 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
493 return;
496 uint8 slot = ArenaTeam::GetSlotByType(type);
497 if(slot >= MAX_ARENA_SLOT)
498 return;
500 if(_player->GetArenaTeamId(slot))
502 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
503 return;
506 if(_player->GetArenaTeamIdInvited())
508 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
509 return;
512 else
514 if(_player->GetGuildId())
516 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
517 return;
519 if(_player->GetGuildIdInvited())
521 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
522 return;
526 if(++signs > type) // client signs maximum
527 return;
529 //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
530 //not allow sign another player from already sign player account
531 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
533 if(result)
535 delete result;
536 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
537 data << petitionguid;
538 data << _player->GetGUID();
539 data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
541 // close at signer side
542 SendPacket(&data);
544 // update for owner if online
545 if(Player *owner = objmgr.GetPlayer(ownerguid))
546 owner->GetSession()->SendPacket(&data);
547 return;
550 CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
552 sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
554 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
555 data << petitionguid;
556 data << _player->GetGUID();
557 data << (uint32)PETITION_SIGN_OK;
559 // close at signer side
560 SendPacket(&data);
562 // update signs count on charter, required testing...
563 //Item *item = _player->GetItemByGuid(petitionguid));
564 //if(item)
565 // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
567 // update for owner if online
568 if(Player *owner = objmgr.GetPlayer(ownerguid))
569 owner->GetSession()->SendPacket(&data);
572 void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
574 CHECK_PACKET_SIZE(recv_data, 8);
576 sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok
577 //recv_data.hexlike();
579 uint64 petitionguid;
580 uint64 ownerguid;
581 recv_data >> petitionguid; // petition guid
582 sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
584 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
585 if(!result)
586 return;
588 Field *fields = result->Fetch();
589 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
590 delete result;
592 Player *owner = objmgr.GetPlayer(ownerguid);
593 if(owner) // petition owner online
595 WorldPacket data(MSG_PETITION_DECLINE, 8);
596 data << _player->GetGUID();
597 owner->GetSession()->SendPacket(&data);
601 void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
603 CHECK_PACKET_SIZE(recv_data, 4+8+8);
605 sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok
606 //recv_data.hexlike();
608 uint8 signs = 0;
609 uint64 petitionguid, plguid;
610 uint32 type, junk;
611 Player *player;
612 recv_data >> junk; // this is not petition type!
613 recv_data >> petitionguid; // petition guid
614 recv_data >> plguid; // player guid
616 player = ObjectAccessor::FindPlayer(plguid);
617 if (!player)
618 return;
620 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
621 if (!result)
622 return;
624 Field *fields = result->Fetch();
625 type = fields[0].GetUInt32();
626 delete result;
628 sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
630 if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
632 if(type != 9)
633 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
634 else
635 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
636 return;
639 if(type != 9)
641 if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
643 // player is too low level to join an arena team
644 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
645 return;
648 uint8 slot = ArenaTeam::GetSlotByType(type);
649 if(slot >= MAX_ARENA_SLOT)
650 return;
652 if(player->GetArenaTeamId(slot))
654 // player is already in an arena team
655 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
656 return;
659 if(player->GetArenaTeamIdInvited())
661 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
662 return;
665 else
667 if(player->GetGuildId())
669 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
670 return;
673 if(player->GetGuildIdInvited())
675 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
676 return;
680 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
681 // result==NULL also correct charter without signs
682 if(result)
683 signs = result->GetRowCount();
685 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
686 data << petitionguid; // petition guid
687 data << _player->GetGUID(); // owner guid
688 data << GUID_LOPART(petitionguid); // guild guid (in mangos always same as GUID_LOPART(petition guid)
689 data << signs; // sign's count
691 for(uint8 i = 1; i <= signs; ++i)
693 Field *fields2 = result->Fetch();
694 plguid = fields2[0].GetUInt64();
696 data << plguid; // Player GUID
697 data << (uint32)0; // there 0 ...
699 result->NextRow();
702 delete result;
703 player->GetSession()->SendPacket(&data);
706 void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
708 CHECK_PACKET_SIZE(recv_data, 8);
710 sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
711 //recv_data.hexlike();
713 WorldPacket data;
714 uint64 petitionguid;
716 uint32 ownerguidlo;
717 uint32 type;
718 std::string name;
720 recv_data >> petitionguid;
722 sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
724 // data
725 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
726 if(result)
728 Field *fields = result->Fetch();
729 ownerguidlo = fields[0].GetUInt32();
730 name = fields[1].GetCppString();
731 type = fields[2].GetUInt32();
732 delete result;
734 else
736 sLog.outError("petition table has broken data!");
737 return;
740 if(type == 9)
742 if(_player->GetGuildId())
744 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
745 data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
746 _player->GetSession()->SendPacket(&data);
747 return;
750 else
752 uint8 slot = ArenaTeam::GetSlotByType(type);
753 if(slot >= MAX_ARENA_SLOT)
754 return;
756 if(_player->GetArenaTeamId(slot))
758 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
759 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
760 //_player->GetSession()->SendPacket(&data);
761 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
762 return;
766 if(_player->GetGUIDLow() != ownerguidlo)
767 return;
769 // signs
770 uint8 signs;
771 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
772 if(result)
773 signs = result->GetRowCount();
774 else
775 signs = 0;
777 uint32 count;
778 //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
779 if(type == 9)
780 count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
781 else
782 count = type-1;
783 if(signs < count)
785 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
786 data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
787 SendPacket(&data);
788 delete result;
789 return;
792 if(type == 9)
794 if(objmgr.GetGuildByName(name))
796 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
797 delete result;
798 return;
801 else
803 if(objmgr.GetArenaTeamByName(name))
805 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
806 delete result;
807 return;
811 // and at last charter item check
812 Item *item = _player->GetItemByGuid(petitionguid);
813 if(!item)
815 delete result;
816 return;
819 // OK!
821 // delete charter item
822 _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);
824 if(type == 9) // create guild
826 Guild* guild = new Guild;
827 if(!guild->create(_player, name))
829 delete guild;
830 delete result;
831 return;
834 // register guild and add guildmaster
835 objmgr.AddGuild(guild);
837 // add members
838 for(uint8 i = 0; i < signs; ++i)
840 Field* fields = result->Fetch();
841 guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
842 result->NextRow();
845 else // or arena team
847 ArenaTeam* at = new ArenaTeam;
848 if(!at->Create(_player->GetGUID(), type, name))
850 sLog.outError("PetitionsHandler: arena team create failed.");
851 delete at;
852 delete result;
853 return;
856 CHECK_PACKET_SIZE(recv_data, 8+5*4);
857 uint32 icon, iconcolor, border, bordercolor, backgroud;
858 recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
860 at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
862 // register team and add captain
863 objmgr.AddArenaTeam(at);
864 sLog.outDebug("PetitonsHandler: arena team added to objmrg");
866 // add members
867 for(uint8 i = 0; i < signs; ++i)
869 Field* fields = result->Fetch();
870 uint64 memberGUID = fields[0].GetUInt64();
871 sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
872 at->AddMember(memberGUID);
873 result->NextRow();
877 delete result;
879 CharacterDatabase.BeginTransaction();
880 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
881 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
882 CharacterDatabase.CommitTransaction();
884 // created
885 sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
887 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
888 data << (uint32)PETITION_TURN_OK;
889 SendPacket(&data);
892 void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
894 CHECK_PACKET_SIZE(recv_data, 8);
896 sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok
897 //recv_data.hexlike();
899 uint64 guid;
900 recv_data >> guid;
902 SendPetitionShowList(guid);
905 void WorldSession::SendPetitionShowList(uint64 guid)
907 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER);
908 if (!pCreature)
910 sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
911 return;
914 // remove fake death
915 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
916 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
918 uint8 count = 0;
919 if(pCreature->isTabardDesigner())
920 count = 1;
921 else
922 count = 3;
924 WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
925 data << guid; // npc guid
926 data << count; // count
927 if(count == 1)
929 data << uint32(1); // index
930 data << uint32(GUILD_CHARTER); // charter entry
931 data << uint32(16161); // charter display id
932 data << uint32(GUILD_CHARTER_COST); // charter cost
933 data << uint32(0); // unknown
934 data << uint32(9); // required signs?
936 else
938 // 2v2
939 data << uint32(1); // index
940 data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
941 data << uint32(16161); // charter display id
942 data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
943 data << uint32(2); // unknown
944 data << uint32(2); // required signs?
945 // 3v3
946 data << uint32(2); // index
947 data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
948 data << uint32(16161); // charter display id
949 data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
950 data << uint32(3); // unknown
951 data << uint32(3); // required signs?
952 // 5v5
953 data << uint32(3); // index
954 data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
955 data << uint32(16161); // charter display id
956 data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
957 data << uint32(5); // unknown
958 data << uint32(5); // required signs?
960 //for(uint8 i = 0; i < count; ++i)
962 // data << uint32(i); // index
963 // data << uint32(GUILD_CHARTER); // charter entry
964 // data << uint32(16161); // charter display id
965 // data << uint32(GUILD_CHARTER_COST+i); // charter cost
966 // data << uint32(0); // unknown
967 // data << uint32(9); // required signs?
969 SendPacket(&data);
970 sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");