diff options
| author | pete318 <pete318@hotmail.com> | 2015-10-02 03:20:42 +0100 |
|---|---|---|
| committer | DDuarte <dnpd.dd@gmail.com> | 2016-03-23 00:28:03 +0000 |
| commit | 28f51306d4af3cbbae0ad745858d0eb7c5a98783 (patch) | |
| tree | 618cba9ce9d3188f990419cb89727a6e19fb9eaf /src | |
| parent | 9660848385068c7f57dc3b0ec3408c01ff4341aa (diff) | |
Improved Auction house deposit handling.
Including the weird quirks.
Changes:
* Deposit caculated according to same rule as client. (detailed below). Should always match client deposit now
* Deposit for multiple auctions now only collected once. Deferred calculation of deposit until all auctions listed.
Deposit calculation is as follows:
Base deposit calculation = MSV x 15/75% (depending on AH). However this is not rounded. Case to int is used (so always round down)
The remainder is held in a float.
The base is then multiplied by number of items, and the time multiplier (x2 for 24 hour, x4 for 48 hour)
The nearest (no of items or lower) no of items when multiplied by the remainder that creates a whole number is then multiplied by the time multiplier (x1/x2/x4) and then added to deposit.
Example:
Item sell price 1s25. Deposit 18.75c (15% of 1s25). So base deposit = 18, remainder 0.75. Time 24h (x2) Item count 1 = 36c. Remainder = 0.75 (n) Min = 1s. Deposit 1s
Item sell price 1s25. Deposit 18.75c (15% of 1s25). So base deposit = 18, remainder 0.75. Time 24h (x2) Item count 2 = 72c. Remainder = 1.50 (n) Min = 1s. Deposit 1s
Item sell price 1s25. Deposit 18.75c (15% of 1s25). So base deposit = 18, remainder 0.75. Time 24h (x2) Item count 3 = 108c. Remainder = 2.25 (n) Min = 1s. Deposit 1s08c
Item sell price 1s25. Deposit 18.75c (15% of 1s25). So base deposit = 18, remainder 0.75. Time 24h (x2) Item count 4 = 144c. Remainder = 3.00 (n) Min = 1s. Deposit 1s50c (144c + (3c * 2))
Horrible kludge, to re-create a very weird deposit method.
Closes #15674 (PR)
Closes #15643 (Issue)
(cherry picked from commit 0ac442f19fcfa8c39775c5ae06bba8f3bcbd0407)
# Conflicts:
# src/server/game/AuctionHouse/AuctionHouseMgr.h
Diffstat (limited to 'src')
| -rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.cpp | 123 | ||||
| -rw-r--r-- | src/server/game/AuctionHouse/AuctionHouseMgr.h | 11 | ||||
| -rw-r--r-- | src/server/game/Entities/Player/Player.cpp | 1 | ||||
| -rw-r--r-- | src/server/game/Handlers/AuctionHouseHandler.cpp | 7 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 8 | ||||
| -rw-r--r-- | src/server/game/World/World.h | 1 |
6 files changed, 147 insertions, 4 deletions
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp index 9939b372513..ce8815dee07 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp @@ -77,12 +77,23 @@ uint32 AuctionHouseMgr::GetAuctionDeposit(AuctionHouseEntry const* entry, uint32 float multiplier = CalculatePct(float(entry->DepositRate), 3); uint32 timeHr = (((time / 60) / 60) / 12); - uint32 deposit = uint32(((multiplier * MSV * count / 3) * timeHr * 3) * sWorld->getRate(RATE_AUCTION_DEPOSIT)); + uint32 deposit = uint32(MSV * multiplier * sWorld->getRate(RATE_AUCTION_DEPOSIT)); + float remainderbase = float(MSV * multiplier * sWorld->getRate(RATE_AUCTION_DEPOSIT)) - deposit; + + deposit *= timeHr * count; + + int i = count; + while (i > 0 && (remainderbase * i) != uint32(remainderbase * i)) + i--; + + if (i) + deposit += remainderbase * i * timeHr; TC_LOG_DEBUG("auctionHouse", "MSV: %u", MSV); TC_LOG_DEBUG("auctionHouse", "Items: %u", count); TC_LOG_DEBUG("auctionHouse", "Multiplier: %f", multiplier); TC_LOG_DEBUG("auctionHouse", "Deposit: %u", deposit); + TC_LOG_DEBUG("auctionHouse", "Deposit rm: %f", remainderbase * count); if (deposit < AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT)) return AH_MINIMUM_DEPOSIT * sWorld->getRate(RATE_AUCTION_DEPOSIT); @@ -385,6 +396,116 @@ bool AuctionHouseMgr::RemoveAItem(ObjectGuid::LowType id, bool deleteItem) return true; } +void AuctionHouseMgr::PendingAuctionAdd(Player* player, AuctionEntry* aEntry) +{ + PlayerAuctions* thisAH; + auto itr = pendingAuctionMap.find(player->GetGUID()); + if (itr != pendingAuctionMap.end()) + thisAH = itr->second.first; + else + { + thisAH = new PlayerAuctions; + pendingAuctionMap[player->GetGUID()] = AuctionPair(thisAH, 0); + } + thisAH->push_back(aEntry); +} + +uint32 AuctionHouseMgr::PendingAuctionCount(const Player* player) const +{ + auto const itr = pendingAuctionMap.find(player->GetGUID()); + if (itr != pendingAuctionMap.end()) + return itr->second.first->size(); + + return 0; +} + +void AuctionHouseMgr::PendingAuctionProcess(Player* player) +{ + auto iterMap = pendingAuctionMap.find(player->GetGUID()); + if (iterMap == pendingAuctionMap.end()) + return; + + PlayerAuctions* thisAH = iterMap->second.first; + + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + + uint32 totalItems = 0; + for (auto itrAH = thisAH->begin(); itrAH != thisAH->end(); ++itrAH) + { + AuctionEntry* AH = (*itrAH); + totalItems += AH->itemCount; + } + + uint32 totaldeposit = 0; + auto itr = (*thisAH->begin()); + + if (Item* item = GetAItem(itr->itemGUIDLow)) + totaldeposit = GetAuctionDeposit(itr->auctionHouseEntry, itr->etime, item, totalItems); + + uint32 depositremain = totaldeposit; + for (auto itr = thisAH->begin(); itr != thisAH->end(); ++itr) + { + AuctionEntry* AH = (*itr); + + if (next(itr) == thisAH->end()) + AH->deposit = depositremain; + else + { + AH->deposit = totaldeposit / thisAH->size(); + depositremain -= AH->deposit; + } + + AH->DeleteFromDB(trans); + AH->SaveToDB(trans); + } + + CharacterDatabase.CommitTransaction(trans); + pendingAuctionMap.erase(player->GetGUID()); + delete thisAH; + player->ModifyMoney(-int32(totaldeposit)); +} + +void AuctionHouseMgr::UpdatePendingAuctions() +{ + for (auto itr = pendingAuctionMap.begin(); itr != pendingAuctionMap.end();) + { + ObjectGuid playerGUID = itr->first; + if (Player* player = ObjectAccessor::FindConnectedPlayer(playerGUID)) + { + // Check if there were auctions since last update process if not + if (PendingAuctionCount(player) == itr->second.second) + { + ++itr; + PendingAuctionProcess(player); + } + else + { + ++itr; + pendingAuctionMap[playerGUID].second = PendingAuctionCount(player); + } + } + else + { + // Expire any auctions that we couldn't get a deposit for + TC_LOG_WARN("auctionHouse", "Player %s was offline, unable to retrieve deposit!", playerGUID.ToString().c_str()); + PlayerAuctions* thisAH = itr->second.first; + ++itr; + SQLTransaction trans = CharacterDatabase.BeginTransaction(); + for (auto AHitr = thisAH->begin(); AHitr != thisAH->end();) + { + AuctionEntry* AH = (*AHitr); + ++AHitr; + AH->expire_time = time(NULL); + AH->DeleteFromDB(trans); + AH->SaveToDB(trans); + } + CharacterDatabase.CommitTransaction(trans); + pendingAuctionMap.erase(playerGUID); + delete thisAH; + } + } +} + void AuctionHouseMgr::Update() { mHordeAuctions.Update(); diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h index b5ae7d26514..62b6838a6e6 100644 --- a/src/server/game/AuctionHouse/AuctionHouseMgr.h +++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h @@ -24,6 +24,7 @@ #include "DBCStructure.h" #include "ObjectGuid.h" #include "AuctionHousePackets.h" +#include <set> class Item; class Player; @@ -77,6 +78,7 @@ struct AuctionEntry time_t expire_time; ObjectGuid::LowType bidder; uint32 deposit; //deposit can be calculated only when creating auction + uint32 etime; AuctionHouseEntry const* auctionHouseEntry; // in AuctionHouse.dbc uint32 factionTemplateId; @@ -143,6 +145,8 @@ class AuctionHouseMgr static AuctionHouseMgr* instance(); typedef std::unordered_map<ObjectGuid::LowType, Item*> ItemMap; + typedef std::vector<AuctionEntry*> PlayerAuctions; + typedef std::pair<PlayerAuctions*, uint32> AuctionPair; AuctionHouseObject* GetAuctionsMap(uint32 factionTemplateId); AuctionHouseObject* GetBidsMap(uint32 factionTemplateId); @@ -175,7 +179,10 @@ class AuctionHouseMgr void AddAItem(Item* it); bool RemoveAItem(ObjectGuid::LowType id, bool deleteItem = false); - + void PendingAuctionAdd(Player* player, AuctionEntry* aEntry); + uint32 PendingAuctionCount(const Player* player) const; + void PendingAuctionProcess(Player* player); + void UpdatePendingAuctions(); void Update(); private: @@ -184,6 +191,8 @@ class AuctionHouseMgr AuctionHouseObject mAllianceAuctions; AuctionHouseObject mNeutralAuctions; + std::map<ObjectGuid, AuctionPair> pendingAuctionMap; + ItemMap mAitems; }; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index a01bba9aef3..950a1ff0841 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -1362,6 +1362,7 @@ void Player::Update(uint32 p_time) //because we don't want player's ghost teleported from graveyard if (IsHasDelayedTeleport() && IsAlive()) TeleportTo(m_teleport_dest, m_teleport_options); + } void Player::setDeathState(DeathState s) diff --git a/src/server/game/Handlers/AuctionHouseHandler.cpp b/src/server/game/Handlers/AuctionHouseHandler.cpp index a92298981ec..ed464c15eca 100644 --- a/src/server/game/Handlers/AuctionHouseHandler.cpp +++ b/src/server/game/Handlers/AuctionHouseHandler.cpp @@ -258,18 +258,21 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; + AH->etime = etime; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling item %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), item->GetGUID().ToString().c_str(), item->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, item->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(item); auctionHouse->AddAuction(AH); + sAuctionMgr->PendingAuctionAdd(_player, AH); _player->MoveItemFromInventory(item->GetBagSlot(), item->GetSlot(), true); SQLTransaction trans = CharacterDatabase.BeginTransaction(); item->DeleteFromInventoryDB(trans); item->SaveToDB(trans); + AH->SaveToDB(trans); _player->SaveInventoryAndGoldToDB(trans); CharacterDatabase.CommitTransaction(trans); @@ -306,12 +309,14 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell AH->buyout = packet.BuyoutPrice; AH->expire_time = time(NULL) + auctionTime; AH->deposit = deposit; + AH->etime = etime; AH->auctionHouseEntry = auctionHouseEntry; TC_LOG_INFO("network", "CMSG_AUCTION_SELL_ITEM: %s %s is selling %s %s to auctioneer " UI64FMTD " with count %u with initial bid " UI64FMTD " with buyout " UI64FMTD " and with time %u (in sec) in auctionhouse %u", _player->GetGUID().ToString().c_str(), _player->GetName().c_str(), newItem->GetGUID().ToString().c_str(), newItem->GetTemplate()->GetDefaultLocaleName(), AH->auctioneer, newItem->GetCount(), packet.MinBid, packet.BuyoutPrice, auctionTime, AH->GetHouseId()); sAuctionMgr->AddAItem(newItem); auctionHouse->AddAuction(AH); + sAuctionMgr->PendingAuctionAdd(_player, AH); for (auto const& packetItem : packet.Items) { @@ -351,8 +356,6 @@ void WorldSession::HandleAuctionSellItem(WorldPackets::AuctionHouse::AuctionSell GetPlayer()->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION, 1); } - - _player->ModifyMoney(-int32(deposit)); } // this function is called when client bids or buys out auction diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 862352d30bd..bb675720d23 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1946,6 +1946,7 @@ void World::SetInitialWorldSettings() m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS); m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS); + m_timers[WUPDATE_AUCTIONS_PENDING].SetInterval(250); m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS); //Update "uptime" table based on configuration entry in minutes. m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS); @@ -2195,6 +2196,13 @@ void World::Update(uint32 diff) sAuctionMgr->Update(); } + if (m_timers[WUPDATE_AUCTIONS_PENDING].Passed()) + { + m_timers[WUPDATE_AUCTIONS_PENDING].Reset(); + + sAuctionMgr->UpdatePendingAuctions(); + } + /// <li> Handle AHBot operations if (m_timers[WUPDATE_AHBOT].Passed()) { diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index 1ccdec3e2dd..88baac9abf3 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -79,6 +79,7 @@ enum ShutdownExitCode enum WorldTimers { WUPDATE_AUCTIONS, + WUPDATE_AUCTIONS_PENDING, WUPDATE_WEATHERS, WUPDATE_UPTIME, WUPDATE_CORPSES, |
