root/trunk/src/game/PetitionsHandler.cpp @ 37

Revision 37, 32.4 kB (checked in by yumileroy, 17 years ago)

[svn] * svn:eol-style native set on all files that need it

Original author: Neo2003
Date: 2008-10-11 14:16:25-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
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.
8 *
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.
13 *
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
17 */
18
19#include "Common.h"
20#include "Language.h"
21#include "WorldPacket.h"
22#include "WorldSession.h"
23#include "World.h"
24#include "ObjectMgr.h"
25#include "Log.h"
26#include "Opcodes.h"
27#include "Guild.h"
28#include "ArenaTeam.h"
29#include "MapManager.h"
30#include "GossipDef.h"
31#include "SocialMgr.h"
32
33/*enum PetitionType // dbc data
34{
35    PETITION_TYPE_GUILD      = 1,
36    PETITION_TYPE_ARENA_TEAM = 3
37};*/
38
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
49void WorldSession::HandlePetitionBuyOpcode(WorldPacket & recv_data)
50{
51    CHECK_PACKET_SIZE(recv_data, 8+8+4+1+5*8+2+1+4+4);
52
53    sLog.outDebug("Received opcode CMSG_PETITION_BUY");
54    //recv_data.hexlike();
55
56    uint64 guidNPC;
57    uint64 unk1, unk3, unk4, unk5, unk6, unk7;
58    uint32 unk2;
59    std::string name;
60    uint16 unk8;
61    uint8  unk9;
62    uint32 unk10;                                           // selected index
63    uint32 unk11;
64    recv_data >> guidNPC;                                   // NPC GUID
65    recv_data >> unk1;                                      // 0
66    recv_data >> unk2;                                      // 0
67    recv_data >> name;                                      // name
68
69    // recheck
70    CHECK_PACKET_SIZE(recv_data, 8+8+4+(name.size()+1)+5*8+2+1+4+4);
71
72    recv_data >> unk3;                                      // 0
73    recv_data >> unk4;                                      // 0
74    recv_data >> unk5;                                      // 0
75    recv_data >> unk6;                                      // 0
76    recv_data >> unk7;                                      // 0
77    recv_data >> unk8;                                      // 0
78    recv_data >> unk9;                                      // 0
79    recv_data >> unk10;                                     // index
80    recv_data >> unk11;                                     // 0
81    sLog.outDebug("Petitioner with GUID %u tried sell petition: name %s", GUID_LOPART(guidNPC), name.c_str());
82
83    // prevent cheating
84    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guidNPC,UNIT_NPC_FLAG_PETITIONER);
85    if (!pCreature)
86    {
87        sLog.outDebug("WORLD: HandlePetitionBuyOpcode - Unit (GUID: %u) not found or you can't interact with him.", GUID_LOPART(guidNPC));
88        return;
89    }
90
91    // remove fake death
92    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
93        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
94
95    uint32 charterid = 0;
96    uint32 cost = 0;
97    uint32 type = 0;
98    if(pCreature->isTabardDesigner())
99    {
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;
104
105        charterid = GUILD_CHARTER;
106        cost = GUILD_CHARTER_COST;
107        type = 9;
108    }
109    else
110    {
111        // TODO: find correct opcode
112        if(_player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
113        {
114            SendNotification(LANG_ARENA_ONE_TOOLOW, 70);
115            return;
116        }
117
118        for(uint8 i = 0; i < MAX_ARENA_SLOT; i++)
119        {
120            if(_player->GetArenaTeamId(i) && (i == (unk10-1)))
121            {
122                SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
123                return;
124            }
125        }
126        switch(unk10)
127        {
128            case 1:
129                charterid = ARENA_TEAM_CHARTER_2v2;
130                cost = ARENA_TEAM_CHARTER_2v2_COST;
131                type = 2;                                   // 2v2
132                break;
133            case 2:
134                charterid = ARENA_TEAM_CHARTER_3v3;
135                cost = ARENA_TEAM_CHARTER_3v3_COST;
136                type = 3;                                   // 3v3
137                break;
138            case 3:
139                charterid = ARENA_TEAM_CHARTER_5v5;
140                cost = ARENA_TEAM_CHARTER_5v5_COST;
141                type = 5;                                   // 5v5
142                break;
143            default:
144                sLog.outDebug("unknown selection at buy petition: %u", unk10);
145                return;
146        }
147    }
148
149    if(type == 9)
150    {
151        if(objmgr.GetGuildByName(name))
152        {
153            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
154            return;
155        }
156        if(objmgr.IsReservedName(name))
157        {
158            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
159            return;
160        }
161        if(!ObjectMgr::IsValidCharterName(name))
162        {
163            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_INVALID);
164            return;
165        }
166    }
167    else
168    {
169        if(objmgr.GetArenaTeamByName(name))
170        {
171            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
172            return;
173        }
174        if(objmgr.IsReservedName(name))
175        {
176            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
177            return;
178        }
179        if(!ObjectMgr::IsValidCharterName(name))
180        {
181            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_INVALID);
182            return;
183        }
184    }
185
186    ItemPrototype const *pProto = objmgr.GetItemPrototype(charterid);
187    if(!pProto)
188    {
189        _player->SendBuyError(BUY_ERR_CANT_FIND_ITEM, NULL, charterid, 0);
190        return;
191    }
192
193    if(_player->GetMoney() < cost)
194    {                                                       //player hasn't got enough money
195        _player->SendBuyError(BUY_ERR_NOT_ENOUGHT_MONEY, pCreature, charterid, 0);
196        return;
197    }
198
199    ItemPosCountVec dest;
200    uint8 msg = _player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, charterid, pProto->BuyCount );
201    if(msg != EQUIP_ERR_OK)
202    {
203        _player->SendBuyError(msg, pCreature, charterid, 0);
204        return;
205    }
206
207    _player->ModifyMoney(-(int32)cost);
208    Item *charter = _player->StoreNewItem(dest, charterid, true);
209    if(!charter)
210        return;
211
212    charter->SetUInt32Value(ITEM_FIELD_ENCHANTMENT, charter->GetGUIDLow());
213    // ITEM_FIELD_ENCHANTMENT is guild/arenateam id
214    // ITEM_FIELD_ENCHANTMENT+1 is current signatures count (showed on item)
215    charter->SetState(ITEM_CHANGED, _player);
216    _player->SendNewItem(charter, 1, true, false);
217
218    // a petition is invalid, if both the owner and the type matches
219    QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE ownerguid = '%u'  AND type = '%u'", _player->GetGUIDLow(), type);
220
221    std::ostringstream ssInvalidPetitionGUIDs;
222
223    if (result)
224    {
225
226        do
227        {
228            Field *fields = result->Fetch();
229            ssInvalidPetitionGUIDs << "'" << fields[0].GetUInt32() << "' , ";
230        } while (result->NextRow());
231
232        delete result;
233    }
234
235    // delete petitions with the same guid as this one
236    ssInvalidPetitionGUIDs << "'" << charter->GetGUIDLow() << "'";
237
238    sLog.outDebug("Invalid petition GUIDs: %s", ssInvalidPetitionGUIDs.str().c_str());
239    CharacterDatabase.escape_string(name);
240    CharacterDatabase.BeginTransaction();
241    CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid IN ( %s )",  ssInvalidPetitionGUIDs.str().c_str());
242    CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid IN ( %s )", ssInvalidPetitionGUIDs.str().c_str());
243    CharacterDatabase.PExecute("INSERT INTO petition (ownerguid, petitionguid, name, type) VALUES ('%u', '%u', '%s', '%u')",
244        _player->GetGUIDLow(), charter->GetGUIDLow(), name.c_str(), type);
245    CharacterDatabase.CommitTransaction();
246}
247
248void WorldSession::HandlePetitionShowSignOpcode(WorldPacket & recv_data)
249{
250    CHECK_PACKET_SIZE(recv_data, 8);
251
252                                                            // ok
253    sLog.outDebug("Received opcode CMSG_PETITION_SHOW_SIGNATURES");
254    //recv_data.hexlike();
255
256    uint8 signs = 0;
257    uint64 petitionguid;
258    recv_data >> petitionguid;                              // petition guid
259
260    // solve (possible) some strange compile problems with explicit use GUID_LOPART(petitionguid) at some GCC versions (wrong code optimization in compiler?)
261    uint32 petitionguid_low = GUID_LOPART(petitionguid);
262
263    QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid, type FROM petition WHERE petitionguid = '%u'", petitionguid_low);
264    if(!result)
265    {
266        sLog.outError("any petition on server...");
267        return;
268    }
269    Field *fields = result->Fetch();
270    uint32 type = fields[1].GetUInt32();
271    delete result;
272    // if guild petition and has guild => error, return;
273    if(type==9 && _player->GetGuildId())
274        return;
275
276    result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", petitionguid_low);
277
278    // result==NULL also correct in case no sign yet
279    if(result)
280        signs = result->GetRowCount();
281
282    sLog.outDebug("CMSG_PETITION_SHOW_SIGNATURES petition entry: '%u'", petitionguid_low);
283
284    WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+1+signs*12));
285    data << petitionguid;                                   // petition guid
286    data << _player->GetGUID();                             // owner guid
287    data << petitionguid_low;                               // guild guid (in mangos always same as GUID_LOPART(petitionguid)
288    data << signs;                                          // sign's count
289
290    for(uint8 i = 1; i <= signs; i++)
291    {
292        Field *fields = result->Fetch();
293        uint64 plguid = fields[0].GetUInt64();
294
295        data << plguid;                                     // Player GUID
296        data << (uint32)0;                                  // there 0 ...
297
298        result->NextRow();
299    }
300    delete result;
301    SendPacket(&data);
302}
303
304void WorldSession::HandlePetitionQueryOpcode(WorldPacket & recv_data)
305{
306    CHECK_PACKET_SIZE(recv_data, 4+8);
307
308    sLog.outDebug("Received opcode CMSG_PETITION_QUERY");   // ok
309    //recv_data.hexlike();
310
311    uint32 guildguid;
312    uint64 petitionguid;
313    recv_data >> guildguid;                                 // in mangos always same as GUID_LOPART(petitionguid)
314    recv_data >> petitionguid;                              // petition guid
315    sLog.outDebug("CMSG_PETITION_QUERY Petition GUID %u Guild GUID %u", GUID_LOPART(petitionguid), guildguid);
316
317    SendPetitionQueryOpcode(petitionguid);
318}
319
320void WorldSession::SendPetitionQueryOpcode(uint64 petitionguid)
321{
322    uint64 ownerguid = 0;
323    uint32 type;
324    std::string name = "NO_NAME_FOR_GUID";
325    uint8 signs = 0;
326
327    QueryResult *result = CharacterDatabase.PQuery(
328        "SELECT ownerguid, name, "
329        "  (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs "
330        "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
331
332    if(result)
333    {
334        Field* fields = result->Fetch();
335        ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
336        name      = fields[1].GetCppString();
337        signs     = fields[2].GetUInt8();
338        delete result;
339    }
340    else
341    {
342        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
343        return;
344    }
345
346    QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
347
348    if(result2)
349    {
350        Field* fields = result2->Fetch();
351        type = fields[0].GetUInt32();
352        delete result2;
353    }
354    else
355    {
356        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
357        return;
358    }
359
360    WorldPacket data(SMSG_PETITION_QUERY_RESPONSE, (4+8+name.size()+1+1+4*13));
361    data << GUID_LOPART(petitionguid);                      // guild/team guid (in mangos always same as GUID_LOPART(petition guid)
362    data << ownerguid;                                      // charter owner guid
363    data << name;                                           // name (guild/arena team)
364    data << uint8(0);                                       // 1
365    if(type == 9)
366    {
367        data << uint32(9);
368        data << uint32(9);
369        data << uint32(0);                                  // bypass client - side limitation, a different value is needed here for each petition
370    }
371    else
372    {
373        data << type-1;
374        data << type-1;
375        data << type;                                       // bypass client - side limitation, a different value is needed here for each petition
376    }
377    data << uint32(0);                                      // 5
378    data << uint32(0);                                      // 6
379    data << uint32(0);                                      // 7
380    data << uint32(0);                                      // 8
381    data << uint16(0);                                      // 9 2 bytes field
382    data << uint32(0);                                      // 10
383    data << uint32(0);                                      // 11
384    data << uint32(0);                                      // 13 count of next strings?
385    data << uint32(0);                                      // 14
386    if(type == 9)
387        data << uint32(0);                                  // 15 0 - guild, 1 - arena team
388    else
389        data << uint32(1);
390    SendPacket(&data);
391}
392
393void WorldSession::HandlePetitionRenameOpcode(WorldPacket & recv_data)
394{
395    CHECK_PACKET_SIZE(recv_data, 8+1);
396
397    sLog.outDebug("Received opcode MSG_PETITION_RENAME");   // ok
398    //recv_data.hexlike();
399
400    uint64 petitionguid;
401    uint32 type;
402    std::string newname;
403
404    recv_data >> petitionguid;                              // guid
405    recv_data >> newname;                                   // new name
406
407    Item *item = _player->GetItemByGuid(petitionguid);
408    if(!item)
409        return;
410
411    QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
412
413    if(result2)
414    {
415        Field* fields = result2->Fetch();
416        type = fields[0].GetUInt32();
417        delete result2;
418    }
419    else
420    {
421        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
422        return;
423    }
424
425    if(type == 9)
426    {
427        if(objmgr.GetGuildByName(newname))
428        {
429            SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_EXISTS);
430            return;
431        }
432        if(objmgr.IsReservedName(newname))
433        {
434            SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
435            return;
436        }
437        if(!ObjectMgr::IsValidCharterName(newname))
438        {
439            SendGuildCommandResult(GUILD_CREATE_S, newname, GUILD_NAME_INVALID);
440            return;
441        }
442    }
443    else
444    {
445        if(objmgr.GetArenaTeamByName(newname))
446        {
447            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
448            return;
449        }
450        if(objmgr.IsReservedName(newname))
451        {
452            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
453            return;
454        }
455        if(!ObjectMgr::IsValidCharterName(newname))
456        {
457            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, newname, "", ERR_ARENA_TEAM_NAME_INVALID);
458            return;
459        }
460    }
461
462    std::string db_newname = newname;
463    CharacterDatabase.escape_string(db_newname);
464    CharacterDatabase.PExecute("UPDATE petition SET name = '%s' WHERE petitionguid = '%u'",
465        db_newname.c_str(), GUID_LOPART(petitionguid));
466
467    sLog.outDebug("Petition (GUID: %u) renamed to '%s'", GUID_LOPART(petitionguid), newname.c_str());
468    WorldPacket data(MSG_PETITION_RENAME, (8+newname.size()+1));
469    data << petitionguid;
470    data << newname;
471    SendPacket(&data);
472}
473
474void WorldSession::HandlePetitionSignOpcode(WorldPacket & recv_data)
475{
476    CHECK_PACKET_SIZE(recv_data, 8+1);
477
478    sLog.outDebug("Received opcode CMSG_PETITION_SIGN");    // ok
479    //recv_data.hexlike();
480
481    Field *fields;
482    uint64 petitionguid;
483    uint32 type;
484    uint8 unk;
485    uint64 ownerguid;
486    recv_data >> petitionguid;                              // petition guid
487    recv_data >> unk;
488
489    uint8 signs = 0;
490
491    QueryResult *result = CharacterDatabase.PQuery(
492        "SELECT ownerguid, "
493        "  (SELECT COUNT(playerguid) FROM petition_sign WHERE petition_sign.petitionguid = '%u') AS signs "
494        "FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid), GUID_LOPART(petitionguid));
495
496    if(!result)
497    {
498        sLog.outError("any petition on server...");
499        return;
500    }
501
502    fields = result->Fetch();
503    ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
504    signs = fields[1].GetUInt8();
505
506    delete result;
507
508    uint32 plguidlo = _player->GetGUIDLow();
509    if(GUID_LOPART(ownerguid) == plguidlo)
510        return;
511
512    // not let enemies sign guild charter
513    if(!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != objmgr.GetPlayerTeamByGUID(ownerguid))
514        return;
515
516    QueryResult *result2 = CharacterDatabase.PQuery("SELECT type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
517
518    if(result2)
519    {
520        Field* fields = result2->Fetch();
521        type = fields[0].GetUInt32();
522        delete result2;
523    }
524    else
525    {
526        sLog.outDebug("CMSG_PETITION_QUERY failed for petition (GUID: %u)", GUID_LOPART(petitionguid));
527        return;
528    }
529
530    if(type != 9 && _player->getLevel() < sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL))
531    {
532        // player is too low level to join an arena team
533        SendNotification(LANG_YOUR_ARENA_LEVEL_REQ_ERROR,sWorld.getConfig(CONFIG_MAX_PLAYER_LEVEL));
534        return;
535    }
536
537    signs += 1;
538    if(signs > type)                                        // client signs maximum
539        return;
540
541    //client doesn't allow to sign petition two times by one character, but not check sign by another character from same account
542    //not allow sign another player from already sign player account
543    result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE player_account = '%u' AND petitionguid = '%u'", GetAccountId(), GUID_LOPART(petitionguid));
544
545    if(result)
546    {
547        delete result;
548        WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
549        data << petitionguid;
550        data << _player->GetGUID();
551        data << (uint32)PETITION_SIGN_ALREADY_SIGNED;
552
553        // close at signer side
554        SendPacket(&data);
555
556        // update for owner if online
557        if(Player *owner = objmgr.GetPlayer(ownerguid))
558            owner->GetSession()->SendPacket(&data);
559        return;
560    }
561
562    CharacterDatabase.PExecute("INSERT INTO petition_sign (ownerguid,petitionguid, playerguid, player_account) VALUES ('%u', '%u', '%u','%u')", GUID_LOPART(ownerguid),GUID_LOPART(petitionguid), plguidlo,GetAccountId());
563
564    sLog.outDebug("PETITION SIGN: GUID %u by player: %s (GUID: %u Account: %u)", GUID_LOPART(petitionguid), _player->GetName(),plguidlo,GetAccountId());
565
566    WorldPacket data(SMSG_PETITION_SIGN_RESULTS, (8+8+4));
567    data << petitionguid;
568    data << _player->GetGUID();
569    data << (uint32)PETITION_SIGN_OK;
570
571    // close at signer side
572    SendPacket(&data);
573
574    // update signs count on charter, required testing...
575    //Item *item = _player->GetItemByGuid(petitionguid));
576    //if(item)
577    //    item->SetUInt32Value(ITEM_FIELD_ENCHANTMENT+1, signs);
578
579    // update for owner if online
580    if(Player *owner = objmgr.GetPlayer(ownerguid))
581        owner->GetSession()->SendPacket(&data);
582}
583
584void WorldSession::HandlePetitionDeclineOpcode(WorldPacket & recv_data)
585{
586    CHECK_PACKET_SIZE(recv_data, 8);
587
588    sLog.outDebug("Received opcode MSG_PETITION_DECLINE");  // ok
589    //recv_data.hexlike();
590
591    uint64 petitionguid;
592    uint64 ownerguid;
593    recv_data >> petitionguid;                              // petition guid
594    sLog.outDebug("Petition %u declined by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
595
596    QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
597    if(!result)
598        return;
599
600    Field *fields = result->Fetch();
601    ownerguid = MAKE_NEW_GUID(fields[0].GetUInt32(), 0, HIGHGUID_PLAYER);
602    delete result;
603
604    Player *owner = objmgr.GetPlayer(ownerguid);
605    if(owner)                                               // petition owner online
606    {
607        WorldPacket data(MSG_PETITION_DECLINE, 8);
608        data << _player->GetGUID();
609        owner->GetSession()->SendPacket(&data);
610    }
611}
612
613void WorldSession::HandleOfferPetitionOpcode(WorldPacket & recv_data)
614{
615    CHECK_PACKET_SIZE(recv_data, 4+8+8);
616
617    sLog.outDebug("Received opcode CMSG_OFFER_PETITION");   // ok
618    //recv_data.hexlike();
619
620    uint8 signs = 0;
621    uint64 petitionguid, plguid;
622    uint32 petitiontype;
623    Player *player;
624    recv_data >> petitiontype;                              // 2.0.8 - petition type?
625    recv_data >> petitionguid;                              // petition guid
626    recv_data >> plguid;                                    // player guid
627    sLog.outDebug("OFFER PETITION: type %u, GUID1 %u, to player id: %u", petitiontype, GUID_LOPART(petitionguid), GUID_LOPART(plguid));
628
629    player = ObjectAccessor::FindPlayer(plguid);
630    if(!player || player->GetSocial()->HasIgnore(GetPlayer()->GetGUIDLow()))
631        return;
632
633    // not let offer to enemies
634    if (!sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD) && GetPlayer()->GetTeam() != player->GetTeam() )
635        return;
636
637    QueryResult *result = CharacterDatabase.PQuery("SELECT petitionguid FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
638    if(!result)
639    {
640        sLog.outError("any petition on server...");
641        return;
642    }
643
644    delete result;
645
646    result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
647    // result==NULL also correct charter without signs
648    if(result)
649        signs = result->GetRowCount();
650
651    WorldPacket data(SMSG_PETITION_SHOW_SIGNATURES, (8+8+4+signs+signs*12));
652    data << petitionguid;                                   // petition guid
653    data << _player->GetGUID();                             // owner guid
654    data << GUID_LOPART(petitionguid);                      // guild guid (in mangos always same as GUID_LOPART(petition guid)
655    data << signs;                                          // sign's count
656
657    for(uint8 i = 1; i <= signs; i++)
658    {
659        Field *fields = result->Fetch();
660        uint64 plguid = fields[0].GetUInt64();
661
662        data << plguid;                                     // Player GUID
663        data << (uint32)0;                                  // there 0 ...
664
665        result->NextRow();
666    }
667
668    delete result;
669    player->GetSession()->SendPacket(&data);
670}
671
672void WorldSession::HandleTurnInPetitionOpcode(WorldPacket & recv_data)
673{
674    CHECK_PACKET_SIZE(recv_data, 8);
675
676    sLog.outDebug("Received opcode CMSG_TURN_IN_PETITION"); // ok
677    //recv_data.hexlike();
678
679    WorldPacket data;
680    uint64 petitionguid;
681
682    uint32 ownerguidlo;
683    uint32 type;
684    std::string name;
685
686    recv_data >> petitionguid;
687
688    sLog.outDebug("Petition %u turned in by %u", GUID_LOPART(petitionguid), _player->GetGUIDLow());
689
690    // data
691    QueryResult *result = CharacterDatabase.PQuery("SELECT ownerguid, name, type FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
692    if(result)
693    {
694        Field *fields = result->Fetch();
695        ownerguidlo = fields[0].GetUInt32();
696        name = fields[1].GetCppString();
697        type = fields[2].GetUInt32();
698        delete result;
699    }
700    else
701    {
702        sLog.outError("petition table has broken data!");
703        return;
704    }
705
706    if(type == 9)
707    {
708        if(_player->GetGuildId())
709        {
710            data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
711            data << (uint32)PETITION_TURN_ALREADY_IN_GUILD; // already in guild
712            _player->GetSession()->SendPacket(&data);
713            return;
714        }
715    }
716    else
717    {
718        uint8 slot = ArenaTeam::GetSlotByType(type);
719        if(slot >= MAX_ARENA_SLOT)
720            return;
721
722        if(_player->GetArenaTeamId(slot))
723        {
724            //data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
725            //data << (uint32)PETITION_TURN_ALREADY_IN_GUILD;                          // already in guild
726            //_player->GetSession()->SendPacket(&data);
727            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ALREADY_IN_ARENA_TEAM);
728            return;
729        }
730    }
731
732    if(_player->GetGUIDLow() != ownerguidlo)
733        return;
734
735    // signs
736    uint8 signs;
737    result = CharacterDatabase.PQuery("SELECT playerguid FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
738    if(result)
739        signs = result->GetRowCount();
740    else
741        signs = 0;
742
743    uint32 count;
744    //if(signs < sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS))
745    if(type == 9)
746        count = sWorld.getConfig(CONFIG_MIN_PETITION_SIGNS);
747    else
748        count = type-1;
749    if(signs < count)
750    {
751        data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
752        data << (uint32)PETITION_TURN_NEED_MORE_SIGNATURES; // need more signatures...
753        SendPacket(&data);
754        delete result;
755        return;
756    }
757
758    if(type == 9)
759    {
760        if(objmgr.GetGuildByName(name))
761        {
762            SendGuildCommandResult(GUILD_CREATE_S, name, GUILD_NAME_EXISTS);
763            delete result;
764            return;
765        }
766    }
767    else
768    {
769        if(objmgr.GetArenaTeamByName(name))
770        {
771            SendArenaTeamCommandResult(ERR_ARENA_TEAM_CREATE_S, name, "", ERR_ARENA_TEAM_NAME_EXISTS_S);
772            delete result;
773            return;
774        }
775    }
776
777    // and at last charter item check
778    Item *item = _player->GetItemByGuid(petitionguid);
779    if(!item)
780    {
781        delete result;
782        return;
783    }
784
785    // OK!
786
787    // delete charter item
788    _player->DestroyItem(item->GetBagSlot(),item->GetSlot(), true);
789
790    if(type == 9)                                           // create guild
791    {
792        Guild* guild = new Guild;
793        if(!guild->create(_player->GetGUID(), name))
794        {
795            delete guild;
796            delete result;
797            return;
798        }
799
800        // register guild and add guildmaster
801        objmgr.AddGuild(guild);
802
803        // add members
804        for(uint8 i = 0; i < signs; ++i)
805        {
806            Field* fields = result->Fetch();
807            guild->AddMember(fields[0].GetUInt64(), guild->GetLowestRank());
808            result->NextRow();
809        }
810    }
811    else                                                    // or arena team
812    {
813        ArenaTeam* at = new ArenaTeam;
814        if(!at->create(_player->GetGUID(), type, name))
815        {
816            sLog.outError("PetitionsHandler: arena team create failed.");
817            delete at;
818            delete result;
819            return;
820        }
821
822        CHECK_PACKET_SIZE(recv_data, 8+5*4);
823        uint32 icon, iconcolor, border, bordercolor, backgroud;
824        recv_data >> backgroud >> icon >> iconcolor >> border >> bordercolor;
825
826        at->SetEmblem(backgroud, icon, iconcolor, border, bordercolor);
827
828        // register team and add captain
829        objmgr.AddArenaTeam(at);
830        sLog.outDebug("PetitonsHandler: arena team added to objmrg");
831
832        // add members
833        for(uint8 i = 0; i < signs; ++i)
834        {
835            Field* fields = result->Fetch();
836            sLog.outDebug("PetitionsHandler: adding arena member %u", fields[0].GetUInt64());
837            at->AddMember(fields[0].GetUInt64());
838            result->NextRow();
839        }
840    }
841
842    delete result;
843
844    CharacterDatabase.BeginTransaction();
845    CharacterDatabase.PExecute("DELETE FROM petition WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
846    CharacterDatabase.PExecute("DELETE FROM petition_sign WHERE petitionguid = '%u'", GUID_LOPART(petitionguid));
847    CharacterDatabase.CommitTransaction();
848
849    // created
850    sLog.outDebug("TURN IN PETITION GUID %u", GUID_LOPART(petitionguid));
851
852    data.Initialize(SMSG_TURN_IN_PETITION_RESULTS, 4);
853    data << (uint32)PETITION_TURN_OK;
854    SendPacket(&data);
855}
856
857void WorldSession::HandlePetitionShowListOpcode(WorldPacket & recv_data)
858{
859    CHECK_PACKET_SIZE(recv_data, 8);
860
861    sLog.outDebug("Received CMSG_PETITION_SHOWLIST");       // ok
862    //recv_data.hexlike();
863
864    uint64 guid;
865    recv_data >> guid;
866
867    SendPetitionShowList(guid);
868}
869
870void WorldSession::SendPetitionShowList(uint64 guid)
871{
872    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid, UNIT_NPC_FLAG_PETITIONER);
873    if (!pCreature)
874    {
875        sLog.outDebug("WORLD: HandlePetitionShowListOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)));
876        return;
877    }
878
879    // remove fake death
880    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
881        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
882
883    uint8 count = 0;
884    if(pCreature->isTabardDesigner())
885        count = 1;
886    else
887        count = 3;
888
889    WorldPacket data(SMSG_PETITION_SHOWLIST, 8+1+4*6);
890    data << guid;                                           // npc guid
891    data << count;                                          // count
892    if(count == 1)
893    {
894        data << uint32(1);                                  // index
895        data << uint32(GUILD_CHARTER);                      // charter entry
896        data << uint32(16161);                              // charter display id
897        data << uint32(GUILD_CHARTER_COST);                 // charter cost
898        data << uint32(0);                                  // unknown
899        data << uint32(9);                                  // required signs?
900    }
901    else
902    {
903        // 2v2
904        data << uint32(1);                                  // index
905        data << uint32(ARENA_TEAM_CHARTER_2v2);             // charter entry
906        data << uint32(16161);                              // charter display id
907        data << uint32(ARENA_TEAM_CHARTER_2v2_COST);        // charter cost
908        data << uint32(2);                                  // unknown
909        data << uint32(2);                                  // required signs?
910        // 3v3
911        data << uint32(2);                                  // index
912        data << uint32(ARENA_TEAM_CHARTER_3v3);             // charter entry
913        data << uint32(16161);                              // charter display id
914        data << uint32(ARENA_TEAM_CHARTER_3v3_COST);        // charter cost
915        data << uint32(3);                                  // unknown
916        data << uint32(3);                                  // required signs?
917        // 5v5
918        data << uint32(3);                                  // index
919        data << uint32(ARENA_TEAM_CHARTER_5v5);             // charter entry
920        data << uint32(16161);                              // charter display id
921        data << uint32(ARENA_TEAM_CHARTER_5v5_COST);        // charter cost
922        data << uint32(5);                                  // unknown
923        data << uint32(5);                                  // required signs?
924    }
925    //for(uint8 i = 0; i < count; i++)
926    //{
927    //    data << uint32(i);                      // index
928    //    data << uint32(GUILD_CHARTER);          // charter entry
929    //    data << uint32(16161);                  // charter display id
930    //    data << uint32(GUILD_CHARTER_COST+i);   // charter cost
931    //    data << uint32(0);                      // unknown
932    //    data << uint32(9);                      // required signs?
933    //}
934    SendPacket(&data);
935    sLog.outDebug("Sent SMSG_PETITION_SHOWLIST");
936}
Note: See TracBrowser for help on using the browser.