[9033] Fixed percent mana regneration from spell 53228 and ranks buff.
[getmangos.git] / src / game / PetitionsHandler.cpp
blob41fe2b12cb7523e9745e6c5d4877317ec1a5cfc2
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 "ObjectDefines.h"
26 #include "Log.h"
27 #include "Opcodes.h"
28 #include "Guild.h"
29 #include "ArenaTeam.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 sLog.outDebug("Received opcode CMSG_PETITION_BUY");
52 recv_data.hexlike();
54 uint64 guidNPC;
55 uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client
56 std::string name;
58 recv_data >> guidNPC; // NPC GUID
59 recv_data.read_skip<uint32>(); // 0
60 recv_data.read_skip<uint64>(); // 0
61 recv_data >> name; // name
62 recv_data.read_skip<std::string>(); // some string
63 recv_data.read_skip<uint32>(); // 0
64 recv_data.read_skip<uint32>(); // 0
65 recv_data.read_skip<uint32>(); // 0
66 recv_data.read_skip<uint32>(); // 0
67 recv_data.read_skip<uint32>(); // 0
68 recv_data.read_skip<uint32>(); // 0
69 recv_data.read_skip<uint32>(); // 0
70 recv_data.read_skip<uint16>(); // 0
71 recv_data.read_skip<uint32>(); // 0
72 recv_data.read_skip<uint32>(); // 0
73 recv_data.read_skip<uint32>(); // 0
75 for (int i = 0; i < 10; ++i)
76 recv_data.read_skip<std::string>();
78 recv_data >> clientIndex; // index
79 recv_data.read_skip<uint32>(); // 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 = GetPlayer()->GetNPCIfCanInteractWith(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(clientIndex) // arenaSlot+1 as received from client (1 from 3 case)
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 arena petition: %u", clientIndex);
137 return;
140 if(_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client
142 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
143 return;
147 if(type == 9)
149 if(sObjectMgr.GetGuildByName(name))
151 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
152 return;
154 if(sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
156 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
157 return;
160 else
162 if(sObjectMgr.GetArenaTeamByName(name))
164 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
165 return;
167 if(sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
169 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
170 return;
174 ItemPrototype const *pProto = ObjectMgr::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)
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 // ok
240 sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
241 //recv_data.hexlike();
243 uint8 signs = 0;
244 uint64 petitionguid;
245 recv_data >> petitionguid; // petition guid
247 // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
248 uint32 petitionguid_low = GUID_LOPART(petitionguid);
250 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
251 if(!result)
253 sLog.outError("any petition on server...");
254 return;
256 Field *fields = result->Fetch();
257 uint32 type = fields[0].GetUInt32();
258 delete result;
260 // if guild petition and has guild => error, return;
261 if(type==9 && _player->GetGuildId())
262 return;
264 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);
266 // result==NULL also correct in case no sign yet
267 if(result)
268 signs = result->GetRowCount();
270 sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);
272 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
273 data << petitionguid; // petition guid
274 data << _player->GetGUID(); // owner guid
275 data << petitionguid_low; // guild guid (in mangos always same as GUID_LOPART(petitionguid)
276 data << signs; // sign's count
278 for(uint8 i = 1; i <= signs; ++i)
280 Field *fields2 = result->Fetch();
281 uint64 plguid = fields2[0].GetUInt64();
283 data << plguid; // Player GUID
284 data << (uint32)0; // there 0 ...
286 result->NextRow();
288 delete result;
289 SendPacket(&data);
292 void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data)
294 sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok
295 //recv_data.hexlike();
297 uint32 guildguid;
298 uint64 petitionguid;
299 recv_data >> guildguid; // in mangos always same as GUID_LOPART(petitionguid)
300 recv_data >> petitionguid; // petition guid
301 sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid);
303 SendPetitionQueryOpcode(petitionguid);
306 void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
308 uint64 ownerguid = 0;
309 uint32 type;
310 std::string name = "NO_NAME_FOR_GUID";
311 uint8 signs = 0;
313 QueryResult *result = CharacterDatabase.PQuery(
314 "SELECT ownerguid, name, "
315 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
316 " type "
317 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
319 if(result)
321 Field* fields = result->Fetch();
322 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
323 name = fields[1].GetCppString();
324 signs = fields[2].GetUInt8();
325 type = fields[3].GetUInt32();
326 delete result;
328 else
330 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
331 return;
334 WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*12+2+10));
335 data << uint32(GUID_LOPART(petitionguid)); // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
336 data << uint64(ownerguid); // charter owner guid
337 data << name; // name (guild/arena team)
338 data << uint8(0); // some string
339 if(type == 9)
341 data << uint32(9);
342 data << uint32(9);
343 data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition
345 else
347 data << uint32(type-1);
348 data << uint32(type-1);
349 data << uint32(type); // bypass client - side limitation, a different value is needed here for each petition
351 data << uint32(0); // 5
352 data << uint32(0); // 6
353 data << uint32(0); // 7
354 data << uint32(0); // 8
355 data << uint16(0); // 9 2 bytes field
356 data << uint32(0); // 10
357 data << uint32(0); // 11
358 data << uint32(0); // 13 count of next strings?
360 for(int i = 0; i < 10; ++i)
361 data << uint8(0); // some string
363 data << uint32(0); // 14
365 if(type == 9)
366 data << uint32(0); // 15 0 - guild, 1 - arena team
367 else
368 data << uint32(1);
370 SendPacket(&data);
373 void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
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(sObjectMgr.GetGuildByName(newname))
407 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
408 return;
410 if(sObjectMgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
412 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
413 return;
416 else
418 if(sObjectMgr.GetArenaTeamByName(newname))
420 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
421 return;
423 if(sObjectMgr.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 sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok
445 //recv_data.hexlike();
447 Field *fields;
448 uint64 petitionguid;
449 uint8 unk;
450 recv_data >> petitionguid; // petition guid
451 recv_data >> unk;
453 QueryResult *result = CharacterDatabase.PQuery(
454 "SELECT ownerguid, "
455 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
456 " type "
457 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
459 if(!result)
461 sLog.outError("any petition on server...");
462 return;
465 fields = result->Fetch();
466 uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
467 uint8 signs = fields[1].GetUInt8();
468 uint32 type = fields[2].GetUInt32();
470 delete result;
472 uint32 plguidlo = _player->GetGUIDLow();
473 if(GUID_LOPART(ownerguid) == plguidlo)
474 return;
476 // not let enemies sign guild charter
477 if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(ownerguid))
479 if(type != 9)
480 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
481 else
482 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
483 return;
486 if(type != 9)
488 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
490 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
491 return;
494 uint8 slot = ArenaTeam::GetSlotByType(type);
495 if(slot >= MAX_ARENA_SLOT)
496 return;
498 if(_player->GetArenaTeamId(slot))
500 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
501 return;
504 if(_player->GetArenaTeamIdInvited())
506 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
507 return;
510 else
512 if(_player->GetGuildId())
514 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
515 return;
517 if(_player->GetGuildIdInvited())
519 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
520 return;
524 if(++signs > type) // client signs maximum
525 return;
527 //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
528 //not allow sign another player from already sign player account
529 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
531 if(result)
533 delete result;
534 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
535 data << petitionguid;
536 data << _player->GetGUID();
537 data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
539 // close at signer side
540 SendPacket(&data);
542 // update for owner if online
543 if(Player *owner = sObjectMgr.GetPlayer(ownerguid))
544 owner->GetSession()->SendPacket(&data);
545 return;
548 CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
550 sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
552 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
553 data << petitionguid;
554 data << _player->GetGUID();
555 data << (uint32)PETITION_SIGN_OK;
557 // close at signer side
558 SendPacket(&data);
560 // update signs count on charter, required testing...
561 //Item *item = _player->GetItemByGuid(petitionguid));
562 //if(item)
563 // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
565 // update for owner if online
566 if(Player *owner = sObjectMgr.GetPlayer(ownerguid))
567 owner->GetSession()->SendPacket(&data);
570 void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
572 sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok
573 //recv_data.hexlike();
575 uint64 petitionguid;
576 uint64 ownerguid;
577 recv_data >> petitionguid; // petition guid
578 sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
580 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
581 if(!result)
582 return;
584 Field *fields = result->Fetch();
585 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
586 delete result;
588 Player *owner = sObjectMgr.GetPlayer(ownerguid);
589 if(owner) // petition owner online
591 WorldPacket data(MSG_PETITION_DECLINE, 8);
592 data << _player->GetGUID();
593 owner->GetSession()->SendPacket(&data);
597 void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
599 sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok
600 //recv_data.hexlike();
602 uint8 signs = 0;
603 uint64 petitionguid, plguid;
604 uint32 type, junk;
605 Player *player;
606 recv_data >> junk; // this is not petition type!
607 recv_data >> petitionguid; // petition guid
608 recv_data >> plguid; // player guid
610 player = ObjectAccessor::FindPlayer(plguid);
611 if (!player)
612 return;
614 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
615 if (!result)
616 return;
618 Field *fields = result->Fetch();
619 type = fields[0].GetUInt32();
620 delete result;
622 sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
624 if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
626 if(type != 9)
627 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
628 else
629 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
630 return;
633 if(type != 9)
635 if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
637 // player is too low level to join an arena team
638 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
639 return;
642 uint8 slot = ArenaTeam::GetSlotByType(type);
643 if(slot >= MAX_ARENA_SLOT)
644 return;
646 if(player->GetArenaTeamId(slot))
648 // player is already in an arena team
649 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
650 return;
653 if(player->GetArenaTeamIdInvited())
655 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
656 return;
659 else
661 if(player->GetGuildId())
663 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
664 return;
667 if(player->GetGuildIdInvited())
669 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
670 return;
674 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
675 // result==NULL also correct charter without signs
676 if(result)
677 signs = result->GetRowCount();
679 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
680 data << petitionguid; // petition guid
681 data << _player->GetGUID(); // owner guid
682 data << GUID_LOPART(petitionguid); // guild guid (in mangos always same as GUID_LOPART(petition guid)
683 data << signs; // sign's count
685 for(uint8 i = 1; i <= signs; ++i)
687 Field *fields2 = result->Fetch();
688 plguid = fields2[0].GetUInt64();
690 data << plguid; // Player GUID
691 data << (uint32)0; // there 0 ...
693 result->NextRow();
696 delete result;
697 player->GetSession()->SendPacket(&data);
700 void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
702 sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
703 //recv_data.hexlike();
705 WorldPacket data;
706 uint64 petitionguid;
708 uint32 ownerguidlo;
709 uint32 type;
710 std::string name;
712 recv_data >> petitionguid;
714 sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
716 // data
717 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
718 if(result)
720 Field *fields = result->Fetch();
721 ownerguidlo = fields[0].GetUInt32();
722 name = fields[1].GetCppString();
723 type = fields[2].GetUInt32();
724 delete result;
726 else
728 sLog.outError("petition table has broken data!");
729 return;
732 if(type == 9)
734 if(_player->GetGuildId())
736 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
737 data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
738 _player->GetSession()->SendPacket(&data);
739 return;
742 else
744 uint8 slot = ArenaTeam::GetSlotByType(type);
745 if(slot >= MAX_ARENA_SLOT)
746 return;
748 if(_player->GetArenaTeamId(slot))
750 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
751 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
752 //_player->GetSession()->SendPacket(&data);
753 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
754 return;
758 if(_player->GetGUIDLow() != ownerguidlo)
759 return;
761 // signs
762 uint8 signs;
763 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
764 if(result)
765 signs = result->GetRowCount();
766 else
767 signs = 0;
769 uint32 count;
770 //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
771 if(type == 9)
772 count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
773 else
774 count = type-1;
775 if(signs < count)
777 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
778 data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
779 SendPacket(&data);
780 delete result;
781 return;
784 if(type == 9)
786 if(sObjectMgr.GetGuildByName(name))
788 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
789 delete result;
790 return;
793 else
795 if(sObjectMgr.GetArenaTeamByName(name))
797 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
798 delete result;
799 return;
803 // and at last charter item check
804 Item *item = _player->GetItemByGuid(petitionguid);
805 if(!item)
807 delete result;
808 return;
811 // OK!
813 // delete charter item
814 _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);
816 if(type == 9) // create guild
818 Guild* guild = new Guild;
819 if(!guild->Create(_player, name))
821 delete guild;
822 delete result;
823 return;
826 // register guild and add guildmaster
827 sObjectMgr.AddGuild(guild);
829 // add members
830 for(uint8 i = 0; i < signs; ++i)
832 Field* fields = result->Fetch();
833 guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
834 result->NextRow();
837 else // or arena team
839 ArenaTeam* at = new ArenaTeam;
840 if(!at->Create(_player->GetGUID(), type, name))
842 sLog.outError("PetitionsHandler: arena team create failed.");
843 delete at;
844 delete result;
845 return;
848 uint32 icon, iconcolor, border, bordercolor, backgroud;
849 recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
851 at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
853 // register team and add captain
854 sObjectMgr.AddArenaTeam(at);
855 sLog.outDebug("PetitonsHandler: arena team added to objmrg");
857 // add members
858 for(uint8 i = 0; i < signs; ++i)
860 Field* fields = result->Fetch();
861 uint64 memberGUID = fields[0].GetUInt64();
862 sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
863 at->AddMember(memberGUID);
864 result->NextRow();
868 delete result;
870 CharacterDatabase.BeginTransaction();
871 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
872 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
873 CharacterDatabase.CommitTransaction();
875 // created
876 sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
878 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
879 data << (uint32)PETITION_TURN_OK;
880 SendPacket(&data);
883 void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
885 sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok
886 //recv_data.hexlike();
888 uint64 guid;
889 recv_data >> guid;
891 SendPetitionShowList(guid);
894 void WorldSession::SendPetitionShowList(uint64 guid)
896 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER);
897 if (!pCreature)
899 sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
900 return;
903 // remove fake death
904 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
905 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
907 uint8 count = 0;
908 if(pCreature->isTabardDesigner())
909 count = 1;
910 else
911 count = 3;
913 WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
914 data << guid; // npc guid
915 data << count; // count
916 if(count == 1)
918 data << uint32(1); // index
919 data << uint32(GUILD_CHARTER); // charter entry
920 data << uint32(16161); // charter display id
921 data << uint32(GUILD_CHARTER_COST); // charter cost
922 data << uint32(0); // unknown
923 data << uint32(9); // required signs?
925 else
927 // 2v2
928 data << uint32(1); // index
929 data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
930 data << uint32(16161); // charter display id
931 data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
932 data << uint32(2); // unknown
933 data << uint32(2); // required signs?
934 // 3v3
935 data << uint32(2); // index
936 data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
937 data << uint32(16161); // charter display id
938 data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
939 data << uint32(3); // unknown
940 data << uint32(3); // required signs?
941 // 5v5
942 data << uint32(3); // index
943 data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
944 data << uint32(16161); // charter display id
945 data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
946 data << uint32(5); // unknown
947 data << uint32(5); // required signs?
949 //for(uint8 i = 0; i < count; ++i)
951 // data << uint32(i); // index
952 // data << uint32(GUILD_CHARTER); // charter entry
953 // data << uint32(16161); // charter display id
954 // data << uint32(GUILD_CHARTER_COST+i); // charter cost
955 // data << uint32(0); // unknown
956 // data << uint32(9); // required signs?
958 SendPacket(&data);
959 sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");