root/trunk/src/game/AuctionHouse.cpp @ 2

Revision 2, 28.9 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

RevLine 
[2]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 "WorldPacket.h"
20#include "WorldSession.h"
21#include "Opcodes.h"
22#include "Log.h"
23#include "World.h"
24#include "ObjectMgr.h"
25#include "Player.h"
26#include "UpdateMask.h"
27#include "AuctionHouseObject.h"
28#include "Util.h"
29
30//please DO NOT use iterator++, because it is slower than ++iterator!!!
31//post-incrementation is always slower than pre-incrementation !
32
33//void called when player click on auctioneer npc
34void WorldSession::HandleAuctionHelloOpcode( WorldPacket & recv_data )
35{
36    CHECK_PACKET_SIZE(recv_data,8);
37
38    uint64 guid;                                            //NPC guid
39    recv_data >> guid;
40
41    Creature *unit = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER);
42    if (!unit)
43    {
44        sLog.outDebug( "WORLD: HandleAuctionHelloOpcode - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
45        return;
46    }
47
48    // remove fake death
49    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
50        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
51
52    SendAuctionHello(guid, unit);
53}
54
55static uint8 AuctioneerFactionToLocation(uint32 faction)
56{
57    if(sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION))
58        return 7;                                           // neutral
59
60    FactionTemplateEntry const* u_entry = sFactionTemplateStore.LookupEntry(faction);
61    if(!u_entry)
62        return 7;                                           // neutral
63
64    if(u_entry->ourMask & FACTION_MASK_ALLIANCE)
65        return 2;
66    else if(u_entry->ourMask & FACTION_MASK_HORDE)
67        return 6;
68    else
69        return 7;
70}
71
72//this void causes that auction window is opened
73void WorldSession::SendAuctionHello( uint64 guid, Creature* unit )
74{
75    WorldPacket data( MSG_AUCTION_HELLO, 12 );
76    data << (uint64) guid;
77    data << (uint32) AuctioneerFactionToLocation(unit->getFaction());
78    SendPacket( &data );
79}
80
81//this function inserts to WorldPacket auction's data
82bool WorldSession::SendAuctionInfo(WorldPacket & data, AuctionEntry* auction)
83{
84    Item *pItem = objmgr.GetAItem(auction->item_guidlow);
85    if (!pItem)
86    {
87        sLog.outError("auction to item, that doesn't exist !!!!");
88        return false;
89    }
90    data << auction->Id;
91    data << pItem->GetUInt32Value(OBJECT_FIELD_ENTRY);
92
93    for (uint8 i = 0; i < MAX_INSPECTED_ENCHANTMENT_SLOT; i++)
94    {
95        data << (uint32) pItem->GetEnchantmentId(EnchantmentSlot(i));
96        data << (uint32) pItem->GetEnchantmentDuration(EnchantmentSlot(i));
97        data << (uint32) pItem->GetEnchantmentCharges(EnchantmentSlot(i));
98    }
99
100    data << (uint32) pItem->GetItemRandomPropertyId();      //random item property id
101    data << (uint32) pItem->GetItemSuffixFactor();          //SuffixFactor
102    data << (uint32) pItem->GetCount();                     //item->count
103    data << (uint32) pItem->GetSpellCharges();              //item->charge FFFFFFF
104    data << (uint32) 0;                                     //Unknown
105    data << (uint64) auction->owner;                        //Auction->owner
106    data << (uint32) auction->startbid;                     //Auction->startbid (not sure if useful)
107    data << (uint32) ((auction->bid)? objmgr.GetAuctionOutBid(auction->bid) : 0);
108                                                            //minimal outbid
109    data << (uint32) auction->buyout;                       //auction->buyout
110    data << (uint32) (auction->time - time(NULL)) * 1000;   //time left
111    data << (uint64) auction->bidder;                       //auction->bidder current
112    data << (uint32) auction->bid;                          //current bid
113    return true;
114}
115
116//call this method when player bids, creates, or deletes auction
117void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError )
118{
119    WorldPacket data( SMSG_AUCTION_COMMAND_RESULT, 16 );
120    data << auctionId;
121    data << Action;
122    data << ErrorCode;
123    if ( !ErrorCode && Action )
124        data << bidError;                                   //when bid, then send 0, once...
125    SendPacket(&data);
126}
127
128//this function sends notification, if bidder is online
129void WorldSession::SendAuctionBidderNotification( uint32 location, uint32 auctionId, uint64 bidder, uint32 bidSum, uint32 diff, uint32 item_template)
130{
131    WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4));
132    data << location;
133    data << auctionId;
134    data << (uint64) bidder;
135    data << bidSum;
136    data << (uint32) diff;
137    data << item_template;
138    data << (uint32) 0;
139    SendPacket(&data);
140}
141
142//this void causes on client to display: "Your auction sold"
143void WorldSession::SendAuctionOwnerNotification( AuctionEntry* auction)
144{
145    WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (7*4));
146    data << auction->Id;
147    data << auction->bid;
148    data << (uint32) 0;                                     //unk
149    data << (uint32) 0;                                     //unk
150    data << (uint32) 0;                                     //unk
151    data << auction->item_template;
152    data << (uint32) 0;                                     //unk
153    SendPacket(&data);
154}
155
156//this function sends mail to old bidder
157void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice)
158{
159    uint64 oldBidder_guid = MAKE_NEW_GUID(auction->bidder,0, HIGHGUID_PLAYER);
160    Player *oldBidder = objmgr.GetPlayer(oldBidder_guid);
161
162    uint32 oldBidder_accId = 0;
163    if(!oldBidder)
164        oldBidder_accId = objmgr.GetPlayerAccountIdByGUID(oldBidder_guid);
165
166    // old bidder exist
167    if(oldBidder || oldBidder_accId)
168    {
169        std::ostringstream msgAuctionOutbiddedSubject;
170        msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED;
171
172        if (oldBidder)
173            oldBidder->GetSession()->SendAuctionBidderNotification( auction->location, auction->Id, _player->GetGUID(), newPrice, objmgr.GetAuctionOutBid(auction->bid), auction->item_template);
174
175        WorldSession::SendMailTo(oldBidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->bidder, msgAuctionOutbiddedSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE);
176    }
177}
178
179//this function sends mail, when auction is cancelled to old bidder
180void WorldSession::SendAuctionCancelledToBidderMail( AuctionEntry* auction )
181{
182    uint64 bidder_guid = MAKE_NEW_GUID(auction->bidder, 0, HIGHGUID_PLAYER);
183    Player *bidder = objmgr.GetPlayer(bidder_guid);
184
185    uint32 bidder_accId = 0;
186    if(!bidder)
187        bidder_accId = objmgr.GetPlayerAccountIdByGUID(bidder_guid);
188
189    // bidder exist
190    if(bidder || bidder_accId)
191    {
192        std::ostringstream msgAuctionCancelledSubject;
193        msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER;
194
195        WorldSession::SendMailTo(bidder, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, auction->bidder, msgAuctionCancelledSubject.str(), 0, NULL, auction->bid, 0, MAIL_CHECK_MASK_NONE);
196    }
197}
198
199//this void creates new auction and adds auction to some auctionhouse
200void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
201{
202    CHECK_PACKET_SIZE(recv_data,8+8+4+4+4);
203
204    uint64 auctioneer, item;
205    uint32 etime, bid, buyout;
206    recv_data >> auctioneer >> item;
207    recv_data >> bid >> buyout >> etime;
208    Player *pl = GetPlayer();
209
210    if (!item || !bid || !etime)
211        return;                                             //check for cheaters
212
213    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER);
214    if (!pCreature)
215    {
216        sLog.outDebug( "WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) );
217        return;
218    }
219
220    // client send time in minutes, convert to common used sec time
221    etime *= MINUTE;
222
223    // client understand only 3 auction time
224    switch(etime)
225    {
226        case 1*MIN_AUCTION_TIME:
227        case 2*MIN_AUCTION_TIME:
228        case 4*MIN_AUCTION_TIME:
229            break;
230        default:
231            return;
232    }
233
234    // remove fake death
235    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
236        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
237
238    Item *it = pl->GetItemByGuid( item );
239    //do not allow to sell already auctioned items
240    if(objmgr.GetAItem(GUID_LOPART(item)))
241    {
242        sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item));
243        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
244        return;
245    }
246    // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction)
247    if(!it)
248    {
249        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND);
250        return;
251    }
252
253    if(!it->CanBeTraded())
254    {
255        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
256        return;
257    }
258
259    if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION))
260    {
261        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
262        return;
263    }
264
265    uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
266    AuctionHouseObject * mAuctions;
267    mAuctions = objmgr.GetAuctionsMap( location );
268
269    //we have to take deposit :
270    uint32 deposit = objmgr.GetAuctionDeposit( location, etime, it );
271    if ( pl->GetMoney() < deposit )
272    {
273        SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY);
274        return;
275    }
276
277    if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
278    {
279        sLog.outCommand("GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)",
280            GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount());
281    }
282
283    pl->ModifyMoney( -int32(deposit) );
284
285    uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME));
286
287    AuctionEntry *AH = new AuctionEntry;
288    AH->Id = objmgr.GenerateAuctionID();
289    AH->auctioneer = GUID_LOPART(auctioneer);
290    AH->item_guidlow = GUID_LOPART(item);
291    AH->item_template = it->GetEntry();
292    AH->owner = pl->GetGUIDLow();
293    AH->startbid = bid;
294    AH->bidder = 0;
295    AH->bid = 0;
296    AH->buyout = buyout;
297    AH->time = time(NULL) + auction_time;
298    AH->deposit = deposit;
299    AH->location = location;
300
301    sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in location: %u", GUID_LOPART(item), GUID_LOPART(auctioneer), bid, buyout, auction_time, location);
302    mAuctions->AddAuction(AH);
303
304    objmgr.AddAItem(it);
305    pl->MoveItemFromInventory( it->GetBagSlot(), it->GetSlot(), true);
306
307    CharacterDatabase.BeginTransaction();
308    it->DeleteFromInventoryDB();
309    it->SaveToDB();                                         // recursive and not have transaction guard into self, not in inventiory and can be save standalone
310    CharacterDatabase.PExecute("INSERT INTO auctionhouse (id,auctioneerguid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit,location) "
311        "VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" I64FMTD "', '%u', '%u', '%u', '%u', '%u')",
312        AH->Id, AH->auctioneer, AH->item_guidlow, AH->item_template, AH->owner, AH->buyout, (uint64)AH->time, AH->bidder, AH->bid, AH->startbid, AH->deposit, AH->location);
313    pl->SaveInventoryAndGoldToDB();
314    CharacterDatabase.CommitTransaction();
315
316    SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK);
317}
318
319//this function is called when client bids or buys out auction
320void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data )
321{
322    CHECK_PACKET_SIZE(recv_data,8+4+4);
323
324    uint64 auctioneer;
325    uint32 auctionId;
326    uint32 price;
327    recv_data >> auctioneer;
328    recv_data >> auctionId >> price;
329
330    if (!auctionId || !price)
331        return;                                             //check for cheaters
332
333    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER);
334    if (!pCreature)
335    {
336        sLog.outDebug( "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) );
337        return;
338    }
339
340    // remove fake death
341    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
342        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
343
344    uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
345
346    AuctionHouseObject * mAuctions;
347    mAuctions = objmgr.GetAuctionsMap( location );
348
349    AuctionEntry *auction = mAuctions->GetAuction(auctionId);
350    Player *pl = GetPlayer();
351
352    if( !auction || auction->owner == pl->GetGUIDLow() )
353    {
354        //you cannot bid your own auction:
355        SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR );
356        return;
357    }
358
359    // impossible have online own another character (use this for speedup check in case online owner)
360    Player* auction_owner = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER));
361    if( !auction_owner && objmgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId())
362    {
363        //you cannot bid your another character auction:
364        SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR );
365        return;
366    }
367
368    if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid)))
369    {
370        //auction has already higher bid, client tests it!
371        //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
372        return;
373    }
374
375    if (price > pl->GetMoney())
376    {
377        //you don't have enought money!, client tests!
378        //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
379        return;
380    }
381
382    if ((price < auction->buyout) || (auction->buyout == 0))
383    {
384        if (auction->bidder > 0)
385        {
386            if ( auction->bidder == pl->GetGUIDLow() )
387            {
388                pl->ModifyMoney( -int32(price - auction->bid));
389            }
390            else
391            {
392                // mail to last bidder and return money
393                SendAuctionOutbiddedMail( auction , price );
394                pl->ModifyMoney( -int32(price) );
395            }
396        }
397        else
398        {
399            pl->ModifyMoney( -int32(price) );
400        }
401        auction->bidder = pl->GetGUIDLow();
402        auction->bid = price;
403
404        // after this update we should save player's money ...
405        CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id);
406
407        SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0 );
408    }
409    else
410    {
411        //buyout:
412        if (pl->GetGUIDLow() == auction->bidder )
413        {
414            pl->ModifyMoney(-int32(auction->buyout - auction->bid));
415        }
416        else
417        {
418            pl->ModifyMoney(-int32(auction->buyout));
419            if ( auction->bidder )                          //buyout for bidded auction ..
420            {
421                SendAuctionOutbiddedMail( auction, auction->buyout );
422            }
423        }
424        auction->bidder = pl->GetGUIDLow();
425        auction->bid = auction->buyout;
426
427        objmgr.SendAuctionSalePendingMail( auction );
428        objmgr.SendAuctionSuccessfulMail( auction );
429        objmgr.SendAuctionWonMail( auction );
430
431        SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK);
432
433        objmgr.RemoveAItem(auction->item_guidlow);
434        mAuctions->RemoveAuction(auction->Id);
435        CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id);
436
437        delete auction;
438    }
439    CharacterDatabase.BeginTransaction();
440    pl->SaveInventoryAndGoldToDB();
441    CharacterDatabase.CommitTransaction();
442}
443
444//this void is called when auction_owner cancels his auction
445void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data )
446{
447    CHECK_PACKET_SIZE(recv_data,8+4);
448
449    uint64 auctioneer;
450    uint32 auctionId;
451    recv_data >> auctioneer;
452    recv_data >> auctionId;
453    //sLog.outDebug( "Cancel AUCTION AuctionID: %u", auctionId);
454
455    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, auctioneer,UNIT_NPC_FLAG_AUCTIONEER);
456    if (!pCreature)
457    {
458        sLog.outDebug( "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) );
459        return;
460    }
461
462    // remove fake death
463    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
464        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
465
466    uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
467
468    AuctionHouseObject * mAuctions;
469    mAuctions = objmgr.GetAuctionsMap( location );
470
471    AuctionEntry *auction = mAuctions->GetAuction(auctionId);
472    Player *pl = GetPlayer();
473
474    if (auction && auction->owner == pl->GetGUIDLow())
475    {
476        Item *pItem = objmgr.GetAItem(auction->item_guidlow);
477        if (pItem)
478        {
479            if (auction->bidder > 0)                        // If we have a bidder, we have to send him the money he paid
480            {
481                uint32 auctionCut = objmgr.GetAuctionCut( auction->location, auction->bid);
482                if ( pl->GetMoney() < auctionCut )          //player doesn't have enough money, maybe message needed
483                    return;
484                //some auctionBidderNotification would be needed, but don't know that parts..
485                SendAuctionCancelledToBidderMail( auction );
486                pl->ModifyMoney( -int32(auctionCut) );
487            }
488            // Return the item by mail
489            std::ostringstream msgAuctionCanceledOwner;
490            msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED;
491
492            MailItemsInfo mi;
493            mi.AddItem(auction->item_guidlow, auction->item_template, pItem);
494
495            // item will deleted or added to received mail list
496            WorldSession::SendMailTo(pl, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->location, pl->GetGUIDLow(), msgAuctionCanceledOwner.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE);
497        }
498        else
499        {
500            sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow);
501            SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR );
502            return;
503        }
504    }
505    else
506    {
507        SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR );
508        //this code isn't possible ... maybe there should be assert
509        sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId );
510        return;
511    }
512
513    //inform player, that auction is removed
514    SendAuctionCommandResult( auction->Id, AUCTION_CANCEL, AUCTION_OK );
515    // Now remove the auction
516    CharacterDatabase.BeginTransaction();
517    CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id);
518    pl->SaveInventoryAndGoldToDB();
519    CharacterDatabase.CommitTransaction();
520    objmgr.RemoveAItem( auction->item_guidlow );
521    mAuctions->RemoveAuction( auction->Id );
522    delete auction;
523}
524
525//called when player lists his bids
526void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data )
527{
528    CHECK_PACKET_SIZE(recv_data,8+4+4);
529
530    uint64 guid;                                            //NPC guid
531    uint32 listfrom;                                        //page of auctions
532    uint32 outbiddedCount;                                  //count of outbidded auctions
533
534    recv_data >> guid;
535    recv_data >> listfrom;                                  // not used in fact (this list not have page control in client)
536    recv_data >> outbiddedCount;
537    if (recv_data.size() != (16 + outbiddedCount * 4 ))
538    {
539        sLog.outError("Client sent bad opcode!!! with count: %u and size : %d (mustbe: %d", outbiddedCount, recv_data.size(),(16 + outbiddedCount * 4 ));
540        outbiddedCount = 0;
541    }
542
543    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER);
544    if (!pCreature)
545    {
546        sLog.outDebug( "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
547        return;
548    }
549
550    // remove fake death
551    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
552        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
553
554    uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
555    AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location );
556
557    WorldPacket data( SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4) );
558    Player *pl = GetPlayer();
559    data << (uint32) 0;                                     //add 0 as count
560    uint32 count = 0;
561    uint32 totalcount = 0;
562    while ( outbiddedCount > 0)                             //add all data, which client requires
563    {
564        --outbiddedCount;
565        uint32 outbiddedAuctionId;
566        recv_data >> outbiddedAuctionId;
567        AuctionEntry * auction = mAuctions->GetAuction( outbiddedAuctionId );
568        if ( auction && SendAuctionInfo(data, auction))
569        {
570            ++totalcount;
571            ++count;
572        }
573    }
574    for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr)
575    {
576        AuctionEntry *Aentry = itr->second;
577        if( Aentry && Aentry->bidder == pl->GetGUIDLow() )
578        {
579            if (SendAuctionInfo(data, itr->second))
580                ++count;
581            ++totalcount;
582        }
583    }
584    data.put<uint32>( 0, count );                           // add count to placeholder
585    data << totalcount;
586    data << (uint32)300;                                    //unk 2.3.0
587    SendPacket(&data);
588}
589
590//this void sends player info about his auctions
591void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data )
592{
593    CHECK_PACKET_SIZE(recv_data,8+4);
594
595    uint32 listfrom;
596    uint64 guid;
597
598    recv_data >> guid;
599    recv_data >> listfrom;                                  // not used in fact (this list not have page control in client)
600
601    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER);
602    if (!pCreature)
603    {
604        sLog.outDebug( "WORLD: HandleAuctionListOwnerItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
605        return;
606    }
607
608    // remove fake death
609    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
610        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
611
612    uint32 location = AuctioneerFactionToLocation(pCreature->getFaction());
613
614    AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location );
615
616    WorldPacket data( SMSG_AUCTION_OWNER_LIST_RESULT, (4+4+4) );
617    data << (uint32) 0;                                     // amount place holder
618
619    uint32 count = 0;
620    uint32 totalcount = 0;
621    for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr)
622    {
623        AuctionEntry *Aentry = itr->second;
624        if( Aentry && Aentry->owner == _player->GetGUIDLow() )
625        {
626            if(SendAuctionInfo(data, itr->second))
627                ++count;
628            ++totalcount;
629        }
630    }
631    data.put<uint32>(0, count);
632    data << (uint32) totalcount;
633    data << (uint32) 0;
634    SendPacket(&data);
635}
636
637//this void is called when player clicks on search button
638void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
639{
640    CHECK_PACKET_SIZE(recv_data,8+4+1+1+1+4+4+4+4+1);
641
642    std::string searchedname, name;
643    uint8 levelmin, levelmax, usable, location;
644    uint32 count, totalcount, listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality;
645    uint64 guid;
646
647    recv_data >> guid;
648    recv_data >> listfrom;                                  // start, used for page control listing by 50 elements
649    recv_data >> searchedname;
650
651    // recheck with known string size
652    CHECK_PACKET_SIZE(recv_data,8+4+(searchedname.size()+1)+1+1+4+4+4+4+1);
653
654    recv_data >> levelmin >> levelmax;
655    recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory;
656    recv_data >> quality >> usable;
657
658    Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER);
659    if (!pCreature)
660    {
661        sLog.outDebug( "WORLD: HandleAuctionListItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) );
662        return;
663    }
664
665    // remove fake death
666    if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
667        GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
668
669    location = AuctioneerFactionToLocation(pCreature->getFaction());
670    AuctionHouseObject * mAuctions;
671    mAuctions = objmgr.GetAuctionsMap( location );
672
673    //sLog.outDebug("Auctionhouse search guid: " I64FMTD ", list from: %u, searchedname: %s, levelmin: %u, levelmax: %u, auctionSlotID: %u, auctionMainCategory: %u, auctionSubCategory: %u, quality: %u, usable: %u", guid, listfrom, searchedname.c_str(), levelmin, levelmax, auctionSlotID, auctionMainCategory, auctionSubCategory, quality, usable);
674
675    WorldPacket data( SMSG_AUCTION_LIST_RESULT, (4+4+4) );
676    count = 0;
677    totalcount = 0;
678    data << (uint32) 0;
679
680    // converting string that we try to find to lower case
681    std::wstring wsearchedname;
682    if(!Utf8toWStr(searchedname,wsearchedname))
683        return;
684
685    wstrToLower(wsearchedname);
686
687    for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr)
688    {
689        AuctionEntry *Aentry = itr->second;
690        Item *item = objmgr.GetAItem(Aentry->item_guidlow);
691        if( item )
692        {
693            ItemPrototype const *proto = item->GetProto();
694            if( proto )
695            {
696                if( auctionMainCategory == (0xffffffff) || proto->Class == auctionMainCategory )
697                {
698                    if( auctionSubCategory == (0xffffffff) || proto->SubClass == auctionSubCategory )
699                    {
700                        if( auctionSlotID == (0xffffffff) || proto->InventoryType == auctionSlotID )
701                        {
702                            if( quality == (0xffffffff) || proto->Quality == quality )
703                            {
704                                if( usable == (0x00) || _player->CanUseItem( item ) == EQUIP_ERR_OK )
705                                {
706                                    if( ( levelmin == (0x00) || proto->RequiredLevel >= levelmin ) && ( levelmax == (0x00) || proto->RequiredLevel <= levelmax ) )
707                                    {
708                                        name = proto->Name1;
709
710                                        // local name
711                                        int loc_idx = GetSessionDbLocaleIndex();
712                                        if ( loc_idx >= 0 )
713                                        {
714                                            ItemLocale const *il = objmgr.GetItemLocale(proto->ItemId);
715                                            if (il)
716                                            {
717                                                if (il->Name.size() > loc_idx && !il->Name[loc_idx].empty())
718                                                    name = il->Name[loc_idx];
719                                            }
720                                        }
721
722                                        if(name.empty())
723                                            continue;
724
725                                        if( wsearchedname.empty() || Utf8FitTo(name, wsearchedname) )
726                                        {
727                                            if ((count < 50) && (totalcount >= listfrom))
728                                            {
729                                                ++count;
730                                                SendAuctionInfo( data, Aentry);
731                                            }
732                                            ++totalcount;
733                                        }
734                                    }
735                                }
736                            }
737                        }
738                    }
739                }
740            }
741        }
742    }
743    data.put<uint32>(0, count);
744    data << (uint32) totalcount;
745    data << (uint32) 300;                                   // unk 2.3.0 const?
746    SendPacket(&data);
747}
Note: See TracBrowser for help on using the browser.