// 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) { 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()->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(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("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()->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(NULL, AUCTION_BID_PLACED, AUCTION_ERR_BID_OWN); 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(NULL, AUCTION_BID_PLACED, AUCTION_ERR_BID_OWN); return; } // cheating or client lags if (price <= auction->bid) { // client test but possible in result lags SendAuctionCommandResult(auction, AUCTION_BID_PLACED, AUCTION_ERR_HIGHER_BID); return; } // price too low for next bid if not buyout if ((price < auction->buyout || auction->buyout == 0) && price < auction->bid + auction->GetAuctionOutBid()) { // client test but possible in result lags SendAuctionCommandResult(auction, AUCTION_BID_PLACED, AUCTION_ERR_BID_INCREMENT); return; } if (price > pl->GetMoney()) { // you don't have enough money!, client tests! // SendAuctionCommandResult(auction->auctionId, AUCTION_ERR_INVENTORY, EQUIP_ERR_NOT_ENOUGH_MONEY); return; } // cheating if (price < auction->startbid) return; SendAuctionCommandResult(auction, AUCTION_BID_PLACED, AUCTION_OK); auction->UpdateBid(price, pl); }
// 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); auctionHouse->RemoveAuction(auction->Id); delete auction; }
// 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"); uint64 auctioneer; uint32 auctionId; uint64 price; recvData >> auctioneer; recvData >> auctionId; recvData >> price; 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, ERR_AUCTION_BID_OWN); return; } // impossible have online own another character (use this for speedup check in case online owner) /*Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == player->GetSession()->GetAccountId()) { //you cannot bid your another character auction: SendAuctionCommandResult(NULL, 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()) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_HIGHER_BID); return; } if (!player->HasEnoughMoney(price)) { // client already test it but just in case ... SendAuctionCommandResult(auction, AUCTION_PLACE_BID, ERR_AUCTION_NOT_ENOUGHT_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); }
//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"); uint64 auctioneer; uint32 auctionId; recvData >> auctioneer; recvData >> auctionId; 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, ERR_AUCTION_DATABASE_ERROR); return; } } else { SendAuctionCommandResult(NULL, AUCTION_CANCEL, 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 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 = ObjectAccessor::GetNPCIfCanInteractWith(*_player, 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); uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject * mAuctions; mAuctions = objmgr.GetAuctionsMap( location ); AuctionEntry *auction = mAuctions->GetAuction(auctionId); Player *pl = GetPlayer(); if (auction && auction->owner == pl->GetGUIDLow()) { Item *pItem = objmgr.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 = objmgr.GetAuctionCut( auction->location, auction->bid); 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->location, 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(); CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); objmgr.RemoveAItem( auction->item_guidlow ); mAuctions->RemoveAuction( auction->Id ); delete auction; }
//called when player lists his bids void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data ) { CHECK_PACKET_SIZE(recv_data,8+4+4); uint64 guid; //NPC guid uint32 listfrom; //page of auctions uint32 outbiddedCount; //count of outbidded auctions recv_data >> guid; recv_data >> listfrom; // not used in fact (this list not have page control in client) recv_data >> outbiddedCount; if (recv_data.size() != (16 + outbiddedCount * 4 )) { sLog.outError("Client sent bad opcode!!! with count: %u and size : %d (mustbe: %d", outbiddedCount, recv_data.size(),(16 + outbiddedCount * 4 )); outbiddedCount = 0; } Creature *pCreature = ObjectAccessor::GetNPCIfCanInteractWith(*_player, guid,UNIT_NPC_FLAG_AUCTIONEER); if (!pCreature) { sLog.outDebug( "WORLD: HandleAuctionListBidderItems - Unit (GUID: %u) not found or you can't interact with him.", uint32(GUID_LOPART(guid)) ); return; } // remove fake death if(GetPlayer()->hasUnitState(UNIT_STAT_DIED)) GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH); uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject* mAuctions = objmgr.GetAuctionsMap( location ); WorldPacket data( SMSG_AUCTION_BIDDER_LIST_RESULT, (4+4+4) ); Player *pl = GetPlayer(); data << (uint32) 0; //add 0 as count uint32 count = 0; uint32 totalcount = 0; while ( outbiddedCount > 0) //add all data, which client requires { --outbiddedCount; uint32 outbiddedAuctionId; recv_data >> outbiddedAuctionId; AuctionEntry * auction = mAuctions->GetAuction( outbiddedAuctionId ); if ( auction && SendAuctionInfo(data, auction)) { ++totalcount; ++count; } } for (AuctionHouseObject::AuctionEntryMap::iterator itr = mAuctions->GetAuctionsBegin();itr != mAuctions->GetAuctionsEnd();++itr) { AuctionEntry *Aentry = itr->second; if( Aentry && Aentry->bidder == pl->GetGUIDLow() ) { if (SendAuctionInfo(data, itr->second)) ++count; ++totalcount; } } data.put<uint32>( 0, count ); // add count to placeholder data << totalcount; data << (uint32)300; //unk 2.3.0 SendPacket(&data); }
//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 = ObjectAccessor::GetNPCIfCanInteractWith(*_player, 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); uint32 location = AuctioneerFactionToLocation(pCreature->getFaction()); AuctionHouseObject * mAuctions; mAuctions = objmgr.GetAuctionsMap( location ); AuctionEntry *auction = mAuctions->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; } if (price < (auction->bid + objmgr.GetAuctionOutBid(auction->bid))) { //auction has already higher bid, client tests it! //SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???); 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; objmgr.SendAuctionSalePendingMail( auction ); objmgr.SendAuctionSuccessfulMail( auction ); objmgr.SendAuctionWonMail( auction ); SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK); objmgr.RemoveAItem(auction->item_guidlow); mAuctions->RemoveAuction(auction->Id); CharacterDatabase.PExecute("DELETE FROM auctionhouse WHERE id = '%u'",auction->Id); delete auction; } CharacterDatabase.BeginTransaction(); pl->SaveInventoryAndGoldToDB(); CharacterDatabase.CommitTransaction(); }
//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->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(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->GetGUIDLow(), 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& 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 function is called when client bids or buys out auction void WorldSession::HandleAuctionPlaceBid(WorldPacket & recv_data) { sLog->outDebug(LOG_FILTER_NETWORKIO, "WORLD: Received CMSG_AUCTION_PLACE_BID"); uint64 auctioneer; uint32 auctionId; uint32 priceTmp; uint64 price; recv_data >> auctioneer; recv_data >> auctionId >> priceTmp; price = priceTmp; 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_STAT_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(0, AUCTION_PLACE_BID, ERR_AUCTION_DATABASE_ERROR); return; } // impossible have online own another character (use this for speedup check in case online owner) Player* auction_owner = ObjectAccessor::FindPlayer(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)); if (!auction_owner && sObjectMgr->GetPlayerAccountIdByGUID(MAKE_NEW_GUID(auction->owner, 0, HIGHGUID_PLAYER)) == 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->GetGUIDLow()) 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->GetGUIDLow(); auction->bid = (price >> 32); 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 (player->GetGUIDLow() == auction->bidder)
// Tries to bid and buy items based on their prices and chances set in configs void AuctionBotBuyer::BuyAndBidItems(BuyerConfiguration& config) { time_t now = time(nullptr); AuctionHouseObject* auctionHouse = sAuctionMgr->GetAuctionsMap(config.GetHouseType()); CheckEntryMap& items = config.EligibleItems; // Max amount of items to buy or bid uint32 cycles = sAuctionBotConfig->GetItemPerCycleNormal(); if (items.size() > sAuctionBotConfig->GetItemPerCycleBoost()) { // set more cycles if there is a huge influx of items cycles = sAuctionBotConfig->GetItemPerCycleBoost(); TC_LOG_DEBUG("ahbot", "AHBot: Boost value used for Buyer! (if this happens often adjust both ItemsPerCycle in worldserver.conf)"); } // Process items eligible to be bidded or bought CheckEntryMap::iterator itr = items.begin(); while (cycles && itr != items.end()) { AuctionEntry* auction = auctionHouse->GetAuction(itr->second.AuctionId); if (!auction) { TC_LOG_DEBUG("ahbot", "AHBot: Entry %u doesn't exists, perhaps bought already?", itr->second.AuctionId); items.erase(itr++); continue; } // Check if the item has been checked once before // If it has been checked and it was recently, skip it if (itr->second.LastChecked && (now - itr->second.LastChecked) <= _checkInterval) { TC_LOG_DEBUG("ahbot", "AHBot: In time interval wait for entry %u!", auction->Id); ++itr; continue; } Item* item = sAuctionMgr->GetAItem(auction->itemGUIDLow); if (!item) { // auction item not accessible, possible auction in payment pending mode items.erase(itr++); continue; } // price to bid if bidding uint32 bidPrice; if (auction->bid >= auction->startbid) { // get bid price to outbid previous bidder bidPrice = auction->bid + auction->GetAuctionOutBid(); } else { // no previous bidders - use starting bid bidPrice = auction->startbid; } const BuyerItemInfo* ahInfo = nullptr; BuyerItemInfoMap::const_iterator sameItemItr = config.SameItemInfo.find(item->GetEntry()); if (sameItemItr != config.SameItemInfo.end()) ahInfo = &sameItemItr->second; TC_LOG_DEBUG("ahbot", "AHBot: Rolling for AHentry %u:", auction->Id); // Roll buy and bid chances bool successBuy = RollBuyChance(ahInfo, item, auction, bidPrice); bool successBid = RollBidChance(ahInfo, item, auction, bidPrice); // If roll bidding succesfully and bid price is above buyout -> buyout // If roll for buying was successful but not for bid, buyout directly // If roll bidding was also successful, buy the entry with 20% chance // - Better bid than buy since the item is bought by bot if no player bids after // Otherwise bid if roll for bid was successful if ((auction->buyout && successBid && bidPrice >= auction->buyout) || (successBuy && (!successBid || urand(1, 5) == 1))) BuyEntry(auction, auctionHouse); // buyout else if (successBid) PlaceBidToEntry(auction, bidPrice); // bid itr->second.LastChecked = now; --cycles; ++itr; } // Clear not needed entries config.SameItemInfo.clear(); }