//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) { uint64 auctioneer; uint32 auctionId; recv_data >> auctioneer; recv_data >> auctionId; //sLog.outDebug( "Cancel AUCTION AuctionID: %u", auctionId); Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionRemoveItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap( pCreature->getFaction() ); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); if (auction && auction->owner == pl->GetGUIDLow()) { Item *pItem = sAuctionMgr.GetAItem(auction->item_guidlow); if (pItem) { if (auction->bidder > 0) // If we have a bidder, we have to send him the money he paid { uint32 auctionCut = auction->GetAuctionCut(); if ( pl->GetMoney() < auctionCut ) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. SendAuctionCancelledToBidderMail( auction ); pl->ModifyMoney( -int32(auctionCut) ); } // Return the item by mail std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str()) .AddItem(pItem) .SendMailTo(pl, auction); } else { sLog.outError("Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->item_guidlow); SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR ); return; } } else { SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR ); //this code isn't possible ... maybe there should be assert sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId ); return; } //inform player, that auction is removed SendAuctionCommandResult( auction->Id, AUCTION_CANCEL, AUCTION_OK ); // Now remove the auction CharacterDatabase.BeginTransaction(); auction->DeleteFromDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); sAuctionMgr.RemoveAItem( auction->item_guidlow ); auctionHouse->RemoveAuction( auction->Id ); delete auction; }
//this void creates new auction and adds auction to some auctionhouse void WorldSession::HandleAuctionSellItem(WorldPacket & recv_data) { uint64 auctioneer, item; uint32 etime, bid, buyout; recv_data >> auctioneer >> item; recv_data >> bid >> buyout >> etime; Player *pl = GetPlayer(); if (!item || !bid || !etime) return; //check for cheaters Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer))); return; } AuctionHouseEntry const* auctionHouseEntry = AuctionHouseMgr::GetAuctionHouseEntry(pCreature->getFaction()); if (!auctionHouseEntry) { sLog.outDebug("WORLD: HandleAuctionSellItem - Unit (GUID: %u) has wrong faction.", uint32(GUID_LOPART(auctioneer))); return; } sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); // client send time in minutes, convert to common used sec time etime *= MINUTE; sLog.outDebug("WORLD: HandleAuctionSellItem - ETIME: %u", etime); // client understand only 3 auction time switch(etime) { case 1*MIN_AUCTION_TIME: case 2*MIN_AUCTION_TIME: case 4*MIN_AUCTION_TIME: break; default: return; } // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); Item *it = pl->GetItemByGuid(item); //do not allow to sell already auctioned items if (auctionmgr.GetAItem(GUID_LOPART(item))) { sLog.outError("AuctionError, player %s is sending item id: %u, but item is already in another auction", pl->GetName(), GUID_LOPART(item)); SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } // prevent sending bag with items (cheat: can be placed in bag after adding equiped empty bag to auction) if (!it) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_ITEM_NOT_FOUND); return; } if (!it->CanBeTraded()) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } if (it->HasFlag(ITEM_FIELD_FLAGS, ITEM_FLAGS_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION)) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR); return; } AuctionHouseObject* auctionHouse = auctionmgr.GetAuctionsMap(pCreature->getFaction()); //we have to take deposit : uint32 deposit = auctionmgr.GetAuctionDeposit(auctionHouseEntry, etime, it); if (pl->GetMoney() < deposit) { SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_NOT_ENOUGHT_MONEY); return; } if (GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE)) { sLog.outCommand(GetAccountId(),"GM %s (Account: %u) create auction: %s (Entry: %u Count: %u)", GetPlayerName(),GetAccountId(),it->GetProto()->Name1,it->GetEntry(),it->GetCount()); } pl->ModifyMoney(-int32(deposit)); uint32 auction_time = uint32(etime * sWorld.getRate(RATE_AUCTION_TIME)); AuctionEntry *AH = new AuctionEntry; AH->Id = objmgr.GenerateAuctionID(); if (sWorld.getConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION)) AH->auctioneer = 23442; else AH->auctioneer = GUID_LOPART(auctioneer); AH->item_guidlow = GUID_LOPART(item); AH->item_template = it->GetEntry(); AH->owner = pl->GetGUIDLow(); AH->startbid = bid; AH->bidder = 0; AH->bid = 0; AH->buyout = buyout; AH->expire_time = time(NULL) + auction_time; AH->deposit = deposit; AH->auctionHouseEntry = auctionHouseEntry; sLog.outDetail("selling item %u to auctioneer %u with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u", GUID_LOPART(item), AH->auctioneer, bid, buyout, auction_time, AH->GetHouseId()); auctionmgr.AddAItem(it); auctionHouse->AddAuction(AH); pl->MoveItemFromInventory(it->GetBagSlot(), it->GetSlot(), true); CharacterDatabase.BeginTransaction(); it->DeleteFromInventoryDB(); it->SaveToDB(); // recursive and not have transaction guard into self, not in inventiory and can be save standalone AH->SaveToDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); SendAuctionCommandResult(AH->Id, AUCTION_SELL_ITEM, AUCTION_OK); }
//this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) { uint64 auctioneer; uint32 auctionId; uint32 price; recv_data >> auctioneer; recv_data >> auctionId >> price; if (!auctionId || !price) return; //check for cheaters Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionPlaceBid - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(auctioneer)) ); return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap( pCreature->getFaction() ); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); if( !auction || auction->owner == pl->GetGUIDLow() ) { //you cannot bid your own auction: SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR ); return; } // impossible have online own another character (use this for speedup check in case online owner) Player* auction_owner = sObjectMgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if( !auction_owner && sObjectMgr.GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == pl->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult( 0, AUCTION_PLACE_BID, CANNOT_BID_YOUR_AUCTION_ERROR ); return; } // cheating if(price <= auction->bid) return; // price too low for next bid if not buyout if ((price < auction->buyout || auction->buyout == 0) && price < auction->bid + auction->GetAuctionOutBid()) { //auction has already higher bid, client tests it! return; } if (price > pl->GetMoney()) { //you don't have enought money!, client tests! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } if ((price < auction->buyout) || (auction->buyout == 0)) { if (auction->bidder > 0) { if ( auction->bidder == pl->GetGUIDLow() ) { pl->ModifyMoney( -int32(price - auction->bid)); } else { // mail to last bidder and return money SendAuctionOutbiddedMail( auction , price ); pl->ModifyMoney( -int32(price) ); } } else { pl->ModifyMoney( -int32(price) ); } auction->bidder = pl->GetGUIDLow(); auction->bid = price; // after this update we should save player's money ... CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK, 0 ); } else { //buyout: if (pl->GetGUIDLow() == auction->bidder ) { pl->ModifyMoney(-int32(auction->buyout - auction->bid)); } else { pl->ModifyMoney(-int32(auction->buyout)); if ( auction->bidder ) //buyout for bidded auction .. { SendAuctionOutbiddedMail( auction, auction->buyout ); } } auction->bidder = pl->GetGUIDLow(); auction->bid = auction->buyout; sAuctionMgr.SendAuctionSalePendingMail( auction ); sAuctionMgr.SendAuctionSuccessfulMail( auction ); sAuctionMgr.SendAuctionWonMail( auction ); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); sAuctionMgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction->Id); auction->DeleteFromDB(); delete auction; } CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }