//this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_PLACE_BID"); ObjectGuid auctioneer; uint32 auctionId; uint32 price; recvData >> auctioneer; recvData >> auctionId >> price; if (!auctionId || !price) return; //check for cheaters Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionPlaceBid - %s not found or you can't interact with him.", auctioneer.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); if (!auction || auction->owner == player->GetGUID().GetCounter()) { //you cannot bid your own auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // impossible have online own another character (use this for speedup check in case online owner) ObjectGuid ownerGuid(HighGuid::Player, auction->owner); Player* auction_owner = ObjectAccessor::FindPlayer(ownerGuid); if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(ownerGuid) == player->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(0, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // cheating if (price <= auction->bid || price < auction->startbid) 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 (!player->HasEnoughMoney(price)) { //you don't have enought money!, client tests! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (price < auction->buyout || auction->buyout == 0) { if (auction->bidder > 0) { if (auction->bidder == player->GetGUID().GetCounter()) player->ModifyMoney(-int32(price - auction->bid)); else { // mail to last bidder and return money sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); player->ModifyMoney(-int32(price)); } } else player->ModifyMoney(-int32(price)); auction->bidder = player->GetGUID().GetCounter(); auction->bid = price; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID); stmt->setUInt32(0, auction->bidder); stmt->setUInt32(1, auction->bid); stmt->setUInt32(2, auction->Id); trans->Append(stmt); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK, 0); } else { //buyout: if (player->GetGUID().GetCounter() == auction->bidder) player->ModifyMoney(-int32(auction->buyout - auction->bid)); else { player->ModifyMoney(-int32(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = player->GetGUID().GetCounter(); auction->bid = auction->buyout; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, ERR_AUCTION_OK); auction->DeleteFromDB(trans); sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction); } player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData) { TC_LOG_DEBUG("network", "WORLD: Received CMSG_AUCTION_REMOVE_ITEM"); ObjectGuid auctioneer; uint32 auctionId; recvData >> auctioneer; recvData >> auctionId; //TC_LOG_DEBUG("Cancel AUCTION AuctionID: %u", auctionId); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionRemoveItem - %s not found or you can't interact with him.", auctioneer.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction && auction->owner == player->GetGUID().GetCounter()) { Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow); 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 (!player->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans); player->ModifyMoney(-int32(auctionCut)); } // item will deleted or added to received mail list MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELED), AuctionEntry::BuildAuctionMailBody(0, 0, auction->buyout, auction->deposit, 0)) .AddItem(pItem) .SendMailTo(trans, player, auction, MAIL_CHECK_MASK_COPIED); } else { TC_LOG_ERROR("network", "Auction id: %u has non-existed item (item guid : %u)!!!", auction->Id, auction->itemGUIDLow); SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR); return; } } else { SendAuctionCommandResult(0, AUCTION_CANCEL, ERR_AUCTION_DATABASE_ERROR); //this code isn't possible ... maybe there should be assert TC_LOG_ERROR("network", "CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", player->GetGUID().GetCounter(), auctionId); return; } //inform player, that auction is removed SendAuctionCommandResult(auction->Id, AUCTION_CANCEL, ERR_AUCTION_OK); // Now remove the auction player->SaveInventoryAndGoldToDB(trans); auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction); }
//this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) { uint64 auctioneer; uint32 auctionId; uint64 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(LOG_FILTER_NETWORKIO, "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()->RemoveAurasByType(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 || price < auction->startbid) 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 (!pl->HasEnoughMoney((uint32)price)) { //you don't have enought money!, client tests! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); 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 sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); pl->ModifyMoney(-int32(price)); } } else pl->ModifyMoney(-int32(price)); auction->bidder = pl->GetGUIDLow(); auction->bid = price; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); trans->PAppend("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 .. sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = pl->GetGUIDLow(); auction->bid = auction->buyout; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); auction->DeleteFromDB(trans); uint32 item_template = auction->item_template; sAuctionMgr->RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); } pl->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
//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(LOG_FILTER_NETWORKIO, "Cancel AUCTION AuctionID: %u", auctionId); Creature *pCreature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(pCreature->getFaction()); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); 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->HasEnoughMoney(auctionCut)) //player doesn't have enough money, maybe message needed return; //some auctionBidderNotification would be needed, but don't know that parts.. sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans); pl->ModifyMoney(-int32(auctionCut)); } // Return the item by mail std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0"; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body .AddItem(pItem) .SendMailTo(trans, pl, auction, MAIL_CHECK_MASK_COPIED); } 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 pl->SaveInventoryAndGoldToDB(trans); auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); uint32 item_template = auction->item_template; sAuctionMgr->RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction, item_template); }
// this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: HandleAuctionPlaceBid"); ObjectGuid auctioneerGuid; uint32 auctionId; uint32 price; recv_data >> auctioneerGuid; recv_data >> auctionId >> price; if (!auctionId || !price) return; // check for cheaters AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid); if (!auctionHouseEntry) return; // always return pointer AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); 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; } ObjectGuid ownerGuid = ObjectGuid(HIGHGUID_PLAYER, auction->owner); // impossible have online own another character (use this for speedup check in case online owner) Player* auction_owner = sObjectMgr.GetPlayer(ownerGuid); if (!auction_owner && sObjectMgr.GetPlayerAccountIdByGUID(ownerGuid) == 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 || price < auction->startbid) 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 enough 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; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); // after this update we should save player's money ... CharacterDatabase.PExecute("UPDATE auction 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; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_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(); }
// this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) { DEBUG_LOG("WORLD: HandleAuctionRemoveItem"); ObjectGuid auctioneerGuid; uint32 auctionId; recv_data >> auctioneerGuid; recv_data >> auctionId; //DEBUG_LOG( "Cancel AUCTION AuctionID: %u", auctionId); AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid); if (!auctionHouseEntry) return; // always return pointer AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); 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 << ":0:0"; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body .AddItem(pItem) .SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED); } else { sLog.outError("Auction id: %u has nonexistent 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 function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+4+4); 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 = auctionmgr.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 = objmgr.GetPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if( !auction_owner && objmgr.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; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_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; GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); auctionmgr.SendAuctionSalePendingMail( auction ); auctionmgr.SendAuctionSuccessfulMail( auction ); auctionmgr.SendAuctionWonMail( auction ); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); auctionmgr.RemoveAItem(auction->item_guidlow); auctionHouse->RemoveAuction(auction->Id); auction->DeleteFromDB(); delete auction; } CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+4); 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 = auctionmgr.GetAuctionsMap( pCreature->getFaction() ); AuctionEntry *auction = auctionHouse->GetAuction(auctionId); Player *pl = GetPlayer(); if (auction && auction->owner == pl->GetGUIDLow()) { Item *pItem = auctionmgr.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; MailItemsInfo mi; mi.AddItem(auction->item_guidlow, auction->item_template, pItem); // item will deleted or added to received mail list WorldSession::SendMailTo(pl, MAIL_AUCTION, MAIL_STATIONERY_AUCTION, auction->GetHouseId(), pl->GetGUIDLow(), msgAuctionCanceledOwner.str(), 0, &mi, 0, 0, MAIL_CHECK_MASK_NONE); } 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(); auctionmgr.RemoveAItem( auction->item_guidlow ); auctionHouse->RemoveAuction( auction->Id ); delete auction; }
// this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem(WorldPacket& recv_data) { DEBUG_LOG("WORLD: HandleAuctionRemoveItem"); ObjectGuid auctioneerGuid; uint32 auctionId; recv_data >> auctioneerGuid; recv_data >> auctionId; // DEBUG_LOG("Cancel AUCTION AuctionID: %u", auctionId); AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid); if (!auctionHouseEntry) return; // always return pointer AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry); // remove fake death if (GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* pl = GetPlayer(); if (!auction || auction->owner != pl->GetGUIDLow()) { SendAuctionCommandResult(NULL, AUCTION_REMOVED, AUCTION_ERR_DATABASE); sLog.outError("CHEATER : %u, he tried to cancel auction (id: %u) of another player, or auction is NULL", pl->GetGUIDLow(), auctionId); return; } Item* pItem = sAuctionMgr.GetAItem(auction->itemGuidLow); if (!pItem) { sLog.outError("Auction id: %u has nonexistent item (item guid : %u)!!!", auction->Id, auction->itemGuidLow); SendAuctionCommandResult(NULL, AUCTION_REMOVED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND); return; } if (auction->bid) // If we have a bid, 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; if (auction->bidder) // if auction have real existed bidder send mail SendAuctionCancelledToBidderMail(auction); pl->ModifyMoney(-int32(auctionCut)); } // Return the item by mail std::ostringstream msgAuctionCanceledOwner; msgAuctionCanceledOwner << auction->itemTemplate << ":" << auction->itemRandomPropertyId << ":" << AUCTION_CANCELED; // item will deleted or added to received mail list MailDraft(msgAuctionCanceledOwner.str()) .AddItem(pItem) .SendMailTo(pl, auction, MAIL_CHECK_MASK_COPIED); // inform player, that auction is removed SendAuctionCommandResult(auction, AUCTION_REMOVED, AUCTION_OK); // Now remove the auction CharacterDatabase.BeginTransaction(); auction->DeleteFromDB(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); sAuctionMgr.RemoveAItem(auction->itemGuidLow); // used by eluna sHookMgr->OnRemove(auctionHouse); auctionHouse->RemoveAuction(auction->Id); delete auction; }
//this void is called when auction_owner cancels his auction void WorldSession::HandleAuctionRemoveItem(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_REMOVE_ITEM"); ObjectGuid auctioneer; uint32 auctionId; recvData >> auctionId; uint8 bitOrder[8] = { 1, 6, 0, 5, 2, 7, 4, 3 }; recvData.ReadBitInOrder(auctioneer, bitOrder); recvData.FlushBits(); uint8 byteOrder[8] = { 0, 4, 7, 3, 6, 1, 5, 2 }; recvData.ReadBytesSeq(auctioneer, byteOrder); Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (auction && auction->owner == player->GetGUIDLow()) { Item* pItem = sAuctionMgr->GetAItem(auction->itemGUIDLow); 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 (!player->HasEnoughMoney((uint64)auctionCut)) //player doesn't have enough money, maybe message needed return; sAuctionMgr->SendAuctionCancelledToBidderMail(auction, trans, pItem); player->ModifyMoney(-int64(auctionCut)); } // item will deleted or added to received mail list MailDraft(auction->BuildAuctionMailSubject(AUCTION_CANCELED), AuctionEntry::BuildAuctionMailBody(0, 0, auction->buyout, auction->deposit, 0)) .AddItem(pItem) .SendMailTo(trans, player, auction, MAIL_CHECK_MASK_COPIED); } else { sLog->outError(LOG_FILTER_NETWORKIO, "Auction id: %u got non existing item (item guid : %u)!", auction->Id, auction->itemGUIDLow); SendAuctionCommandResult(NULL, AUCTION_CANCEL, 0, ERR_AUCTION_DATABASE_ERROR); return; } } else { SendAuctionCommandResult(NULL, AUCTION_CANCEL, 0, ERR_AUCTION_DATABASE_ERROR); //this code isn't possible ... maybe there should be assert sLog->outError(LOG_FILTER_NETWORKIO, "CHEATER: %u tried to cancel auction (id: %u) of another player or auction is NULL", player->GetGUIDLow(), auctionId); return; } //inform player, that auction is removed SendAuctionCommandResult(auction, AUCTION_CANCEL, ERR_AUCTION_OK); // Now remove the auction player->SaveInventoryAndGoldToDB(trans); auction->DeleteFromDB(trans); CharacterDatabase.CommitTransaction(trans); uint32 itemEntry = auction->itemEntry; sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction, itemEntry); }
// this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket& recvData) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID"); ObjectGuid auctioneer; uint32 auctionId; uint64 price; recvData >> price; recvData >> auctionId; auctioneer[2] = recvData.ReadBit(); auctioneer[5] = recvData.ReadBit(); auctioneer[4] = recvData.ReadBit(); auctioneer[1] = recvData.ReadBit(); auctioneer[0] = recvData.ReadBit(); auctioneer[3] = recvData.ReadBit(); auctioneer[6] = recvData.ReadBit(); auctioneer[7] = recvData.ReadBit(); recvData.FlushBits(); recvData.ReadByteSeq(auctioneer[4]); recvData.ReadByteSeq(auctioneer[7]); recvData.ReadByteSeq(auctioneer[5]); recvData.ReadByteSeq(auctioneer[3]); recvData.ReadByteSeq(auctioneer[6]); recvData.ReadByteSeq(auctioneer[2]); recvData.ReadByteSeq(auctioneer[1]); recvData.ReadByteSeq(auctioneer[0]); if (!auctionId || !price) return; // check for cheaters Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { sLog->outDebug(LOG_FILTER_NETWORKIO, "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_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(auctionId); Player* player = GetPlayer(); if (!auction || auction->owner == player->GetGUIDLow()) { //you cannot bid your own auction: SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, 0, ERR_AUCTION_BID_OWN); return; } // cheating if (price <= auction->bid || price < auction->startbid) return; // price too low for next bid if not buyout if ((price < auction->buyout || auction->buyout == 0) && price < auction->bid + auction->GetAuctionOutBid()) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, 0, ERR_AUCTION_HIGHER_BID); return; } if (!player->HasEnoughMoney(price)) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, 0, ERR_AUCTION_NOT_ENOUGH_MONEY); return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (price < auction->buyout || auction->buyout == 0) { if (auction->bidder > 0) { if (auction->bidder == player->GetGUIDLow()) player->ModifyMoney(-int64(price - auction->bid)); else { // mail to last bidder and return money sAuctionMgr->SendAuctionOutbiddedMail(auction, price, GetPlayer(), trans); player->ModifyMoney(-int64(price)); } } else player->ModifyMoney(-int64(price)); auction->bidder = player->GetGUIDLow(); auction->bid = price; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, price); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID); stmt->setUInt32(0, auction->bidder); stmt->setUInt32(1, auction->bid); stmt->setUInt32(2, auction->Id); trans->Append(stmt); SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK); } else { //buyout: if (player->GetGUIDLow() == auction->bidder) player->ModifyMoney(-int64(auction->buyout - auction->bid)); else { player->ModifyMoney(-int64(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = player->GetGUIDLow(); auction->bid = auction->buyout; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK); auction->DeleteFromDB(trans); uint32 itemEntry = auction->itemEntry; sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction, itemEntry); } player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }
static void addNewAuctionBuyerBotBid(Player *AHBplayer, AHBConfig *config, WorldSession *session) { if (!AHBBuyer) return; // Fetches content of selected AH AuctionHouseObject* auctionHouse = objmgr.GetAuctionsMap(config->GetAHID()); AuctionHouseObject::AuctionEntryMap::iterator itr; itr = auctionHouse->GetAuctionsBegin(); vector<uint32> possibleBids; while (itr != auctionHouse->GetAuctionsEnd()) { AuctionHouseObject::AuctionEntryMap::iterator tmp = itr; ++itr; // Check if the auction is ours // if it is, we skip this iteration. if(tmp->second->owner == AHBplayerGUID) { continue; } // Check that we haven't bidded in this auction already. if(tmp->second->bidder != AHBplayerGUID) { uint32 tmpdata = tmp->second->Id; possibleBids.push_back(tmpdata); } } // Do we have anything to bid? If not, stop here. if(possibleBids.empty()) { return; } // Choose random auction from possible auctions uint32 auctionID = possibleBids[urand(0, possibleBids.size() - 1)]; // from auctionhouse.cpp, creates auction pointer & player pointer AuctionEntry* auction = auctionHouse->GetAuction(auctionID); // get exact item information Item *pItem = objmgr.GetAItem(auction->item_guidlow); if (!pItem) { sLog.outError("Item doesn't exists, perhaps bought already?"); return; } // get item prototype ItemPrototype const* prototype = objmgr.GetItemPrototype(auction->item_template); // check which price we have to use, startbid or if it is bidded already if(debug_Out) {sLog.outError("Auction Number: %u", auction->Id);} if(debug_Out) {sLog.outError("Item Template: %u", auction->item_template);} if(debug_Out) {sLog.outError("Buy Price: %u", prototype->BuyPrice);} if(debug_Out) {sLog.outError("Sell Price: %u", prototype->SellPrice);} if(debug_Out) {sLog.outError("Quality: %u", prototype->Quality);} uint32 currentprice; if(auction->bid) { currentprice = auction->bid; if(debug_Out) {sLog.outError("Current Price: %u", auction->bid);} } else { currentprice = auction->startbid; if(debug_Out) {sLog.outError("Current Price: %u", auction->startbid);} } uint32 bidprice; // Prepare portion from maximum bid uint32 tmprate2 = urand(0, 100); double tmprate = static_cast<double>(tmprate2); if(debug_Out) {sLog.outError("tmprate: %f", tmprate);} double bidrate = tmprate / 100; if(debug_Out) {sLog.outError("bidrate: %f", bidrate);} long double bidMax = 0; // check that bid has acceptable value and take bid based on vendorprice, stacksize and quality switch (BuyMethod) { case 0: switch (prototype->Quality) { case 0: if(currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREY)) { bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREY); } break; case 1: if(currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_WHITE)) { bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_WHITE); } break; case 2: if(currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREEN)) { bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREEN); } break; case 3: if(currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_BLUE)) { bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_BLUE); } break; case 4: if(currentprice < prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_PURPLE)) { bidMax = prototype->SellPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_PURPLE); } break; default: // quality is something it shouldn't be, let's get out of here if(debug_Out) {sLog.outError("bidMax(fail): %f", bidMax);} return; break; } break; case 1: switch (prototype->Quality) { case 0: if(currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREY)) { bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREY); } break; case 1: if(currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_WHITE)) { bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_WHITE); } break; case 2: if(currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREEN)) { bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_GREEN); } break; case 3: if(currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_BLUE)) { bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_BLUE); } break; case 4: if(currentprice < prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_PURPLE)) { bidMax = prototype->BuyPrice * pItem->GetCount() * config->GetBuyerPrice(AHB_PURPLE); } break; default: // quality is something it shouldn't be, let's get out of here if(debug_Out) {sLog.outError("bidMax(fail): %f", bidMax);} return; break; } break; default: bidMax = 0; break; } if(debug_Out) {sLog.outError("bidMax(succeed): %f", bidMax);} // check some special items, and do recalculating to their prices switch (prototype->Class) { // ammo case 6: bidMax = 0; break; default: break; } if(bidMax == 0) { // quality check failed to get bidmax, let's get out of here return; } // Calculate our bid long double bidvalue = currentprice + ( (bidMax - currentprice) * bidrate); if(debug_Out) {sLog.outError("bidvalue: %f", bidvalue);} // Convert to uint32 bidprice = static_cast<uint32>(bidvalue); if(debug_Out) {sLog.outError("bidprice: %u", bidprice);} // Check our bid is high enough to be valid. If not, correct it to minimum. if((currentprice + objmgr.GetAuctionOutBid(currentprice)) > bidprice) { bidprice = currentprice + objmgr.GetAuctionOutBid(currentprice); if(debug_Out) {sLog.outError("bidprice(>): %u", bidprice);} } // Check wether we do normal bid, or buyout if ((bidprice < auction->buyout) || (auction->buyout == 0)) { if (auction->bidder > 0) { if ( auction->bidder == AHBplayer->GetGUIDLow() ) { //pl->ModifyMoney( -int32(price - auction->bid)); } else { // mail to last bidder and return money session->SendAuctionOutbiddedMail( auction , bidprice ); //pl->ModifyMoney( -int32(price) ); } } auction->bidder = AHBplayer->GetGUIDLow(); auction->bid = bidprice; // Saving auction into database CharacterDatabase.PExecute("UPDATE auctionhouse SET buyguid = '%u',lastbid = '%u' WHERE id = '%u'", auction->bidder, auction->bid, auction->Id); } else { //buyout if (AHBplayer->GetGUIDLow() == auction->bidder ) { //pl->ModifyMoney(-int32(auction->buyout - auction->bid)); } else { //pl->ModifyMoney(-int32(auction->buyout)); if ( auction->bidder ) { session->SendAuctionOutbiddedMail( auction, auction->buyout ); } } auction->bidder = AHBplayer->GetGUIDLow(); auction->bid = auction->buyout; // Send mails to buyer & seller objmgr.SendAuctionSuccessfulMail( auction ); objmgr.SendAuctionWonMail( auction ); // Remove item from auctionhouse objmgr.RemoveAItem(auction->item_guidlow); // Remove auction auctionHouse->RemoveAuction(auction->Id); // Remove from database CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id); delete auction; } }
// this function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPackets::AuctionHouse::AuctionPlaceBid& packet) { if (!packet.AuctionItemID || !packet.BidAmount) return; // check for cheaters Creature* creature = GetPlayer()->GetNPCIfCanInteractWith(packet.Auctioneer, UNIT_NPC_FLAG_AUCTIONEER); if (!creature) { TC_LOG_DEBUG("network", "WORLD: HandleAuctionPlaceBid - %s not found or you can't interact with him.", packet.Auctioneer.ToString().c_str()); return; } // remove fake death if (GetPlayer()->HasUnitState(UNIT_STATE_DIED)) GetPlayer()->RemoveAurasByType(SPELL_AURA_FEIGN_DEATH); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(creature->getFaction()); AuctionEntry* auction = auctionHouse->GetAuction(packet.AuctionItemID); Player* player = GetPlayer(); if (!auction || auction->owner == player->GetGUID().GetCounter()) { //you cannot bid your own auction: SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // impossible have online own another character (use this for speedup check in case online owner) ObjectGuid ownerGuid = ObjectGuid::Create<HighGuid::Player>(auction->owner); Player* auction_owner = ObjectAccessor::FindPlayer(ownerGuid); if (!auction_owner && ObjectMgr::GetPlayerAccountIdByGUID(ownerGuid) == player->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(NULL, AUCTION_PLACE_BID, ERR_AUCTION_BID_OWN); return; } // cheating if (packet.BidAmount <= auction->bid || packet.BidAmount < auction->startbid) return; // price too low for next bid if not buyout if ((packet.BidAmount < auction->buyout || auction->buyout == 0) && packet.BidAmount < auction->bid + auction->GetAuctionOutBid()) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_HIGHER_BID); return; } if (!player->HasEnoughMoney(packet.BidAmount)) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_NOT_ENOUGHT_MONEY); return; } SQLTransaction trans = CharacterDatabase.BeginTransaction(); if (packet.BidAmount < auction->buyout || auction->buyout == 0) { if (auction->bidder) { if (auction->bidder == player->GetGUID().GetCounter()) player->ModifyMoney(-int64(packet.BidAmount - auction->bid)); else { // mail to last bidder and return money sAuctionMgr->SendAuctionOutbiddedMail(auction, packet.BidAmount, GetPlayer(), trans); player->ModifyMoney(-int64(packet.BidAmount)); } } else player->ModifyMoney(-int64(packet.BidAmount)); auction->bidder = player->GetGUID().GetCounter(); auction->bid = packet.BidAmount; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, packet.BidAmount); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_AUCTION_BID); stmt->setUInt64(0, auction->bidder); stmt->setUInt32(1, auction->bid); stmt->setUInt32(2, auction->Id); trans->Append(stmt); SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK); // Not sure if we must send this now. Player* owner = sObjectAccessor->FindConnectedPlayer(ObjectGuid::Create<HighGuid::Player>(auction->owner)); Item* item = sAuctionMgr->GetAItem(auction->itemGUIDLow); if (owner && item) owner->GetSession()->SendAuctionOwnerBidNotification(auction, item); } else { //buyout: if (player->GetGUID().GetCounter() == auction->bidder) player->ModifyMoney(-int64(auction->buyout - auction->bid)); else { player->ModifyMoney(-int64(auction->buyout)); if (auction->bidder) //buyout for bidded auction .. sAuctionMgr->SendAuctionOutbiddedMail(auction, auction->buyout, GetPlayer(), trans); } auction->bidder = player->GetGUID().GetCounter(); auction->bid = auction->buyout; GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID, auction->buyout); SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_OK); //- Mails must be under transaction control too to prevent data loss sAuctionMgr->SendAuctionSalePendingMail(auction, trans); sAuctionMgr->SendAuctionSuccessfulMail(auction, trans); sAuctionMgr->SendAuctionWonMail(auction, trans); auction->DeleteFromDB(trans); sAuctionMgr->RemoveAItem(auction->itemGUIDLow); auctionHouse->RemoveAuction(auction); } player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); }