// Copyright (c) CypherCore All rights reserved. // Licensed under the GNU GENERAL PUBLIC LICENSE. See LICENSE file in the project root for full license information. using Framework.Collections; using Framework.Constants; using Framework.Database; using Game.Entities; using Game.Networking.Packets; using System.Collections.Generic; namespace Game.BlackMarket { public class BlackMarketTemplate { public bool LoadFromDB(SQLFields fields) { MarketID = fields.Read(0); SellerNPC = fields.Read(1); Item = new ItemInstance(); Item.ItemID = fields.Read(2); Quantity = fields.Read(3); MinBid = fields.Read(4); Duration = fields.Read(5); Chance = fields.Read(6); var bonusListIDsTok = new StringArray(fields.Read(7), ' '); List bonusListIDs = new(); if (!bonusListIDsTok.IsEmpty()) { foreach (string token in bonusListIDsTok) { if (uint.TryParse(token, out uint id)) bonusListIDs.Add(id); } } if (!bonusListIDs.Empty()) { Item.ItemBonus = new(); Item.ItemBonus.BonusListIDs = bonusListIDs; } if (Global.ObjectMgr.GetCreatureTemplate(SellerNPC) == null) { Log.outError(LogFilter.Misc, "Black market template {0} does not have a valid seller. (Entry: {1})", MarketID, SellerNPC); return false; } if (Global.ObjectMgr.GetItemTemplate(Item.ItemID) == null) { Log.outError(LogFilter.Misc, "Black market template {0} does not have a valid item. (Entry: {1})", MarketID, Item.ItemID); return false; } return true; } public uint MarketID; public uint SellerNPC; public uint Quantity; public ulong MinBid; public long Duration; public float Chance; public ItemInstance Item; } public class BlackMarketEntry { public void Initialize(uint marketId, uint duration) { _marketId = marketId; _secondsRemaining = duration; } public void Update(long newTimeOfUpdate) { _secondsRemaining = (uint)(_secondsRemaining - (newTimeOfUpdate - Global.BlackMarketMgr.GetLastUpdate())); } public BlackMarketTemplate GetTemplate() { return Global.BlackMarketMgr.GetTemplateByID(_marketId); } public uint GetSecondsRemaining() { return (uint)(_secondsRemaining - (GameTime.GetGameTime() - Global.BlackMarketMgr.GetLastUpdate())); } long GetExpirationTime() { return GameTime.GetGameTime() + GetSecondsRemaining(); } public bool IsCompleted() { return GetSecondsRemaining() <= 0; } public bool LoadFromDB(SQLFields fields) { _marketId = fields.Read(0); // Invalid MarketID BlackMarketTemplate templ = Global.BlackMarketMgr.GetTemplateByID(_marketId); if (templ == null) { Log.outError(LogFilter.Misc, "Black market auction {0} does not have a valid id.", _marketId); return false; } _currentBid = fields.Read(1); _secondsRemaining = (uint)(fields.Read(2) - Global.BlackMarketMgr.GetLastUpdate()); _numBids = fields.Read(3); _bidder = fields.Read(4); // Either no bidder or existing player if (_bidder != 0 && Global.CharacterCacheStorage.GetCharacterAccountIdByGuid(ObjectGuid.Create(HighGuid.Player, _bidder)) == 0) // Probably a better way to check if player exists { Log.outError(LogFilter.Misc, "Black market auction {0} does not have a valid bidder (GUID: {1}).", _marketId, _bidder); return false; } return true; } public void SaveToDB(SQLTransaction trans) { PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.INS_BLACKMARKET_AUCTIONS); stmt.AddValue(0, _marketId); stmt.AddValue(1, _currentBid); stmt.AddValue(2, GetExpirationTime()); stmt.AddValue(3, _numBids); stmt.AddValue(4, _bidder); trans.Append(stmt); } public void DeleteFromDB(SQLTransaction trans) { PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.DEL_BLACKMARKET_AUCTIONS); stmt.AddValue(0, _marketId); trans.Append(stmt); } public bool ValidateBid(ulong bid) { if (bid <= _currentBid) return false; if (bid < _currentBid + GetMinIncrement()) return false; if (bid >= BlackMarketConst.MaxBid) return false; return true; } public void PlaceBid(ulong bid, Player player, SQLTransaction trans) //Updated { if (bid < _currentBid) return; _currentBid = bid; ++_numBids; if (GetSecondsRemaining() < 30 * Time.Minute) _secondsRemaining += 30 * Time.Minute; _bidder = player.GetGUID().GetCounter(); player.ModifyMoney(-(long)bid); PreparedStatement stmt = CharacterDatabase.GetPreparedStatement(CharStatements.UPD_BLACKMARKET_AUCTIONS); stmt.AddValue(0, _currentBid); stmt.AddValue(1, GetExpirationTime()); stmt.AddValue(2, _numBids); stmt.AddValue(3, _bidder); stmt.AddValue(4, _marketId); trans.Append(stmt); Global.BlackMarketMgr.Update(true); } public string BuildAuctionMailSubject(BMAHMailAuctionAnswers response) { return GetTemplate().Item.ItemID + ":0:" + response + ':' + GetMarketId() + ':' + GetTemplate().Quantity; } public string BuildAuctionMailBody() { return GetTemplate().SellerNPC + ":" + _currentBid; } public uint GetMarketId() { return _marketId; } public ulong GetCurrentBid() { return _currentBid; } void SetCurrentBid(ulong bid) { _currentBid = bid; } public uint GetNumBids() { return _numBids; } void SetNumBids(uint numBids) { _numBids = numBids; } public ulong GetBidder() { return _bidder; } void SetBidder(ulong bidder) { _bidder = bidder; } public ulong GetMinIncrement() { return (_currentBid / 20) - ((_currentBid / 20) % MoneyConstants.Gold); } //5% increase every bid (has to be round gold value) public void MailSent() { _mailSent = true; } // Set when mail has been sent public bool GetMailSent() { return _mailSent; } uint _marketId; ulong _currentBid; uint _numBids; ulong _bidder; uint _secondsRemaining; bool _mailSent; } }