mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 22:37:03 +00:00
[11391] Auction: multi sell, sale pending list and other fixes.
This commit is contained in:
parent
730a907252
commit
e39a8b55a0
8 changed files with 415 additions and 256 deletions
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
DROP TABLE IF EXISTS `character_db_version`;
|
||||
CREATE TABLE `character_db_version` (
|
||||
`required_11299_02_characters_pet_aura` bit(1) default NULL
|
||||
`required_11391_01_characters_auction` bit(1) default NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
|
||||
|
||||
--
|
||||
|
|
|
|||
4
sql/updates/11391_01_characters_auction.sql
Normal file
4
sql/updates/11391_01_characters_auction.sql
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
ALTER TABLE character_db_version CHANGE COLUMN required_11299_02_characters_pet_aura required_11391_01_characters_auction bit;
|
||||
|
||||
ALTER TABLE `auction`
|
||||
ADD COLUMN `moneyTime` BIGINT(40) DEFAULT '0' NOT NULL AFTER `time`;
|
||||
|
|
@ -67,47 +67,100 @@ void WorldSession::SendAuctionHello(Unit* unit)
|
|||
}
|
||||
|
||||
// call this method when player bids, creates, or deletes auction
|
||||
void WorldSession::SendAuctionCommandResult(uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError )
|
||||
void WorldSession::SendAuctionCommandResult(AuctionEntry *auc, AuctionAction Action, AuctionError ErrorCode, InventoryResult invError )
|
||||
{
|
||||
WorldPacket data( SMSG_AUCTION_COMMAND_RESULT, 16 );
|
||||
data << uint32(auctionId);
|
||||
data << uint32(auc ? auc->Id : 0);
|
||||
data << uint32(Action);
|
||||
data << uint32(ErrorCode);
|
||||
if ( !ErrorCode && Action )
|
||||
data << uint32(bidError); // when bid, then send 0, once...
|
||||
|
||||
switch(ErrorCode)
|
||||
{
|
||||
case AUCTION_OK:
|
||||
if(Action == AUCTION_BID_PLACED)
|
||||
data << uint32(auc->GetAuctionOutBid()); // new AuctionOutBid?
|
||||
break;
|
||||
case AUCTION_ERR_INVENTORY:
|
||||
data << uint32(invError);
|
||||
break;
|
||||
case AUCTION_ERR_HIGHER_BID:
|
||||
data << ObjectGuid(HIGHGUID_PLAYER,auc->bidder);// new bidder guid
|
||||
data << uint32(auc->bid); // new bid
|
||||
data << uint32(auc->GetAuctionOutBid()); // new AuctionOutBid?
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
// this function sends notification, if bidder is online
|
||||
void WorldSession::SendAuctionBidderNotification( uint32 location, uint32 auctionId, ObjectGuid bidderGuid, uint32 bidSum, uint32 diff, uint32 item_template)
|
||||
void WorldSession::SendAuctionBidderNotification(AuctionEntry* auction)
|
||||
{
|
||||
WorldPacket data(SMSG_AUCTION_BIDDER_NOTIFICATION, (8*4));
|
||||
data << uint32(location);
|
||||
data << uint32(auctionId);
|
||||
data << bidderGuid;
|
||||
data << uint32(bidSum);
|
||||
data << uint32(diff);
|
||||
data << uint32(item_template);
|
||||
data << uint32(0);
|
||||
data << uint32(auction->GetHouseId());
|
||||
data << uint32(auction->Id);
|
||||
data << ObjectGuid(HIGHGUID_PLAYER, auction->bidder);
|
||||
|
||||
// if 0, client shows ERR_AUCTION_WON_S, else ERR_AUCTION_OUTBID_S
|
||||
data << uint32(auction->moneyDeliveryTime ? 0 : auction->bid);
|
||||
data << uint32(auction->GetAuctionOutBid()); // AuctionOutBid?
|
||||
data << uint32(auction->itemTemplate);
|
||||
|
||||
Item *item = sAuctionMgr.GetAItem(auction->itemGuidLow);
|
||||
uint32 randomId = item ? item->GetItemRandomPropertyId() : 0;
|
||||
|
||||
data << uint32(randomId); // random property (value > 0) or suffix (value < 0)
|
||||
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
// this void causes on client to display: "Your auction sold"
|
||||
void WorldSession::SendAuctionOwnerNotification( AuctionEntry* auction)
|
||||
void WorldSession::SendAuctionOwnerNotification(AuctionEntry* auction)
|
||||
{
|
||||
WorldPacket data(SMSG_AUCTION_OWNER_NOTIFICATION, (7*4));
|
||||
data << uint32(auction->Id);
|
||||
data << uint32(auction->bid);
|
||||
data << uint32(0); // unk
|
||||
data << uint32(0); // unk
|
||||
data << uint32(0); // unk
|
||||
data << uint32(auction->item_template);
|
||||
data << uint32(0); // unk
|
||||
data << uint32(auction->bid); // if 0, client shows ERR_AUCTION_EXPIRED_S, else ERR_AUCTION_SOLD_S (works only when guid==0)
|
||||
data << uint32(auction->GetAuctionOutBid()); // AuctionOutBid?
|
||||
|
||||
ObjectGuid guid = ObjectGuid();
|
||||
if(!auction->moneyDeliveryTime) // not sold yet
|
||||
guid = ObjectGuid(HIGHGUID_PLAYER, auction->bidder);// bidder==0 and moneyDeliveryTime==0 for expired auctions, so it will show error message properly
|
||||
|
||||
// if guid!=0, client updates auctions with new bid, outbid and bidderGuid, else it shows error messages as described above
|
||||
data << guid; // bidder guid
|
||||
data << uint32(auction->itemTemplate); // item entry
|
||||
|
||||
Item *item = sAuctionMgr.GetAItem(auction->itemGuidLow);
|
||||
uint32 randomId = item ? item->GetItemRandomPropertyId() : 0;
|
||||
|
||||
data << uint32(randomId); // random property (value > 0) or suffix (value < 0)
|
||||
|
||||
float timeLeft = float(auction->moneyDeliveryTime - time(NULL)) / float(DAY);
|
||||
|
||||
data << float(timeLeft); // time till money arrive? only used if bid != 0
|
||||
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
// shows ERR_AUCTION_REMOVED_S
|
||||
void WorldSession::SendAuctionRemovedNotification(AuctionEntry* auction)
|
||||
{
|
||||
WorldPacket data(SMSG_AUCTION_REMOVED_NOTIFICATION, (3*4));
|
||||
data << uint32(auction->Id);
|
||||
data << uint32(auction->itemTemplate);
|
||||
|
||||
Item *item = sAuctionMgr.GetAItem(auction->itemGuidLow);
|
||||
uint32 randomId = item ? item->GetItemRandomPropertyId() : 0;
|
||||
|
||||
data << uint32(randomId); // random property (value > 0) or suffix (value < 0)
|
||||
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
// this function sends mail to old bidder
|
||||
void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPrice)
|
||||
void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction)
|
||||
{
|
||||
ObjectGuid oldBidder_guid = ObjectGuid(HIGHGUID_PLAYER, auction->bidder);
|
||||
Player *oldBidder = sObjectMgr.GetPlayer(oldBidder_guid);
|
||||
|
|
@ -120,12 +173,10 @@ void WorldSession::SendAuctionOutbiddedMail(AuctionEntry *auction, uint32 newPri
|
|||
if(oldBidder || oldBidder_accId)
|
||||
{
|
||||
std::ostringstream msgAuctionOutbiddedSubject;
|
||||
msgAuctionOutbiddedSubject << auction->item_template << ":0:" << AUCTION_OUTBIDDED << ":0:0";
|
||||
msgAuctionOutbiddedSubject << auction->itemTemplate << ":0:" << AUCTION_OUTBIDDED << ":0:0";
|
||||
|
||||
if (oldBidder)
|
||||
oldBidder->GetSession()->SendAuctionBidderNotification(
|
||||
auction->GetHouseId(), auction->Id, _player->GetObjectGuid(),
|
||||
newPrice, auction->GetAuctionOutBid(), auction->item_template);
|
||||
oldBidder->GetSession()->SendAuctionBidderNotification(auction);
|
||||
|
||||
MailDraft(msgAuctionOutbiddedSubject.str(), "") // TODO: fix body
|
||||
.SetMoney(auction->bid)
|
||||
|
|
@ -147,7 +198,10 @@ void WorldSession::SendAuctionCancelledToBidderMail( AuctionEntry* auction )
|
|||
if(bidder || bidder_accId)
|
||||
{
|
||||
std::ostringstream msgAuctionCancelledSubject;
|
||||
msgAuctionCancelledSubject << auction->item_template << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0";
|
||||
msgAuctionCancelledSubject << auction->itemTemplate << ":0:" << AUCTION_CANCELLED_TO_BIDDER << ":0:0";
|
||||
|
||||
if(bidder)
|
||||
bidder->GetSession()->SendAuctionRemovedNotification(auction);
|
||||
|
||||
MailDraft(msgAuctionCancelledSubject.str(), "") // TODO: fix body
|
||||
.SetMoney(auction->bid)
|
||||
|
|
@ -193,17 +247,33 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
|
|||
DEBUG_LOG("WORLD: HandleAuctionSellItem");
|
||||
|
||||
ObjectGuid auctioneerGuid;
|
||||
ObjectGuid itemGuid;
|
||||
uint32 etime, bid, buyout;
|
||||
uint32 etime, bid, buyout, itemCount;
|
||||
std::vector<ObjectGuid> guids;
|
||||
std::vector<uint32> stackSizes;
|
||||
|
||||
recv_data >> auctioneerGuid;
|
||||
recv_data.read_skip<uint32>(); // const 1?
|
||||
recv_data >> itemGuid;
|
||||
recv_data.read_skip<uint32>(); // stack size
|
||||
recv_data >> itemCount;
|
||||
|
||||
if(itemCount > MAX_BAG_SIZE * 5)
|
||||
{
|
||||
recv_data.rpos(recv_data.wpos()); // should not happen
|
||||
return;
|
||||
}
|
||||
|
||||
guids.resize(itemCount);
|
||||
stackSizes.resize(itemCount);
|
||||
|
||||
for(uint32 i = 0; i < itemCount; ++i)
|
||||
{
|
||||
recv_data >> guids[i]; // item guid
|
||||
recv_data >> stackSizes[i]; // stack size
|
||||
}
|
||||
|
||||
recv_data >> bid;
|
||||
recv_data >> buyout;
|
||||
recv_data >> etime;
|
||||
|
||||
if (itemGuid.IsEmpty() || !bid || !etime)
|
||||
if (!bid || !etime)
|
||||
return; // check for cheaters
|
||||
|
||||
Player *pl = GetPlayer();
|
||||
|
|
@ -233,81 +303,105 @@ void WorldSession::HandleAuctionSellItem( WorldPacket & recv_data )
|
|||
if(GetPlayer()->hasUnitState(UNIT_STAT_DIED))
|
||||
GetPlayer()->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
|
||||
|
||||
Item *it = pl->GetItemByGuid(itemGuid);
|
||||
// do not allow to sell already auctioned items
|
||||
if (sAuctionMgr.GetAItem(itemGuid.GetCounter()))
|
||||
for(uint32 i = 0; i < itemCount; ++i)
|
||||
{
|
||||
sLog.outError("AuctionError, %s is sending %s, but item is already in another auction", pl->GetGuidStr().c_str(), itemGuid.GetString().c_str());
|
||||
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
|
||||
return;
|
||||
ObjectGuid itemGuid = guids[i];
|
||||
|
||||
if(itemGuid.IsEmpty())
|
||||
continue;
|
||||
|
||||
uint32 stackSize = stackSizes[i];
|
||||
|
||||
Item *it = pl->GetItemByGuid(itemGuid);
|
||||
|
||||
// do not allow to sell already auctioned items
|
||||
if (sAuctionMgr.GetAItem(itemGuid.GetCounter()))
|
||||
{
|
||||
sLog.outError("AuctionError, %s is sending %s, but item is already in another auction", pl->GetGuidStr().c_str(), itemGuid.GetString().c_str());
|
||||
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
|
||||
continue;
|
||||
}
|
||||
|
||||
// prevent sending bag with items (cheat: can be placed in bag after adding equipped empty bag to auction)
|
||||
if(!it)
|
||||
{
|
||||
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_ITEM_NOT_FOUND);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!it->CanBeTraded())
|
||||
{
|
||||
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_CANNOT_TRADE_THAT);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((it->GetProto()->Flags & ITEM_FLAG_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION))
|
||||
{
|
||||
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_INVENTORY, EQUIP_ERR_CANNOT_TRADE_THAT);
|
||||
continue;
|
||||
}
|
||||
|
||||
// check money for deposit
|
||||
uint32 deposit = AuctionHouseMgr::GetAuctionDeposit( auctionHouseEntry, etime, it );
|
||||
if ( pl->GetMoney() < deposit )
|
||||
{
|
||||
SendAuctionCommandResult(NULL, AUCTION_STARTED, AUCTION_ERR_NOT_ENOUGH_MONEY);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_BOOL_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());
|
||||
}
|
||||
|
||||
if(stackSize == 0)
|
||||
stackSize = 1;
|
||||
|
||||
if(stackSize > it->GetMaxStackCount()) // too big stack size
|
||||
stackSize = it->GetMaxStackCount();
|
||||
|
||||
if(!pl->HasItemCount(it->GetEntry(), stackSize)) // not enough items
|
||||
continue;
|
||||
|
||||
Item *newItem = it->CloneItem(stackSize, pl);
|
||||
|
||||
pl->DestroyItemCount(it, stackSize, true);
|
||||
|
||||
pl->ModifyMoney( -int32(deposit) );
|
||||
|
||||
uint32 auction_time = uint32(etime * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME));
|
||||
|
||||
AuctionEntry *AH = new AuctionEntry;
|
||||
AH->Id = sObjectMgr.GenerateAuctionID();
|
||||
AH->itemGuidLow = newItem->GetObjectGuid().GetCounter();
|
||||
AH->itemTemplate = newItem->GetEntry();
|
||||
AH->owner = pl->GetGUIDLow();
|
||||
AH->startbid = bid;
|
||||
AH->bidder = 0;
|
||||
AH->bid = 0;
|
||||
AH->buyout = buyout;
|
||||
AH->expireTime = time(NULL) + auction_time;
|
||||
AH->moneyDeliveryTime = 0;
|
||||
AH->deposit = deposit;
|
||||
AH->auctionHouseEntry = auctionHouseEntry;
|
||||
|
||||
DETAIL_LOG("selling %s to auctioneer %s with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
|
||||
itemGuid.GetString().c_str(), auctioneerGuid.GetString().c_str(), bid, buyout, auction_time, AH->GetHouseId());
|
||||
auctionHouse->AddAuction(AH);
|
||||
|
||||
sAuctionMgr.AddAItem(newItem);
|
||||
|
||||
CharacterDatabase.BeginTransaction();
|
||||
newItem->SaveToDB();
|
||||
AH->SaveToDB();
|
||||
pl->SaveInventoryAndGoldToDB();
|
||||
CharacterDatabase.CommitTransaction();
|
||||
|
||||
SendAuctionCommandResult(AH, AUCTION_STARTED, AUCTION_OK);
|
||||
|
||||
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
|
||||
}
|
||||
// prevent sending bag with items (cheat: can be placed in bag after adding equipped 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->GetProto()->Flags & ITEM_FLAG_CONJURED) || it->GetUInt32Value(ITEM_FIELD_DURATION))
|
||||
{
|
||||
SendAuctionCommandResult(0, AUCTION_SELL_ITEM, AUCTION_INTERNAL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
//we have to take deposit :
|
||||
uint32 deposit = AuctionHouseMgr::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_BOOL_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.getConfig(CONFIG_FLOAT_RATE_AUCTION_TIME));
|
||||
|
||||
AuctionEntry *AH = new AuctionEntry;
|
||||
AH->Id = sObjectMgr.GenerateAuctionID();
|
||||
AH->item_guidlow = itemGuid.GetCounter();
|
||||
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;
|
||||
|
||||
DETAIL_LOG("selling %s to auctioneer %s with initial bid %u with buyout %u and with time %u (in sec) in auctionhouse %u",
|
||||
itemGuid.GetString().c_str(), auctioneerGuid.GetString().c_str(), bid, buyout, auction_time, AH->GetHouseId());
|
||||
auctionHouse->AddAuction(AH);
|
||||
|
||||
sAuctionMgr.AddAItem(it);
|
||||
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);
|
||||
|
||||
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1);
|
||||
}
|
||||
|
||||
// this function is called when client bids or buys out auction
|
||||
|
|
@ -335,14 +429,13 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data )
|
|||
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 );
|
||||
SendAuctionCommandResult( NULL, AUCTION_BID_PLACED, AUCTION_ERR_BID_OWN );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -353,7 +446,7 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data )
|
|||
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 );
|
||||
SendAuctionCommandResult( NULL, AUCTION_BID_PLACED, AUCTION_ERR_BID_OWN );
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -372,68 +465,61 @@ void WorldSession::HandleAuctionPlaceBid( WorldPacket & recv_data )
|
|||
if (price > pl->GetMoney())
|
||||
{
|
||||
// you don't have enough money!, client tests!
|
||||
// SendAuctionCommandResult(auction->auctionId, AUCTION_PLACE_BID, ???);
|
||||
// SendAuctionCommandResult(auction->auctionId, AUCTION_ERR_INVENTORY, EQUIP_ERR_NOT_ENOUGH_MONEY);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((price < auction->buyout) || (auction->buyout == 0))
|
||||
if ((price < auction->buyout) || (auction->buyout == 0))// bid
|
||||
{
|
||||
if (auction->bidder > 0)
|
||||
if (pl->GetGUIDLow() == auction->bidder)
|
||||
{
|
||||
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) );
|
||||
}
|
||||
pl->ModifyMoney(-int32(price - auction->bid));
|
||||
}
|
||||
else
|
||||
{
|
||||
pl->ModifyMoney( -int32(price) );
|
||||
pl->ModifyMoney(-int32(price));
|
||||
if (auction->bidder) // return money to old bidder if present
|
||||
SendAuctionOutbiddedMail(auction);
|
||||
}
|
||||
|
||||
auction->bidder = pl->GetGUIDLow();
|
||||
auction->bid = price;
|
||||
|
||||
if(auction_owner)
|
||||
auction_owner->GetSession()->SendAuctionOwnerNotification(auction);
|
||||
|
||||
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);
|
||||
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 );
|
||||
SendAuctionCommandResult(auction, AUCTION_BID_PLACED, AUCTION_OK);
|
||||
}
|
||||
else
|
||||
else // buyout
|
||||
{
|
||||
// buyout:
|
||||
if (pl->GetGUIDLow() == auction->bidder )
|
||||
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 );
|
||||
}
|
||||
if (auction->bidder) // return money to old bidder if present
|
||||
SendAuctionOutbiddedMail(auction);
|
||||
}
|
||||
|
||||
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 );
|
||||
auction->moneyDeliveryTime = time(NULL) + HOUR;
|
||||
|
||||
SendAuctionCommandResult(auction->Id, AUCTION_PLACE_BID, AUCTION_OK);
|
||||
sAuctionMgr.SendAuctionWonMail(auction);
|
||||
|
||||
sAuctionMgr.RemoveAItem(auction->item_guidlow);
|
||||
auctionHouse->RemoveAuction(auction->Id);
|
||||
auction->DeleteFromDB();
|
||||
SendAuctionCommandResult(auction, AUCTION_BID_PLACED, AUCTION_OK);
|
||||
|
||||
delete auction;
|
||||
CharacterDatabase.PExecute("UPDATE auction SET moneyTime = '" UI64FMTD "', buyguid = '%u', lastbid = '%u' WHERE id = '%u'", (uint64)auction->moneyDeliveryTime, auction->bidder, auction->bid, auction->Id);
|
||||
}
|
||||
CharacterDatabase.BeginTransaction();
|
||||
pl->SaveInventoryAndGoldToDB();
|
||||
|
|
@ -467,21 +553,21 @@ void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data )
|
|||
|
||||
if (auction && auction->owner == pl->GetGUIDLow())
|
||||
{
|
||||
Item *pItem = sAuctionMgr.GetAItem(auction->item_guidlow);
|
||||
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 ( pl->GetMoney() < auctionCut ) //player doesn't have enough money, maybe message needed
|
||||
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";
|
||||
msgAuctionCanceledOwner << auction->itemTemplate << ":0:" << AUCTION_CANCELED << ":0:0";
|
||||
|
||||
// item will deleted or added to received mail list
|
||||
MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body
|
||||
|
|
@ -490,32 +576,32 @@ void WorldSession::HandleAuctionRemoveItem( WorldPacket & recv_data )
|
|||
}
|
||||
else
|
||||
{
|
||||
sLog.outError("Auction id: %u has nonexistent item (item guid : %u)!!!", auction->Id, auction->item_guidlow);
|
||||
SendAuctionCommandResult( 0, AUCTION_CANCEL, AUCTION_INTERNAL_ERROR );
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 );
|
||||
SendAuctionCommandResult( NULL, AUCTION_REMOVED, AUCTION_ERR_DATABASE );
|
||||
// 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 );
|
||||
// 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->item_guidlow );
|
||||
sAuctionMgr.RemoveAItem( auction->itemGuidLow );
|
||||
auctionHouse->RemoveAuction( auction->Id );
|
||||
delete auction;
|
||||
}
|
||||
|
||||
//called when player lists his bids
|
||||
// called when player lists his bids
|
||||
void WorldSession::HandleAuctionListBidderItems( WorldPacket & recv_data )
|
||||
{
|
||||
DEBUG_LOG("WORLD: HandleAuctionListBidderItems");
|
||||
|
|
@ -600,18 +686,18 @@ void WorldSession::HandleAuctionListOwnerItems( WorldPacket & recv_data )
|
|||
auctionHouse->BuildListOwnerItems(data, _player, count, totalcount);
|
||||
data.put<uint32>(0, count);
|
||||
data << uint32(totalcount);
|
||||
data << uint32(0); // 2.3.0 delay for next list request?
|
||||
data << uint32(300); // 2.3.0 delay for next list request?
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
||||
//this void is called when player clicks on search button
|
||||
// this void is called when player clicks on search button
|
||||
void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
|
||||
{
|
||||
DEBUG_LOG("WORLD: HandleAuctionListItems");
|
||||
|
||||
ObjectGuid auctioneerGuid;
|
||||
std::string searchedname;
|
||||
uint8 levelmin, levelmax, usable;
|
||||
uint8 levelmin, levelmax, usable, isFull, sortCount;
|
||||
uint32 listfrom, auctionSlotID, auctionMainCategory, auctionSubCategory, quality;
|
||||
|
||||
recv_data >> auctioneerGuid;
|
||||
|
|
@ -619,10 +705,15 @@ void WorldSession::HandleAuctionListItems( WorldPacket & recv_data )
|
|||
recv_data >> searchedname;
|
||||
|
||||
recv_data >> levelmin >> levelmax;
|
||||
recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory;
|
||||
recv_data >> quality >> usable;
|
||||
recv_data >> auctionSlotID >> auctionMainCategory >> auctionSubCategory >> quality;
|
||||
recv_data >> usable >> isFull >> sortCount;
|
||||
|
||||
recv_data.read_skip(16); // unknown 16 bytes: 00 07 01 00 00 01 05 00 06 00 09 01 08 00 03 00
|
||||
// auction columns sorting
|
||||
for(uint32 i = 0; i < sortCount; ++i)
|
||||
{
|
||||
recv_data.read_skip<uint8>(); // column?
|
||||
recv_data.read_skip<uint8>(); // direction?
|
||||
}
|
||||
|
||||
AuctionHouseEntry const* auctionHouseEntry = GetCheckedAuctionHouseForAuctioneer(auctioneerGuid);
|
||||
if (!auctionHouseEntry)
|
||||
|
|
@ -673,17 +764,14 @@ void WorldSession::HandleAuctionListPendingSales( WorldPacket & recv_data )
|
|||
if (!auctionHouseEntry)
|
||||
return;
|
||||
|
||||
// always return pointer
|
||||
AuctionHouseObject* auctionHouse = sAuctionMgr.GetAuctionsMap(auctionHouseEntry);
|
||||
|
||||
uint32 count = 0;
|
||||
|
||||
WorldPacket data(SMSG_AUCTION_LIST_PENDING_SALES, 4);
|
||||
data << uint32(count); // count
|
||||
/*for(uint32 i = 0; i < count; ++i)
|
||||
{
|
||||
data << ""; // string
|
||||
data << ""; // string
|
||||
data << uint32(0);
|
||||
data << uint32(0);
|
||||
data << float(0);
|
||||
}*/
|
||||
auctionHouse->BuildListPendingSales(data, _player, count);
|
||||
data.put<uint32>(0, count);
|
||||
SendPacket(&data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,10 +76,10 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32
|
|||
return uint32(deposit * sWorld.getConfig(CONFIG_FLOAT_RATE_AUCTION_DEPOSIT));
|
||||
}
|
||||
|
||||
//does not clear ram
|
||||
// does not clear ram
|
||||
void AuctionHouseMgr::SendAuctionWonMail( AuctionEntry *auction )
|
||||
{
|
||||
Item *pItem = GetAItem(auction->item_guidlow);
|
||||
Item *pItem = GetAItem(auction->itemGuidLow);
|
||||
if(!pItem)
|
||||
return;
|
||||
|
||||
|
|
@ -127,11 +127,16 @@ void AuctionHouseMgr::SendAuctionWonMail( AuctionEntry *auction )
|
|||
else if (!bidder)
|
||||
bidder_accId = sObjectMgr.GetPlayerAccountIdByGUID(bidder_guid);
|
||||
|
||||
ObjectGuid ownerGuid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
|
||||
Player* auction_owner = sObjectMgr.GetPlayer(ownerGuid);
|
||||
if(auction_owner)
|
||||
auction_owner->GetSession()->SendAuctionOwnerNotification( auction );
|
||||
|
||||
// receiver exist
|
||||
if(bidder || bidder_accId)
|
||||
{
|
||||
std::ostringstream msgAuctionWonSubject;
|
||||
msgAuctionWonSubject << auction->item_template << ":0:" << AUCTION_WON;
|
||||
msgAuctionWonSubject << auction->itemTemplate << ":0:" << AUCTION_WON;
|
||||
|
||||
std::ostringstream msgAuctionWonBody;
|
||||
msgAuctionWonBody.width(16);
|
||||
|
|
@ -146,7 +151,7 @@ void AuctionHouseMgr::SendAuctionWonMail( AuctionEntry *auction )
|
|||
|
||||
if (bidder)
|
||||
{
|
||||
bidder->GetSession()->SendAuctionBidderNotification( auction->GetHouseId(), auction->Id, bidder_guid, 0, 0, auction->item_template);
|
||||
bidder->GetSession()->SendAuctionBidderNotification(auction);
|
||||
// FIXME: for offline player need also
|
||||
bidder->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS, 1);
|
||||
}
|
||||
|
|
@ -176,7 +181,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail( AuctionEntry * auction )
|
|||
if(owner || sObjectMgr.GetPlayerAccountIdByGUID(owner_guid))
|
||||
{
|
||||
std::ostringstream msgAuctionSalePendingSubject;
|
||||
msgAuctionSalePendingSubject << auction->item_template << ":0:" << AUCTION_SALE_PENDING;
|
||||
msgAuctionSalePendingSubject << auction->itemTemplate << ":0:" << AUCTION_SALE_PENDING;
|
||||
|
||||
std::ostringstream msgAuctionSalePendingBody;
|
||||
uint32 auctionCut = auction->GetAuctionCut();
|
||||
|
|
@ -196,7 +201,7 @@ void AuctionHouseMgr::SendAuctionSalePendingMail( AuctionEntry * auction )
|
|||
}
|
||||
}
|
||||
|
||||
//call this method to send mail to auction owner, when auction is successful, it does not clear ram
|
||||
// call this method to send mail to auction owner, when auction is successful, it does not clear ram
|
||||
void AuctionHouseMgr::SendAuctionSuccessfulMail( AuctionEntry * auction )
|
||||
{
|
||||
ObjectGuid owner_guid = ObjectGuid(HIGHGUID_PLAYER, auction->owner);
|
||||
|
|
@ -210,7 +215,7 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail( AuctionEntry * auction )
|
|||
if(owner || owner_accId)
|
||||
{
|
||||
std::ostringstream msgAuctionSuccessfulSubject;
|
||||
msgAuctionSuccessfulSubject << auction->item_template << ":0:" << AUCTION_SUCCESSFUL;
|
||||
msgAuctionSuccessfulSubject << auction->itemTemplate << ":0:" << AUCTION_SUCCESSFUL;
|
||||
|
||||
std::ostringstream auctionSuccessfulBody;
|
||||
uint32 auctionCut = auction->GetAuctionCut();
|
||||
|
|
@ -226,26 +231,24 @@ void AuctionHouseMgr::SendAuctionSuccessfulMail( AuctionEntry * auction )
|
|||
|
||||
if (owner)
|
||||
{
|
||||
//FIXME: what do if owner offline
|
||||
// FIXME: what do if owner offline
|
||||
owner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS, profit);
|
||||
owner->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD, auction->bid);
|
||||
//send auction owner notification, bidder must be current!
|
||||
owner->GetSession()->SendAuctionOwnerNotification( auction );
|
||||
}
|
||||
|
||||
MailDraft(msgAuctionSuccessfulSubject.str(), auctionSuccessfulBody.str())
|
||||
.SetMoney(profit)
|
||||
.SendMailTo(MailReceiver(owner, owner_guid), auction, MAIL_CHECK_MASK_COPIED, HOUR);
|
||||
.SendMailTo(MailReceiver(owner, owner_guid), auction, MAIL_CHECK_MASK_COPIED);
|
||||
}
|
||||
}
|
||||
|
||||
//does not clear ram
|
||||
// does not clear ram
|
||||
void AuctionHouseMgr::SendAuctionExpiredMail( AuctionEntry * auction )
|
||||
{ //return an item in auction to its owner by mail
|
||||
Item *pItem = GetAItem(auction->item_guidlow);
|
||||
{ // return an item in auction to its owner by mail
|
||||
Item *pItem = GetAItem(auction->itemGuidLow);
|
||||
if(!pItem)
|
||||
{
|
||||
sLog.outError("Auction item (GUID: %u) not found, and lost.",auction->item_guidlow);
|
||||
sLog.outError("Auction item (GUID: %u) not found, and lost.", auction->itemGuidLow);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -260,7 +263,7 @@ void AuctionHouseMgr::SendAuctionExpiredMail( AuctionEntry * auction )
|
|||
if(owner || owner_accId)
|
||||
{
|
||||
std::ostringstream subject;
|
||||
subject << auction->item_template << ":0:" << AUCTION_EXPIRED << ":0:0";
|
||||
subject << auction->itemGuidLow << ":0:" << AUCTION_EXPIRED << ":0:0";
|
||||
|
||||
if ( owner )
|
||||
owner->GetSession()->SendAuctionOwnerNotification( auction );
|
||||
|
|
@ -359,7 +362,7 @@ void AuctionHouseMgr::LoadAuctions()
|
|||
return;
|
||||
}
|
||||
|
||||
result = CharacterDatabase.Query( "SELECT id,houseid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit FROM auction" );
|
||||
result = CharacterDatabase.Query( "SELECT id,houseid,itemguid,item_template,itemowner,buyoutprice,time,moneyTime,buyguid,lastbid,startbid,deposit FROM auction" );
|
||||
if( !result )
|
||||
{
|
||||
barGoLink bar(1);
|
||||
|
|
@ -382,24 +385,25 @@ void AuctionHouseMgr::LoadAuctions()
|
|||
auction = new AuctionEntry;
|
||||
auction->Id = fields[0].GetUInt32();
|
||||
uint32 houseid = fields[1].GetUInt32();
|
||||
auction->item_guidlow = fields[2].GetUInt32();
|
||||
auction->item_template = fields[3].GetUInt32();
|
||||
auction->itemGuidLow = fields[2].GetUInt32();
|
||||
auction->itemTemplate = fields[3].GetUInt32();
|
||||
auction->owner = fields[4].GetUInt32();
|
||||
auction->buyout = fields[5].GetUInt32();
|
||||
auction->expire_time = fields[6].GetUInt32();
|
||||
auction->bidder = fields[7].GetUInt32();
|
||||
auction->bid = fields[8].GetUInt32();
|
||||
auction->startbid = fields[9].GetUInt32();
|
||||
auction->deposit = fields[10].GetUInt32();
|
||||
auction->expireTime = fields[6].GetUInt32();
|
||||
auction->moneyDeliveryTime = fields[7].GetUInt32();
|
||||
auction->bidder = fields[8].GetUInt32();
|
||||
auction->bid = fields[9].GetUInt32();
|
||||
auction->startbid = fields[10].GetUInt32();
|
||||
auction->deposit = fields[11].GetUInt32();
|
||||
auction->auctionHouseEntry = NULL; // init later
|
||||
|
||||
// check if sold item exists for guid
|
||||
// and item_template in fact (GetAItem will fail if problematic in result check in AuctionHouseMgr::LoadAuctionItems)
|
||||
Item* pItem = GetAItem(auction->item_guidlow);
|
||||
Item* pItem = GetAItem(auction->itemGuidLow);
|
||||
if (!pItem)
|
||||
{
|
||||
auction->DeleteFromDB();
|
||||
sLog.outError("Auction %u has not a existing item : %u, deleted", auction->Id, auction->item_guidlow);
|
||||
sLog.outError("Auction %u has not a existing item : %u, deleted", auction->Id, auction->itemGuidLow);
|
||||
delete auction;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -413,14 +417,14 @@ void AuctionHouseMgr::LoadAuctions()
|
|||
|
||||
// Attempt send item back to owner
|
||||
std::ostringstream msgAuctionCanceledOwner;
|
||||
msgAuctionCanceledOwner << auction->item_template << ":0:" << AUCTION_CANCELED << ":0:0";
|
||||
msgAuctionCanceledOwner << auction->itemTemplate << ":0:" << AUCTION_CANCELED << ":0:0";
|
||||
|
||||
// item will deleted or added to received mail list
|
||||
MailDraft(msgAuctionCanceledOwner.str(), "") // TODO: fix body
|
||||
.AddItem(pItem)
|
||||
.SendMailTo(MailReceiver(ObjectGuid(HIGHGUID_PLAYER, auction->owner)), auction, MAIL_CHECK_MASK_COPIED);
|
||||
|
||||
RemoveAItem(auction->item_guidlow);
|
||||
RemoveAItem(auction->itemGuidLow);
|
||||
auction->DeleteFromDB();
|
||||
delete auction;
|
||||
|
||||
|
|
@ -543,32 +547,46 @@ void AuctionHouseObject::Update()
|
|||
time_t curTime = sWorld.GetGameTime();
|
||||
///- Handle expired auctions
|
||||
AuctionEntryMap::iterator next;
|
||||
for (AuctionEntryMap::iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end();itr = next)
|
||||
for (AuctionEntryMap::iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); itr = next)
|
||||
{
|
||||
next = itr;
|
||||
++next;
|
||||
if (curTime > (itr->second->expire_time))
|
||||
{
|
||||
///- Either cancel the auction if there was no bidder
|
||||
if (itr->second->bidder == 0)
|
||||
{
|
||||
sAuctionMgr.SendAuctionExpiredMail( itr->second );
|
||||
}
|
||||
///- Or perform the transaction
|
||||
else
|
||||
{
|
||||
//we should send an "item sold" message if the seller is online
|
||||
//we send the item to the winner
|
||||
//we send the money to the seller
|
||||
sAuctionMgr.SendAuctionSuccessfulMail( itr->second );
|
||||
sAuctionMgr.SendAuctionWonMail( itr->second );
|
||||
}
|
||||
|
||||
///- In any case clear the auction
|
||||
itr->second->DeleteFromDB();
|
||||
sAuctionMgr.RemoveAItem(itr->second->item_guidlow);
|
||||
delete itr->second;
|
||||
RemoveAuction(itr->first);
|
||||
if (itr->second->moneyDeliveryTime)
|
||||
{
|
||||
if (curTime > itr->second->moneyDeliveryTime)
|
||||
{
|
||||
sAuctionMgr.SendAuctionSuccessfulMail( itr->second );
|
||||
|
||||
itr->second->DeleteFromDB();
|
||||
sAuctionMgr.RemoveAItem(itr->second->itemGuidLow);
|
||||
delete itr->second;
|
||||
RemoveAuction(itr->first);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curTime > itr->second->expireTime)
|
||||
{
|
||||
///- Either cancel the auction if there was no bidder
|
||||
if (itr->second->bidder == 0)
|
||||
{
|
||||
sAuctionMgr.SendAuctionExpiredMail( itr->second );
|
||||
}
|
||||
///- Or perform the transaction
|
||||
else
|
||||
{
|
||||
itr->second->moneyDeliveryTime = time(NULL) + HOUR;
|
||||
sAuctionMgr.SendAuctionWonMail( itr->second );
|
||||
continue;
|
||||
}
|
||||
|
||||
///- In any case clear the auction
|
||||
itr->second->DeleteFromDB();
|
||||
sAuctionMgr.RemoveAItem(itr->second->itemGuidLow);
|
||||
delete itr->second;
|
||||
RemoveAuction(itr->first);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -578,6 +596,8 @@ void AuctionHouseObject::BuildListBidderItems(WorldPacket& data, Player* player,
|
|||
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin();itr != AuctionsMap.end();++itr)
|
||||
{
|
||||
AuctionEntry *Aentry = itr->second;
|
||||
if(Aentry->moneyDeliveryTime)
|
||||
continue;
|
||||
if( Aentry && Aentry->bidder == player->GetGUIDLow() )
|
||||
{
|
||||
if (itr->second->BuildAuctionInfo(data))
|
||||
|
|
@ -592,6 +612,8 @@ void AuctionHouseObject::BuildListOwnerItems(WorldPacket& data, Player* player,
|
|||
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin();itr != AuctionsMap.end();++itr)
|
||||
{
|
||||
AuctionEntry *Aentry = itr->second;
|
||||
if(Aentry->moneyDeliveryTime)
|
||||
continue;
|
||||
if( Aentry && Aentry->owner == player->GetGUIDLow() )
|
||||
{
|
||||
if(Aentry->BuildAuctionInfo(data))
|
||||
|
|
@ -611,7 +633,9 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
|
|||
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin();itr != AuctionsMap.end();++itr)
|
||||
{
|
||||
AuctionEntry *Aentry = itr->second;
|
||||
Item *item = sAuctionMgr.GetAItem(Aentry->item_guidlow);
|
||||
if(Aentry->moneyDeliveryTime)
|
||||
continue;
|
||||
Item *item = sAuctionMgr.GetAItem(Aentry->itemGuidLow);
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
|
|
@ -662,10 +686,45 @@ void AuctionHouseObject::BuildListAuctionItems(WorldPacket& data, Player* player
|
|||
}
|
||||
}
|
||||
|
||||
//this function inserts to WorldPacket auction's data
|
||||
void AuctionHouseObject::BuildListPendingSales(WorldPacket& data, Player* player, uint32& count)
|
||||
{
|
||||
for (AuctionEntryMap::const_iterator itr = AuctionsMap.begin(); itr != AuctionsMap.end(); ++itr)
|
||||
{
|
||||
AuctionEntry *Aentry = itr->second;
|
||||
if(!Aentry->moneyDeliveryTime)
|
||||
continue;
|
||||
if( Aentry && Aentry->owner == player->GetGUIDLow() )
|
||||
{
|
||||
Item *pItem = sAuctionMgr.GetAItem(Aentry->itemGuidLow);
|
||||
if (!pItem)
|
||||
{
|
||||
sLog.outError("Auction: item with guid %u doesn't exist!", Aentry->itemGuidLow);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::ostringstream str1;
|
||||
str1 << Aentry->itemTemplate << ":" << pItem->GetItemRandomPropertyId() << ":" << AUCTION_SUCCESSFUL << ":" << Aentry->Id << ":" << pItem->GetCount();
|
||||
|
||||
std::ostringstream str2;
|
||||
str2.width(16);
|
||||
str2 << std::right << std::hex << Aentry->bidder << std::dec << ":";
|
||||
str2 << Aentry->bid << ":" << Aentry->buyout << ":" << Aentry->deposit << ":" << Aentry->GetAuctionCut();
|
||||
|
||||
data << str1.str(); // string "%d:%d:%d:%d:%d" -> itemId, ItemRandomPropertyId, 2, auctionId, unk1 (stack size?, unused)
|
||||
data << str2.str(); // string "%16I64X:%d:%d:%d:%d" -> bidderGuid, bid, buyout, deposit, auctionCut
|
||||
data << uint32(97250); // unk1
|
||||
data << uint32(68); // unk2
|
||||
float timeLeft = float(Aentry->moneyDeliveryTime - time(NULL)) / float(DAY);
|
||||
data << float(timeLeft); // time left
|
||||
++count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this function inserts to WorldPacket auction's data
|
||||
bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const
|
||||
{
|
||||
Item *pItem = sAuctionMgr.GetAItem(item_guidlow);
|
||||
Item *pItem = sAuctionMgr.GetAItem(itemGuidLow);
|
||||
if (!pItem)
|
||||
{
|
||||
sLog.outError("auction to item, that doesn't exist !!!!");
|
||||
|
|
@ -681,19 +740,18 @@ bool AuctionEntry::BuildAuctionInfo(WorldPacket & data) const
|
|||
data << uint32(pItem->GetEnchantmentCharges(EnchantmentSlot(i)));
|
||||
}
|
||||
|
||||
data << uint32(pItem->GetItemRandomPropertyId()); //random item property id
|
||||
data << uint32(pItem->GetItemSuffixFactor()); //SuffixFactor
|
||||
data << uint32(pItem->GetCount()); //item->count
|
||||
data << uint32(pItem->GetSpellCharges()); //item->charge FFFFFFF
|
||||
data << uint32(0); //Unknown
|
||||
data << ObjectGuid(HIGHGUID_PLAYER, owner); //Auction->owner
|
||||
data << uint32(startbid); //Auction->startbid (not sure if useful)
|
||||
data << uint32(bid ? GetAuctionOutBid() : 0);
|
||||
//minimal outbid
|
||||
data << uint32(buyout); //auction->buyout
|
||||
data << uint32((expire_time-time(NULL))*IN_MILLISECONDS);//time left
|
||||
data << ObjectGuid(HIGHGUID_PLAYER, bidder); //auction->bidder current
|
||||
data << uint32(bid); //current bid
|
||||
data << uint32(pItem->GetItemRandomPropertyId()); // random item property id
|
||||
data << uint32(pItem->GetItemSuffixFactor()); // SuffixFactor
|
||||
data << uint32(pItem->GetCount()); // item->count
|
||||
data << uint32(pItem->GetSpellCharges()); // item->charge FFFFFFF
|
||||
data << uint32(0); // item flags (dynamic?) (0x04 no lockId?)
|
||||
data << ObjectGuid(HIGHGUID_PLAYER, owner); // Auction->owner
|
||||
data << uint32(startbid); // Auction->startbid (not sure if useful)
|
||||
data << uint32(bid ? GetAuctionOutBid() : 0); // minimal outbid
|
||||
data << uint32(buyout); // auction->buyout
|
||||
data << uint32((expireTime-time(NULL))*IN_MILLISECONDS);// time left
|
||||
data << ObjectGuid(HIGHGUID_PLAYER, bidder); // auction->bidder current
|
||||
data << uint32(bid); // current bid
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -720,7 +778,7 @@ void AuctionEntry::DeleteFromDB() const
|
|||
void AuctionEntry::SaveToDB() const
|
||||
{
|
||||
//No SQL injection (no strings)
|
||||
CharacterDatabase.PExecute("INSERT INTO auction (id,houseid,itemguid,item_template,itemowner,buyoutprice,time,buyguid,lastbid,startbid,deposit) "
|
||||
"VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '%u', '%u', '%u', '%u')",
|
||||
Id, auctionHouseEntry->houseId, item_guidlow, item_template, owner, buyout, (uint64)expire_time, bidder, bid, startbid, deposit);
|
||||
CharacterDatabase.PExecute("INSERT INTO auction (id,houseid,itemguid,item_template,itemowner,buyoutprice,time,moneyTime,buyguid,lastbid,startbid,deposit) "
|
||||
"VALUES ('%u', '%u', '%u', '%u', '%u', '%u', '" UI64FMTD "', '" UI64FMTD "', '%u', '%u', '%u', '%u')",
|
||||
Id, auctionHouseEntry->houseId, itemGuidLow, itemTemplate, owner, buyout, (uint64)expireTime, (uint64)moneyDeliveryTime, bidder, bid, startbid, deposit);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,32 +33,37 @@ class WorldPacket;
|
|||
|
||||
enum AuctionError
|
||||
{
|
||||
AUCTION_OK = 0,
|
||||
AUCTION_INTERNAL_ERROR = 2,
|
||||
AUCTION_NOT_ENOUGHT_MONEY = 3,
|
||||
AUCTION_ITEM_NOT_FOUND = 4,
|
||||
CANNOT_BID_YOUR_AUCTION_ERROR = 10
|
||||
AUCTION_OK = 0, // depends on enum AuctionAction
|
||||
AUCTION_ERR_INVENTORY = 1, // depends on enum InventoryChangeResult
|
||||
AUCTION_ERR_DATABASE = 2, // ERR_AUCTION_DATABASE_ERROR (default)
|
||||
AUCTION_ERR_NOT_ENOUGH_MONEY = 3, // ERR_NOT_ENOUGH_MONEY
|
||||
AUCTION_ERR_ITEM_NOT_FOUND = 4, // ERR_ITEM_NOT_FOUND
|
||||
AUCTION_ERR_HIGHER_BID = 5, // ERR_AUCTION_HIGHER_BID
|
||||
AUCTION_ERR_BID_INCREMENT = 7, // ERR_AUCTION_BID_INCREMENT
|
||||
AUCTION_ERR_BID_OWN = 10, // ERR_AUCTION_BID_OWN
|
||||
AUCTION_ERR_RESTRICTED_ACCOUNT = 13 // ERR_RESTRICTED_ACCOUNT
|
||||
};
|
||||
|
||||
enum AuctionAction
|
||||
{
|
||||
AUCTION_SELL_ITEM = 0,
|
||||
AUCTION_CANCEL = 1,
|
||||
AUCTION_PLACE_BID = 2
|
||||
AUCTION_STARTED = 0, // ERR_AUCTION_STARTED
|
||||
AUCTION_REMOVED = 1, // ERR_AUCTION_REMOVED
|
||||
AUCTION_BID_PLACED = 2 // ERR_AUCTION_BID_PLACED
|
||||
};
|
||||
|
||||
struct AuctionEntry
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 item_guidlow;
|
||||
uint32 item_template;
|
||||
uint32 itemGuidLow;
|
||||
uint32 itemTemplate;
|
||||
uint32 owner;
|
||||
uint32 startbid; //maybe useless
|
||||
uint32 startbid; // maybe useless
|
||||
uint32 bid;
|
||||
uint32 buyout;
|
||||
time_t expire_time;
|
||||
time_t expireTime;
|
||||
time_t moneyDeliveryTime;
|
||||
uint32 bidder;
|
||||
uint32 deposit; //deposit can be calculated only when creating auction
|
||||
uint32 deposit; // deposit can be calculated only when creating auction
|
||||
AuctionHouseEntry const* auctionHouseEntry; // in AuctionHouse.dbc
|
||||
|
||||
// helpers
|
||||
|
|
@ -107,6 +112,7 @@ class AuctionHouseObject
|
|||
|
||||
void BuildListBidderItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
|
||||
void BuildListOwnerItems(WorldPacket& data, Player* player, uint32& count, uint32& totalcount);
|
||||
void BuildListPendingSales(WorldPacket& data, Player* player, uint32& count);
|
||||
void BuildListAuctionItems(WorldPacket& data, Player* player,
|
||||
std::wstring const& searchedname, uint32 listfrom, uint32 levelmin, uint32 levelmax, uint32 usable,
|
||||
uint32 inventoryType, uint32 itemClass, uint32 itemSubClass, uint32 quality,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
#include "Common.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "AuctionHouseMgr.h"
|
||||
#include "Item.h"
|
||||
|
||||
struct ItemPrototype;
|
||||
struct AuctionEntry;
|
||||
|
|
@ -347,12 +349,13 @@ class MANGOS_DLL_SPEC WorldSession
|
|||
bool SendItemInfo( uint32 itemid, WorldPacket data );
|
||||
|
||||
//auction
|
||||
void SendAuctionHello(Unit * unit);
|
||||
void SendAuctionCommandResult( uint32 auctionId, uint32 Action, uint32 ErrorCode, uint32 bidError = 0);
|
||||
void SendAuctionBidderNotification( uint32 location, uint32 auctionId, ObjectGuid bidderGuid, uint32 bidSum, uint32 diff, uint32 item_template);
|
||||
void SendAuctionOwnerNotification( AuctionEntry * auction );
|
||||
void SendAuctionOutbiddedMail( AuctionEntry * auction, uint32 newPrice );
|
||||
void SendAuctionCancelledToBidderMail( AuctionEntry* auction );
|
||||
void SendAuctionHello(Unit *unit);
|
||||
void SendAuctionCommandResult(AuctionEntry *auc, AuctionAction Action, AuctionError ErrorCode, InventoryResult invError = EQUIP_ERR_OK);
|
||||
void SendAuctionBidderNotification(AuctionEntry *auction);
|
||||
void SendAuctionOwnerNotification(AuctionEntry *auction);
|
||||
void SendAuctionRemovedNotification(AuctionEntry* auction);
|
||||
void SendAuctionOutbiddedMail(AuctionEntry *auction);
|
||||
void SendAuctionCancelledToBidderMail(AuctionEntry *auction);
|
||||
AuctionHouseEntry const* GetCheckedAuctionHouseForAuctioneer(ObjectGuid guid);
|
||||
|
||||
//Item Enchantment
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#ifndef __REVISION_NR_H__
|
||||
#define __REVISION_NR_H__
|
||||
#define REVISION_NR "11390"
|
||||
#define REVISION_NR "11391"
|
||||
#endif // __REVISION_NR_H__
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __REVISION_SQL_H__
|
||||
#define __REVISION_SQL_H__
|
||||
#define REVISION_DB_CHARACTERS "required_11299_02_characters_pet_aura"
|
||||
#define REVISION_DB_CHARACTERS "required_11391_01_characters_auction"
|
||||
#define REVISION_DB_MANGOS "required_11385_01_mangos_creature_template"
|
||||
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
|
||||
#endif // __REVISION_SQL_H__
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue