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

Revision 102, 32.5 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

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