[9581] Fixed apply damage reduction to melee/ranged damage.
[getmangos.git] / src / game / PetitionsHandler.cpp
blob3f637edac93bb4ed36595b50c64793a49109ae29
1 /*
2 * Copyright (C) 2005-2010 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 "ObjectGuid.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
48 #define CHARTER_DISPLAY_ID 16161
50 void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
52 sLog.outDebug("Received opcode CMSG_PETITION_BUY");
53 recv_data.hexlike();
55 uint64 guidNPC;
56 uint32 clientIndex; // 1 for guild and arenaslot+1 for arenas in client
57 std::string name;
59 recv_data >> guidNPC; // NPC GUID
60 recv_data.read_skip<uint32>(); // 0
61 recv_data.read_skip<uint64>(); // 0
62 recv_data >> name; // name
63 recv_data.read_skip<std::string>(); // some string
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<uint32>(); // 0
71 recv_data.read_skip<uint16>(); // 0
72 recv_data.read_skip<uint32>(); // 0
73 recv_data.read_skip<uint32>(); // 0
74 recv_data.read_skip<uint32>(); // 0
76 for (int i = 0; i < 10; ++i)
77 recv_data.read_skip<std::string>();
79 recv_data >> clientIndex; // index
80 recv_data.read_skip<uint32>(); // 0
82 sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
84 // prevent cheating
85 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guidNPC,UNIT_NPC_FLAG_PETITIONER);
86 if (!pCreature)
88 sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
89 return;
92 // remove fake death
93 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
94 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
96 uint32 charterid = 0;
97 uint32 cost = 0;
98 uint32 type = 0;
99 if(pCreature->isTabardDesigner())
101 // if tabard designer, then trying to buy a guild charter.
102 // do not let if already in guild.
103 if(_player->GetGuildId())
104 return;
106 charterid = GUILD_CHARTER;
107 cost = GUILD_CHARTER_COST;
108 type = 9;
110 else
112 // TODO: find correct opcode
113 if(_player->getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
115 SendNotification(LANG_ARENA_ONE_TOOLOW, sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL));
116 return;
119 switch(clientIndex) // arenaSlot+1 as received from client (1 from 3 case)
121 case 1:
122 charterid = ARENA_TEAM_CHARTER_2v2;
123 cost = ARENA_TEAM_CHARTER_2v2_COST;
124 type = 2; // 2v2
125 break;
126 case 2:
127 charterid = ARENA_TEAM_CHARTER_3v3;
128 cost = ARENA_TEAM_CHARTER_3v3_COST;
129 type = 3; // 3v3
130 break;
131 case 3:
132 charterid = ARENA_TEAM_CHARTER_5v5;
133 cost = ARENA_TEAM_CHARTER_5v5_COST;
134 type = 5; // 5v5
135 break;
136 default:
137 sLog.outDebug("unknown selection at buy arena petition: %u", clientIndex);
138 return;
141 if(_player->GetArenaTeamId(clientIndex - 1)) // arenaSlot+1 as received from client
143 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
144 return;
148 if(type == 9)
150 if(sObjectMgr.GetGuildByName(name))
152 SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S);
153 return;
155 if(sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
157 SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_INVALID);
158 return;
161 else
163 if(sObjectMgr.GetArenaTeamByName(name))
165 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
166 return;
168 if(sObjectMgr.IsReservedName(name) || !ObjectMgr::IsValidCharterName(name))
170 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
171 return;
175 ItemPrototype const *pProto = ObjectMgr::GetItemPrototype(charterid);
176 if(!pProto)
178 _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
179 return;
182 if(_player->GetMoney() < cost)
183 { //player hasn't got enough money
184 _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
185 return;
188 ItemPosCountVec dest;
189 uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount );
190 if(msg != EQUIP_ERR_OK)
192 _player->SendBuyError(msg, pCreature, charterid, 0);
193 return;
196 _player->ModifyMoney(-(int32)cost);
197 Item *charter = _player->StoreNewItem(dest, charterid, true);
198 if(!charter)
199 return;
201 charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1, charter->GetGUIDLow());
202 // ITEM_FIELD_ENCHANTMENT_1_1 is guild/arenateam id
203 // ITEM_FIELD_ENCHANTMENT_1_1+1 is current signatures count (showed on item)
204 charter->SetState(ITEM_CHANGED, _player);
205 _player->SendNewItem(charter, 1, true, false);
207 // a petition is invalid, if both the owner and the type matches
208 // we checked above, if this player is in an arenateam, so this must be data corruption
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 = (uint8)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 << uint64(petitionguid); // petition guid
274 data << uint64(_player->GetGUID()); // owner guid
275 data << uint32(petitionguid_low); // guild guid (in mangos always same as GUID_LOPART(petitionguid)
276 data << uint8(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 << uint64(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, ERR_GUILD_NAME_EXISTS_S);
408 return;
410 if(sObjectMgr.IsReservedName(newname) || !ObjectMgr::IsValidCharterName(newname))
412 SendGuildCommandResult(GUILD_CREATE_S, newname, ERR_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());
437 WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
438 data << uint64(petitionguid);
439 data << newname;
440 SendPacket(&data);
443 void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
445 sLog.outDebug("Received opcode CMSG_PETITION_SIGN"); // ok
446 //recv_data.hexlike();
448 Field *fields;
449 uint64 petitionguid;
450 uint8 unk;
451 recv_data >> petitionguid; // petition guid
452 recv_data >> unk;
454 QueryResult *result = CharacterDatabase.PQuery(
455 "SELECT ownerguid, "
456 " (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs, "
457 " type "
458 "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
460 if(!result)
462 sLog.outError("any petition on server...");
463 return;
466 fields = result->Fetch();
467 uint64 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
468 uint8 signs = fields[1].GetUInt8();
469 uint32 type = fields[2].GetUInt32();
471 delete result;
473 uint32 plguidlo = _player->GetGUIDLow();
474 if(GUID_LOPART(ownerguid) == plguidlo)
475 return;
477 // not let enemies sign guild charter
478 if(!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != sObjectMgr.GetPlayerTeamByGUID(ownerguid))
480 if(type != 9)
481 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
482 else
483 SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED);
484 return;
487 if(type != 9)
489 if(_player->getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
491 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, "", _player->GetName(), ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
492 return;
495 uint8 slot = ArenaTeam::GetSlotByType(type);
496 if(slot >= MAX_ARENA_SLOT)
497 return;
499 if(_player->GetArenaTeamId(slot))
501 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_IN_ARENA_TEAM_S);
502 return;
505 if(_player->GetArenaTeamIdInvited())
507 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
508 return;
511 else
513 if(_player->GetGuildId())
515 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S);
516 return;
518 if(_player->GetGuildIdInvited())
520 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S);
521 return;
525 if(++signs > type) // client signs maximum
526 return;
528 //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
529 //not allow sign another player from already sign player account
530 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
532 if(result)
534 delete result;
535 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
536 data << uint64(petitionguid);
537 data << uint64(_player->GetGUID());
538 data << uint32(PETITION_SIGN_ALREADY_SIGNED);
540 // close at signer side
541 SendPacket(&data);
543 // update for owner if online
544 if(Player *owner = sObjectMgr.GetPlayer(ownerguid))
545 owner->GetSession()->SendPacket(&data);
546 return;
549 CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
551 sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
553 WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
554 data << uint64(petitionguid);
555 data << uint64(_player->GetGUID());
556 data << uint32(PETITION_SIGN_OK);
558 // close at signer side
559 SendPacket(&data);
561 // update signs count on charter, required testing...
562 //Item *item = _player->GetItemByGuid(petitionguid));
563 //if(item)
564 // item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1+1, signs);
566 // update for owner if online
567 if(Player *owner = sObjectMgr.GetPlayer(ownerguid))
568 owner->GetSession()->SendPacket(&data);
571 void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
573 sLog.outDebug("Received opcode MSG_PETITION_DECLINE"); // ok
574 //recv_data.hexlike();
576 uint64 petitionguid;
577 uint64 ownerguid;
578 recv_data >> petitionguid; // petition guid
579 sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
581 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
582 if(!result)
583 return;
585 Field *fields = result->Fetch();
586 ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
587 delete result;
589 Player *owner = sObjectMgr.GetPlayer(ownerguid);
590 if(owner) // petition owner online
592 WorldPacket data(MSG_PETITION_DECLINE, 8);
593 data << uint64(_player->GetGUID());
594 owner->GetSession()->SendPacket(&data);
598 void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
600 sLog.outDebug("Received opcode CMSG_OFFER_PETITION"); // ok
601 //recv_data.hexlike();
603 uint8 signs = 0;
604 uint64 petitionguid, plguid;
605 uint32 type, junk;
606 Player *player;
607 recv_data >> junk; // this is not petition type!
608 recv_data >> petitionguid; // petition guid
609 recv_data >> plguid; // player guid
611 player = ObjectAccessor::FindPlayer(plguid);
612 if (!player)
613 return;
615 QueryResult *result = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
616 if (!result)
617 return;
619 Field *fields = result->Fetch();
620 type = fields[0].GetUInt32();
621 delete result;
623 sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", type, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
625 if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
627 if(type != 9)
628 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", "", ERR_ARENA_TEAM_NOT_ALLIED);
629 else
630 SendGuildCommandResult(GUILD_CREATE_S, "", ERR_GUILD_NOT_ALLIED);
631 return;
634 if(type != 9)
636 if(player->getLevel() < sWorld.getConfig(CONFIG_UINT32_MAX_PLAYER_LEVEL))
638 // player is too low level to join an arena team
639 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ARENA_TEAM_TARGET_TOO_LOW_S);
640 return;
643 uint8 slot = ArenaTeam::GetSlotByType(type);
644 if(slot >= MAX_ARENA_SLOT)
645 return;
647 if(player->GetArenaTeamId(slot))
649 // player is already in an arena team
650 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, player->GetName(), "", ERR_ALREADY_IN_ARENA_TEAM_S);
651 return;
654 if(player->GetArenaTeamIdInvited())
656 SendArenaTeamCommandResult(ERR_ARENA_TEAM_INVITE_SS, "", _player->GetName(), ERR_ALREADY_INVITED_TO_ARENA_TEAM_S);
657 return;
660 else
662 if(player->GetGuildId())
664 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_IN_GUILD_S);
665 return;
668 if(player->GetGuildIdInvited())
670 SendGuildCommandResult(GUILD_INVITE_S, _player->GetName(), ERR_ALREADY_INVITED_TO_GUILD_S);
671 return;
675 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
676 // result==NULL also correct charter without signs
677 if(result)
678 signs = (uint8)result->GetRowCount();
680 WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
681 data << uint64(petitionguid); // petition guid
682 data << uint64(_player->GetGUID()); // owner guid
683 data << uint32(GUID_LOPART(petitionguid)); // guild guid (in mangos always same as GUID_LOPART(petition guid)
684 data << uint8(signs); // sign's count
686 for(uint8 i = 1; i <= signs; ++i)
688 Field *fields2 = result->Fetch();
689 plguid = fields2[0].GetUInt64();
691 data << uint64(plguid); // Player GUID
692 data << uint32(0); // there 0 ...
694 result->NextRow();
697 delete result;
698 player->GetSession()->SendPacket(&data);
701 void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
703 sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
704 //recv_data.hexlike();
706 WorldPacket data;
707 uint64 petitionguid;
709 uint32 ownerguidlo;
710 uint32 type;
711 std::string name;
713 recv_data >> petitionguid;
715 sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
717 // data
718 QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
719 if(result)
721 Field *fields = result->Fetch();
722 ownerguidlo = fields[0].GetUInt32();
723 name = fields[1].GetCppString();
724 type = fields[2].GetUInt32();
725 delete result;
727 else
729 sLog.outError("petition table has broken data!");
730 return;
733 if(type == 9)
735 if(_player->GetGuildId())
737 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
738 data << uint32(PETITION_TURN_ALREADY_IN_GUILD); // already in guild
739 _player->GetSession()->SendPacket(&data);
740 return;
743 else
745 uint8 slot = ArenaTeam::GetSlotByType(type);
746 if(slot >= MAX_ARENA_SLOT)
747 return;
749 if(_player->GetArenaTeamId(slot))
751 //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
752 //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
753 //_player->GetSession()->SendPacket(&data);
754 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
755 return;
759 if(_player->GetGUIDLow() != ownerguidlo)
760 return;
762 // signs
763 uint8 signs;
764 result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
765 if(result)
766 signs = (uint8)result->GetRowCount();
767 else
768 signs = 0;
770 uint32 count;
771 //if(signs < sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS))
772 if(type == 9)
773 count = sWorld.getConfig(CONFIG_UINT32_MIN_PETITION_SIGNS);
774 else
775 count = type - 1;
776 if(signs < count)
778 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
779 data << uint32(PETITION_TURN_NEED_MORE_SIGNATURES); // need more signatures...
780 SendPacket(&data);
781 delete result;
782 return;
785 if(type == 9)
787 if(sObjectMgr.GetGuildByName(name))
789 SendGuildCommandResult(GUILD_CREATE_S, name, ERR_GUILD_NAME_EXISTS_S);
790 delete result;
791 return;
794 else
796 if(sObjectMgr.GetArenaTeamByName(name))
798 SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
799 delete result;
800 return;
804 // and at last charter item check
805 Item *item = _player->GetItemByGuid(petitionguid);
806 if(!item)
808 delete result;
809 return;
812 // OK!
814 // delete charter item
815 _player->DestroyItem(item->GetBagSlot(), item->GetSlot(), true);
817 if(type == 9) // create guild
819 Guild* guild = new Guild;
820 if(!guild->Create(_player, name))
822 delete guild;
823 delete result;
824 return;
827 // register guild and add guildmaster
828 sObjectMgr.AddGuild(guild);
830 // add members
831 for(uint8 i = 0; i < signs; ++i)
833 Field* fields = result->Fetch();
834 guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
835 result->NextRow();
838 else // or arena team
840 ArenaTeam* at = new ArenaTeam;
841 if(!at->Create(_player->GetGUID(), type, name))
843 sLog.outError("PetitionsHandler: arena team create failed.");
844 delete at;
845 delete result;
846 return;
849 uint32 icon, iconcolor, border, bordercolor, backgroud;
850 recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
852 at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
854 // register team and add captain
855 sObjectMgr.AddArenaTeam(at);
856 sLog.outDebug("PetitonsHandler: arena team added to objmrg");
858 // add members
859 for(uint8 i = 0; i < signs; ++i)
861 Field* fields = result->Fetch();
862 uint64 memberGUID = fields[0].GetUInt64();
863 sLog.outDebug("PetitionsHandler: adding arena member %u", GUID_LOPART(memberGUID));
864 at->AddMember(memberGUID);
865 result->NextRow();
869 delete result;
871 CharacterDatabase.BeginTransaction();
872 CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
873 CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
874 CharacterDatabase.CommitTransaction();
876 // created
877 sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
879 data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
880 data << uint32(PETITION_TURN_OK);
881 SendPacket(&data);
884 void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
886 sLog.outDebug("Received CMSG_PETITION_SHOWLIST"); // ok
887 //recv_data.hexlike();
889 uint64 guid;
890 recv_data >> guid;
892 SendPetitionShowList(guid);
895 void WorldSession::SendPetitionShowList(uint64 guid)
897 Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_PETITIONER);
898 if (!pCreature)
900 sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
901 return;
904 // remove fake death
905 if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
906 GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
908 uint8 count = 0;
909 if(pCreature->isTabardDesigner())
910 count = 1;
911 else
912 count = 3;
914 WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
915 data << uint64(guid); // npc guid
916 data << uint8(count); // count
917 if(count == 1)
919 data << uint32(1); // index
920 data << uint32(GUILD_CHARTER); // charter entry
921 data << uint32(CHARTER_DISPLAY_ID); // charter display id
922 data << uint32(GUILD_CHARTER_COST); // charter cost
923 data << uint32(0); // unknown
924 data << uint32(9); // required signs?
926 else
928 // 2v2
929 data << uint32(1); // index
930 data << uint32(ARENA_TEAM_CHARTER_2v2); // charter entry
931 data << uint32(CHARTER_DISPLAY_ID); // charter display id
932 data << uint32(ARENA_TEAM_CHARTER_2v2_COST); // charter cost
933 data << uint32(2); // unknown
934 data << uint32(2); // required signs?
935 // 3v3
936 data << uint32(2); // index
937 data << uint32(ARENA_TEAM_CHARTER_3v3); // charter entry
938 data << uint32(CHARTER_DISPLAY_ID); // charter display id
939 data << uint32(ARENA_TEAM_CHARTER_3v3_COST); // charter cost
940 data << uint32(3); // unknown
941 data << uint32(3); // required signs?
942 // 5v5
943 data << uint32(3); // index
944 data << uint32(ARENA_TEAM_CHARTER_5v5); // charter entry
945 data << uint32(CHARTER_DISPLAY_ID); // charter display id
946 data << uint32(ARENA_TEAM_CHARTER_5v5_COST); // charter cost
947 data << uint32(5); // unknown
948 data << uint32(5); // required signs?
950 //for(uint8 i = 0; i < count; ++i)
952 // data << uint32(i); // index
953 // data << uint32(GUILD_CHARTER); // charter entry
954 // data << uint32(CHARTER_DISPLAY_ID); // charter display id
955 // data << uint32(GUILD_CHARTER_COST+i); // charter cost
956 // data << uint32(0); // unknown
957 // data << uint32(9); // required signs?
959 SendPacket(&data);
960 sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");