[8449] Deprecate healing/damage item mods and merge internal data in to spell power.
[getmangos.git] / src / game / PetitionsHandler.cpp
bloba4a1201cdca1585f9fbbdf1e6cf1b63d98a40dce
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 sLog.outDebug("Received opcode CMSG_PETITION_BUY");
51 //recv_data.hexlike();
53 uint64 guidNPC;
54 uint64 unk1, unk3, unk4, unk5, unk6, unk7;
55 uint32 unk2;
56 std::string name;
57 uint16 unk8;
58 uint8 unk9;
59 uint32 unk10; // selected index
60 uint32 unk11;
61 recv_data >> guidNPC; // NPC GUID
62 recv_data >> unk1; // 0
63 recv_data >> unk2; // 0
64 recv_data >> name; // name
66 recv_data >> unk3; // 0
67 recv_data >> unk4; // 0
68 recv_data >> unk5; // 0
69 recv_data >> unk6; // 0
70 recv_data >> unk7; // 0
71 recv_data >> unk8; // 0
72 recv_data >> unk9; // 0
73 recv_data >> unk10; // index
74 recv_data >> unk11; // 0
75 sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
77 // prevent cheating
78 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER);
79 if (!pCreature)
81 sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
82 return;
85 // remove fake death
86 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
87 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
89 uint32 charterid = 0;
90 uint32 cost = 0;
91 uint32 type = 0;
92 if(pCreature->isTabardDesigner())
94 // if tabard designer, then trying to buy a guild charter.
95 // do not let if already in guild.
96 if(_player->GetGuildId())
97 return;
99 charterid = GUILD_CHARTER;
100 cost = GUILD_CHARTER_COST;
101 type = 9;
103 else
105 // TODO: find correct opcode
106 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
108 SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
109 return;
112 switch(unk10)
114 case 1:
115 charterid = ARENA_TEAM_CHARTER_2v2;
116 cost = ARENA_TEAM_CHARTER_2v2_COST;
117 type = 2; // 2v2
118 break;
119 case 2:
120 charterid = ARENA_TEAM_CHARTER_3v3;
121 cost = ARENA_TEAM_CHARTER_3v3_COST;
122 type = 3; // 3v3
123 break;
124 case 3:
125 charterid = ARENA_TEAM_CHARTER_5v5;
126 cost = ARENA_TEAM_CHARTER_5v5_COST;
127 type = 5; // 5v5
128 break;
129 default:
130 sLog.outDebug("unknown selection at buy petition: %u", unk10);
131 return;
134 if(_player->GetArenaTeamId(unk10-1))
136 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
137 return;
141 if(type == 9)
143 if(objmgr.GetGuildByName(name))
145 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
146 return;
148 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
150 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
151 return;
154 else
156 if(objmgr.GetArenaTeamByName(name))
158 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
159 return;
161 if(objmgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
163 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
164 return;
168 ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid);
169 if(!pProto)
171 _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
172 return;
175 if(_player->GetMoney() < cost)
176 { //player hasn't got enough money
177 _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
178 return;
181 ItemPosCountVec dest;
182 uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount );
183 if(msg != EQUIP_ERR_OK)
185 _player->SendBuyError(msg, pCreature, charterid, 0);
186 return;
189 _player->ModifyMoney(-(int32)cost);
190 Item *charter = _player->StoreNewItem(dest, charterid, true);
191 if(!charter)
192 return;
194 charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
195 // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
196 // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
197 charter->SetState(ITEM_CHANGED, _player);
198 _player->SendNewItem(charter, 1, true, false);
200 // a petition is invalid, if both the owner and the type matches
201 // we checked above, if this player is in an arenateam, so this must be
202 // datacorruption
203 QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u' AND type = '%u'", _player->GetGUIDLow(), type);
205 std::ostringstream ssInvalidPetitionGUIDs;
207 if (result)
212 Field *fields = result->Fetch();
213 ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";
214 } while (result->NextRow());
216 delete result;
219 // delete petitions with the same guid as this one
220 ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";
222 sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
223 CharacterDatabase.escape_string(name);
224 CharacterDatabase.BeginTransaction();
225 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
226 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
227 CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')",
228 _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);
229 CharacterDatabase.CommitTransaction();
232 void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
234 // ok
235 sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
236 //recv_data.hexlike();
238 uint8 signs = 0;
239 uint64 petitionguid;
240 recv_data >> petitionguid; // petition guid
242 // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
243 uint32 petitionguid_low = GUID_LOPART(petitionguid);
245 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
246 if(!result)
248 sLog.outError("any petition on server...");
249 return;
251 Field *fields = result->Fetch();
252 uint32 type = fields[0].GetUInt32();
253 delete result;
255 // if guild petition and has guild => error, return;
256 if(type==9 && _player->GetGuildId())
257 return;
259 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);
261 // result==NULL also correct in case no sign yet
262 if(result)
263 signs = result->GetRowCount();
265 sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);
267 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
268 data << petitionguid; // petition guid
269 data << _player->GetGUID(); // owner guid
270 data << petitionguid_low; // guild guid (in mangos always same as GUID_LOPART(petitionguid)
271 data << signs; // sign's count
273 for(uint8 i = 1; i <= signs; ++i)
275 Field *fields2 = result->Fetch();
276 uint64 plguid = fields2[0].GetUInt64();
278 data << plguid; // Player GUID
279 data << (uint32)0; // there 0 ...
281 result->NextRow();
283 delete result;
284 SendPacket(&data);
287 void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data)
289 sLog.outDebug("Received opcode CMSG_PETITION_QUERY"); // ok
290 //recv_data.hexlike();
292 uint32 guildguid;
293 uint64 petitionguid;
294 recv_data >> guildguid; // in mangos always same as GUID_LOPART(petitionguid)
295 recv_data >> petitionguid; // petition guid
296 sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid);
298 SendPetitionQueryOpcode(petitionguid);
301 void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
303 uint64 ownerguid = 0;
304 uint32 type;
305 std::string name = "NO_NAME_FOR_GUID";
306 uint8 signs = 0;
308 QueryResult *result = CharacterDatabase.PQuery(
309 "SELECT ownerguid, name, "
310 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
311 " type "
312 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
314 if(result)
316 Field* fields = result->Fetch();
317 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
318 name = fields[1].GetCppString();
319 signs = fields[2].GetUInt8();
320 type = fields[3].GetUInt32();
321 delete result;
323 else
325 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
326 return;
329 WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
330 data << GUID_LOPART(petitionguid); // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
331 data << ownerguid; // charter owner guid
332 data << name; // name (guild/arena team)
333 data << uint8(0); // 1
334 if(type == 9)
336 data << uint32(9);
337 data << uint32(9);
338 data << uint32(0); // bypass client - side limitation, a different value is needed here for each petition
340 else
342 data << type-1;
343 data << type-1;
344 data << type; // bypass client - side limitation, a different value is needed here for each petition
346 data << uint32(0); // 5
347 data << uint32(0); // 6
348 data << uint32(0); // 7
349 data << uint32(0); // 8
350 data << uint16(0); // 9 2 bytes field
351 data << uint32(0); // 10
352 data << uint32(0); // 11
353 data << uint32(0); // 13 count of next strings?
354 data << uint32(0); // 14
355 if(type == 9)
356 data << uint32(0); // 15 0 - guild, 1 - arena team
357 else
358 data << uint32(1);
359 SendPacket(&data);
362 void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
364 sLog.outDebug("Received opcode MSG_PETITION_RENAME"); // ok
365 //recv_data.hexlike();
367 uint64 petitionguid;
368 uint32 type;
369 std::string newname;
371 recv_data >> petitionguid; // guid
372 recv_data >> newname; // new name
374 Item *item = _player->GetItemByGuid(petitionguid);
375 if(!item)
376 return;
378 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
380 if(result)
382 Field* fields = result->Fetch();
383 type = fields[0].GetUInt32();
384 delete result;
386 else
388 sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
389 return;
392 if(type == 9)
394 if(objmgr.GetGuildByName(newname))
396 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
397 return;
399 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
401 SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
402 return;
405 else
407 if(objmgr.GetArenaTeamByName(newname))
409 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
410 return;
412 if(objmgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
414 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
415 return;
419 std::string db_newname = newname;
420 CharacterDatabase.escape_string(db_newname);
421 CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'",
422 db_newname.c_str(), GUID_LOPART(petitionguid));
424 sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str());
425 WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
426 data << petitionguid;
427 data << newname;
428 SendPacket(&data);
431 void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
433 sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok
434 //recv_data.hexlike();
436 Field *fields;
437 uint64 petitionguid;
438 uint8 unk;
439 recv_data >> petitionguid; // petition guid
440 recv_data >> unk;
442 QueryResult *result = CharacterDatabase.PQuery(
443 "SELECT ownerguid, "
444 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
445 " type "
446 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
448 if(!result)
450 sLog.outError("any petition on server...");
451 return;
454 fields = result->Fetch();
455 uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
456 uint8 signs = fields[1].GetUInt8();
457 uint32 type = fields[2].GetUInt32();
459 delete result;
461 uint32 plguidlo = _player->GetGUIDLow();
462 if(GUID_LOPART(ownerguid) == plguidlo)
463 return;
465 // not let enemies sign guild charter
466 if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
468 if(type != 9)
469 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
470 else
471 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
472 return;
475 if(type != 9)
477 if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
479 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_PLAYER_TO_LOW);
480 return;
483 uint8 slot = ArenaTeam::GetSlotByType(type);
484 if(slot >= MAX_ARENA_SLOT)
485 return;
487 if(_player->GetArenaTeamId(slot))
489 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
490 return;
493 if(_player->GetArenaTeamIdInvited())
495 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
496 return;
499 else
501 if(_player->GetGuildId())
503 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
504 return;
506 if(_player->GetGuildIdInvited())
508 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
509 return;
513 if(++signs > type) // client signs maximum
514 return;
516 //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
517 //not allow sign another player from already sign player account
518 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
520 if(result)
522 delete result;
523 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
524 data << petitionguid;
525 data << _player->GetGUID();
526 data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
528 // close at signer side
529 SendPacket(&data);
531 // update for owner if online
532 if(Player *owner = objmgr.GetPlayer(ownerguid))
533 owner->GetSession()->SendPacket(&data);
534 return;
537 CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
539 sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
541 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
542 data << petitionguid;
543 data << _player->GetGUID();
544 data << (uint32)PETITION_SIGN_OK;
546 // close at signer side
547 SendPacket(&data);
549 // update signs count on charter, required testing...
550 //Item *item = _player->GetItemByGuid(petitionguid));
551 //if(item)
552 // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
554 // update for owner if online
555 if(Player *owner = objmgr.GetPlayer(ownerguid))
556 owner->GetSession()->SendPacket(&data);
559 void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
561 sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok
562 //recv_data.hexlike();
564 uint64 petitionguid;
565 uint64 ownerguid;
566 recv_data >> petitionguid; // petition guid
567 sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
569 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
570 if(!result)
571 return;
573 Field *fields = result->Fetch();
574 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
575 delete result;
577 Player *owner = objmgr.GetPlayer(ownerguid);
578 if(owner) // petition owner online
580 WorldPacket data(MSG_PETITION_DECLINE, 8);
581 data << _player->GetGUID();
582 owner->GetSession()->SendPacket(&data);
586 void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
588 sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok
589 //recv_data.hexlike();
591 uint8 signs = 0;
592 uint64 petitionguid, plguid;
593 uint32 type, junk;
594 Player *player;
595 recv_data >> junk; // this is not petition type!
596 recv_data >> petitionguid; // petition guid
597 recv_data >> plguid; // player guid
599 player = ObjectAccessor::FindPlayer(plguid);
600 if (!player)
601 return;
603 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
604 if (!result)
605 return;
607 Field *fields = result->Fetch();
608 type = fields[0].GetUInt32();
609 delete result;
611 sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
613 if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
615 if(type != 9)
616 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
617 else
618 SendGuildCommandResult(GUILD_CREATE_S, "", GUILD_NOT_ALLIED);
619 return;
622 if(type != 9)
624 if(player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
626 // player is too low level to join an arena team
627 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_PLAYER_TO_LOW);
628 return;
631 uint8 slot = ArenaTeam::GetSlotByType(type);
632 if(slot >= MAX_ARENA_SLOT)
633 return;
635 if(player->GetArenaTeamId(slot))
637 // player is already in an arena team
638 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
639 return;
642 if(player->GetArenaTeamIdInvited())
644 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
645 return;
648 else
650 if(player->GetGuildId())
652 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_IN_GUILD);
653 return;
656 if(player->GetGuildIdInvited())
658 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ALREADY_INVITED_TO_GUILD);
659 return;
663 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
664 // result==NULL also correct charter without signs
665 if(result)
666 signs = result->GetRowCount();
668 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
669 data << petitionguid; // petition guid
670 data << _player->GetGUID(); // owner guid
671 data << GUID_LOPART(petitionguid); // guild guid (in mangos always same as GUID_LOPART(petition guid)
672 data << signs; // sign's count
674 for(uint8 i = 1; i <= signs; ++i)
676 Field *fields2 = result->Fetch();
677 plguid = fields2[0].GetUInt64();
679 data << plguid; // Player GUID
680 data << (uint32)0; // there 0 ...
682 result->NextRow();
685 delete result;
686 player->GetSession()->SendPacket(&data);
689 void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
691 sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
692 //recv_data.hexlike();
694 WorldPacket data;
695 uint64 petitionguid;
697 uint32 ownerguidlo;
698 uint32 type;
699 std::string name;
701 recv_data >> petitionguid;
703 sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
705 // data
706 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
707 if(result)
709 Field *fields = result->Fetch();
710 ownerguidlo = fields[0].GetUInt32();
711 name = fields[1].GetCppString();
712 type = fields[2].GetUInt32();
713 delete result;
715 else
717 sLog.outError("petition table has broken data!");
718 return;
721 if(type == 9)
723 if(_player->GetGuildId())
725 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
726 data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
727 _player->GetSession()->SendPacket(&data);
728 return;
731 else
733 uint8 slot = ArenaTeam::GetSlotByType(type);
734 if(slot >= MAX_ARENA_SLOT)
735 return;
737 if(_player->GetArenaTeamId(slot))
739 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
740 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
741 //_player->GetSession()->SendPacket(&data);
742 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
743 return;
747 if(_player->GetGUIDLow() != ownerguidlo)
748 return;
750 // signs
751 uint8 signs;
752 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
753 if(result)
754 signs = result->GetRowCount();
755 else
756 signs = 0;
758 uint32 count;
759 //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
760 if(type == 9)
761 count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
762 else
763 count = type-1;
764 if(signs < count)
766 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
767 data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
768 SendPacket(&data);
769 delete result;
770 return;
773 if(type == 9)
775 if(objmgr.GetGuildByName(name))
777 SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
778 delete result;
779 return;
782 else
784 if(objmgr.GetArenaTeamByName(name))
786 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
787 delete result;
788 return;
792 // and at last charter item check
793 Item *item = _player->GetItemByGuid(petitionguid);
794 if(!item)
796 delete result;
797 return;
800 // OK!
802 // delete charter item
803 _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);
805 if(type == 9) // create guild
807 Guild* guild = new Guild;
808 if(!guild->Create(_player, name))
810 delete guild;
811 delete result;
812 return;
815 // register guild and add guildmaster
816 objmgr.AddGuild(guild);
818 // add members
819 for(uint8 i = 0; i < signs; ++i)
821 Field* fields = result->Fetch();
822 guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
823 result->NextRow();
826 else // or arena team
828 ArenaTeam* at = new ArenaTeam;
829 if(!at->Create(_player->GetGUID(), type, name))
831 sLog.outError("PetitionsHandler: arena team create failed.");
832 delete at;
833 delete result;
834 return;
837 uint32 icon, iconcolor, border, bordercolor, backgroud;
838 recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
840 at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
842 // register team and add captain
843 objmgr.AddArenaTeam(at);
844 sLog.outDebug("PetitonsHandler: arena team added to objmrg");
846 // add members
847 for(uint8 i = 0; i < signs; ++i)
849 Field* fields = result->Fetch();
850 uint64 memberGUID = fields[0].GetUInt64();
851 sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
852 at->AddMember(memberGUID);
853 result->NextRow();
857 delete result;
859 CharacterDatabase.BeginTransaction();
860 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
861 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
862 CharacterDatabase.CommitTransaction();
864 // created
865 sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
867 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
868 data << (uint32)PETITION_TURN_OK;
869 SendPacket(&data);
872 void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
874 sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok
875 //recv_data.hexlike();
877 uint64 guid;
878 recv_data >> guid;
880 SendPetitionShowList(guid);
883 void WorldSession::SendPetitionShowList(uint64 guid)
885 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER);
886 if (!pCreature)
888 sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
889 return;
892 // remove fake death
893 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
894 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
896 uint8 count = 0;
897 if(pCreature->isTabardDesigner())
898 count = 1;
899 else
900 count = 3;
902 WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
903 data << guid; // npc guid
904 data << count; // count
905 if(count == 1)
907 data << uint32(1); // index
908 data << uint32(GUILD_CHARTER); // charter entry
909 data << uint32(16161); // charter display id
910 data << uint32(GUILD_CHARTER_COST); // charter cost
911 data << uint32(0); // unknown
912 data << uint32(9); // required signs?
914 else
916 // 2v2
917 data << uint32(1); // index
918 data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
919 data << uint32(16161); // charter display id
920 data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
921 data << uint32(2); // unknown
922 data << uint32(2); // required signs?
923 // 3v3
924 data << uint32(2); // index
925 data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
926 data << uint32(16161); // charter display id
927 data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
928 data << uint32(3); // unknown
929 data << uint32(3); // required signs?
930 // 5v5
931 data << uint32(3); // index
932 data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
933 data << uint32(16161); // charter display id
934 data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
935 data << uint32(5); // unknown
936 data << uint32(5); // required signs?
938 //for(uint8 i = 0; i < count; ++i)
940 // data << uint32(i); // index
941 // data << uint32(GUILD_CHARTER); // charter entry
942 // data << uint32(16161); // charter display id
943 // data << uint32(GUILD_CHARTER_COST+i); // charter cost
944 // data << uint32(0); // unknown
945 // data << uint32(9); // required signs?
947 SendPacket(&data);
948 sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");