diff --git a/Libraries/Core/Controllers/MatchController.cs b/Libraries/Core/Controllers/MatchController.cs index c7f8182b..af5a7b26 100644 --- a/Libraries/Core/Controllers/MatchController.cs +++ b/Libraries/Core/Controllers/MatchController.cs @@ -1,20 +1,35 @@ +using Core.Context; using SptCommon.Annotations; using Core.Models.Eft.Match; +using Core.Models.Spt.Config; +using Core.Models.Utils; +using Core.Servers; +using Core.Services; +using Core.Utils.Cloners; namespace Core.Controllers; [Injectable] public class MatchController( - + ISptLogger _logger, + SaveServer _saveServer, + MatchLocationService _matchLocationService, + ConfigServer _configServer, + ApplicationContext _applicationContext, + LocationLifecycleService _locationLifecycleService, + ICloner _cloner ) { + protected MatchConfig _matchConfig = _configServer.GetConfig(); + protected PmcConfig _pmcConfig = _configServer.GetConfig(); + /// /// /// /// public bool GetEnabled() { - throw new NotImplementedException(); + return _matchConfig.Enabled; } /// @@ -23,7 +38,7 @@ public class MatchController( /// public void DeleteGroup(object info) // TODO: info is `any` in the node server { - throw new NotImplementedException(); + _matchLocationService.DeleteGroup(info); } /// @@ -32,11 +47,33 @@ public class MatchController( /// /// /// - public ProfileStatusResponse JoinMatch( - MatchGroupStartGameRequest info, - string sessionId) + public ProfileStatusResponse JoinMatch(MatchGroupStartGameRequest info, string sessionId) { - throw new NotImplementedException(); + ProfileStatusResponse output = new ProfileStatusResponse + { + MaxPveCountExceeded = false, + // get list of players joining into the match + Profiles = + [ + new SessionStatus + { + ProfileId = "TODO", + ProfileToken = "TODO", + Status = "MatchWait", + Sid = "", + Ip = "", + Port = 0, + Version = "live", + Location = "TODO get location", + RaidMode = "Online", + Mode = "deathmatch", + ShortId = null, + AdditionalInfo = null + } + ] + }; + + return output; } /// @@ -44,10 +81,13 @@ public class MatchController( /// /// /// - public MatchGroupStatusResponse GetGroupStatus( - MatchGroupStatusRequest info) + public MatchGroupStatusResponse GetGroupStatus(MatchGroupStatusRequest info) { - throw new NotImplementedException(); + return new MatchGroupStatusResponse() + { + Players = [], + MaxPveCountExceeded = false + }; } /// @@ -55,11 +95,20 @@ public class MatchController( /// /// /// - public void ConfigureOfflineRaid( - GetRaidConfigurationRequestData request, - string sessionId) + public void ConfigureOfflineRaid(GetRaidConfigurationRequestData request, string sessionId) { - throw new NotImplementedException(); + // Store request data for access during bot generation + _applicationContext.AddValue(ContextVariableType.RAID_CONFIGURATION, request); + + // TODO: add code to strip PMC of equipment now they've started the raid + + // Set pmcs to difficulty set in pre-raid screen if override in bot config isnt enabled + if (!_pmcConfig.UseDifficultyOverride) + { + _pmcConfig.Difficulty = ConvertDifficultyDropdownIntoBotDifficulty( + request.WavesSettings.BotDifficulty.ToString() + ); + } } /// @@ -67,10 +116,15 @@ public class MatchController( /// /// dropdown difficulty value /// bot difficulty - private string ConvertDifficultyDropdownIntoBotDifficulty( - string botDifficulty) + private string ConvertDifficultyDropdownIntoBotDifficulty(string botDifficulty) { - throw new NotImplementedException(); + // Edge case medium - must be altered + if (botDifficulty.ToLower() == "medium") + { + return "normal"; + } + + return botDifficulty; } /// @@ -79,11 +133,9 @@ public class MatchController( /// /// /// - public StartLocalRaidResponseData StartLocalRaid( - string sessionId, - StartLocalRaidRequestData request) + public StartLocalRaidResponseData StartLocalRaid(string sessionId, StartLocalRaidRequestData request) { - throw new NotImplementedException(); + return _locationLifecycleService.StartLocalRaid(sessionId, request); } /// @@ -91,10 +143,8 @@ public class MatchController( /// /// /// - public void EndLocalRaid( - string sessionId, - EndLocalRaidRequestData request) + public void EndLocalRaid(string sessionId, EndLocalRaidRequestData request) { - throw new NotImplementedException(); + _locationLifecycleService.EndLocalRaid(sessionId, request); } } diff --git a/Libraries/Core/Controllers/RagfairController.cs b/Libraries/Core/Controllers/RagfairController.cs index 40b7ae0b..8a08545d 100644 --- a/Libraries/Core/Controllers/RagfairController.cs +++ b/Libraries/Core/Controllers/RagfairController.cs @@ -73,7 +73,7 @@ public class RagfairController RagfairPriceService ragfairPriceService, RagfairOfferGenerator ragfairOfferGenerator, ConfigServer configServer - ) + ) { _logger = logger; _timeUtil = timeUtil; @@ -108,7 +108,8 @@ public class RagfairController */ public void Update() { - foreach (var (sessionId, profile) in _profileHelper.GetProfiles()) { + foreach (var (sessionId, profile) in _profileHelper.GetProfiles()) + { // Check profile is capable of creating offers var pmcProfile = profile.CharacterData.PmcData; if ( @@ -133,8 +134,9 @@ public class RagfairController var itemsToAdd = _ragfairHelper.FilterCategories(sessionID, searchRequest); var traderAssorts = _ragfairHelper.GetDisplayableAssorts(sessionID); - var result = new GetOffersResult{ - Offers = new List(), + var result = new GetOffersResult + { + Offers = new List(), OffersCount = searchRequest.Limit, SelectedCategory = searchRequest.HandbookId, }; @@ -153,7 +155,8 @@ public class RagfairController result.Offers = _ragfairSortHelper.SortOffers( result.Offers, searchRequest.SortType.Value, - searchRequest.SortDirection.Value); + searchRequest.SortDirection.Value + ); // Match offers with quests and lock unfinished quests - get offers from traders foreach (var traderOffer in result.Offers.Where(offer => _ragfairOfferHelper.OfferIsFromTrader(offer))) @@ -179,6 +182,7 @@ public class RagfairController var end = (int)Math.Min((double)((searchRequest.Page + 1) * searchRequest.Limit), result.Offers.Count); result.Offers = result.Offers.Slice(start.Value, end); } + return result; } @@ -195,10 +199,15 @@ public class RagfairController if (assortPurchased is null) { _logger.Warning( - _localisationService.GetText("ragfair-unable_to_adjust_stack_count_assort_not_found", new { - offerId = offer.Items.First().Id, - traderId = offer.User.Id, - })); + _localisationService.GetText( + "ragfair-unable_to_adjust_stack_count_assort_not_found", + new + { + offerId = offer.Items.First().Id, + traderId = offer.User.Id, + } + ) + ); return; } @@ -221,9 +230,9 @@ public class RagfairController var assortData = traderAssorts.FirstOrDefault((item) => item.Id == assortId); // Use value stored in profile, otherwise use value directly from in-memory trader assort data - offer.BuyRestrictionCurrent = fullProfile.TraderPurchases[offer.User.Id][assortId] is not null + offer.BuyRestrictionCurrent = (int)(fullProfile.TraderPurchases[offer.User.Id][assortId] is not null ? fullProfile.TraderPurchases[offer.User.Id][assortId].PurchaseCount - : assortData.Upd.BuyRestrictionCurrent; + : assortData.Upd.BuyRestrictionCurrent); offer.BuyRestrictionMax = assortData.Upd.BuyRestrictionMax; } @@ -236,7 +245,8 @@ public class RagfairController { var counter = 0; - foreach (var offer in offers) { + foreach (var offer in offers) + { offer.InternalId = ++counter; } } @@ -251,7 +261,7 @@ public class RagfairController { // Linked/required search categories var playerHasFleaUnlocked = - pmcProfile.Info.Level >= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel; + pmcProfile.Info.Level >= _databaseService.GetGlobals().Configuration.RagFair.MinUserLevel; List offerPool = []; if (IsLinkedSearch(searchRequest) || IsRequiredSearch(searchRequest)) { @@ -300,7 +310,8 @@ public class RagfairController * @param pmcProfile Player profile * @returns array of offers */ - private List GetOffersForSearchType(SearchRequestData searchRequest, List itemsToAdd, Dictionary traderAssorts, PmcData pmcProfile) + private List GetOffersForSearchType(SearchRequestData searchRequest, List itemsToAdd, Dictionary traderAssorts, + PmcData pmcProfile) { // Searching for items in preset menu if (searchRequest.BuildCount is not null) @@ -337,7 +348,7 @@ public class RagfairController // Get the average offer price, excluding barter offers var average = GetAveragePriceFromOffers(offers, minMax, ignoreTraderOffers); - return new GetItemPriceResult{ Avg = Math.Round(average), Min = minMax.Min, Max = minMax.Max }; + return new GetItemPriceResult { Avg = Math.Round(average), Min = minMax.Min, Max = minMax.Max }; } // No offers listed, get price from live ragfair price list prices.json @@ -347,8 +358,8 @@ public class RagfairController { tplPrice = _handbookHelper.GetTemplatePrice(getPriceRequest.TemplateId) ?? 0; } - - return new GetItemPriceResult{ Avg = tplPrice, Min = tplPrice, Max = tplPrice }; + + return new GetItemPriceResult { Avg = tplPrice, Min = tplPrice, Max = tplPrice }; } private double GetAveragePriceFromOffers(List offers, MinMax minMax, bool ignoreTraderOffers) @@ -476,6 +487,7 @@ public class RagfairController { return FleaOfferType.SINGLE; } + if (offerRequest.Items.Count > 1) { return FleaOfferType.MULTI; @@ -529,7 +541,8 @@ public class RagfairController * @param output Response to send to client * @returns IItemEventRouterResponse */ - private ItemEventRouterResponse CreateSingleOffer(string sessionID, AddOfferRequestData offerRequest, SptProfile fullProfile, ItemEventRouterResponse output) + private ItemEventRouterResponse CreateSingleOffer(string sessionID, AddOfferRequestData offerRequest, SptProfile fullProfile, + ItemEventRouterResponse output) { var pmcData = fullProfile.CharacterData.PmcData; //var itemsToListCount = offerRequest.Items.Count; // Does not count stack size, only items @@ -550,14 +563,15 @@ public class RagfairController sessionID, offerRequest.Requirements, result.Items.First(), - false); + false + ); var rootItem = offer.Items.First(); // Get average of items quality+children var qualityMultiplier = _itemHelper.GetItemQualityModifierForItems(offer.Items, true); // Average offer price for single item (or whole weapon) - var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData{ TemplateId = rootItem.Template }); + var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData { TemplateId = rootItem.Template }); var averageOfferPriceSingleItem = averages.Avg; // Check for and apply item price modifer if it exists in config @@ -573,7 +587,8 @@ public class RagfairController var sellChancePercent = _ragfairSellHelper.CalculateSellChance( averageOfferPriceSingleItem.Value, playerListedPriceInRub, - qualityMultiplier); + qualityMultiplier + ); offer.SellResult = _ragfairSellHelper.RollForSale(sellChancePercent, stackCountTotal); // Subtract flea market fee from stash @@ -586,7 +601,8 @@ public class RagfairController playerListedPriceInRub, stackCountTotal, offerRequest, - output); + output + ); if (taxFeeChargeFailed) { return output; @@ -598,7 +614,8 @@ public class RagfairController output.ProfileChanges[sessionID].RagFairOffers.Add(offer); // Remove items from inventory after creating offer - foreach (var itemToRemove in offerRequest.Items) { + foreach (var itemToRemove in offerRequest.Items) + { _inventoryHelper.RemoveItem(pmcData, itemToRemove, sessionID, output); } @@ -634,9 +651,10 @@ public class RagfairController pmcData, requirementsPriceInRub, itemStackCount, - offerRequest.SellInOnePiece.GetValueOrDefault(false)); + offerRequest.SellInOnePiece.GetValueOrDefault(false) + ); - _logger.Debug($"Offer tax to charge: { tax}, pulled from client: { storedClientTaxValue.Count is not null}"); + _logger.Debug($"Offer tax to charge: {tax}, pulled from client: {storedClientTaxValue.Count is not null}"); // cleanup of cache now we've used the tax value from it _ragfairTaxService.ClearStoredOfferTaxById(offerRequest.Items.First()); @@ -647,7 +665,8 @@ public class RagfairController { _httpResponseUtil.AppendErrorToOutput( output, - _localisationService.GetText("ragfair-unable_to_pay_commission_fee", tax)); + _localisationService.GetText("ragfair-unable_to_pay_commission_fee", tax) + ); return true; } @@ -657,18 +676,25 @@ public class RagfairController private RagfairOffer CreatePlayerOffer(string sessionId, List requirements, List items, bool sellInOnePiece) { var loyalLevel = 1; - var formattedItems = items.Select(item => { - var isChild = items.Any((subItem) => subItem.Id == item.ParentId); + var formattedItems = items.Select( + item => + { + var isChild = items.Any((subItem) => subItem.Id == item.ParentId); - return new Item { - Id = item.Id, - Template = item.Template, - ParentId = isChild ? item.ParentId: "hideout", - SlotId = isChild ? item.SlotId: "hideout", - Upd = item.Upd }; - }); + return new Item + { + Id = item.Id, + Template = item.Template, + ParentId = isChild ? item.ParentId : "hideout", + SlotId = isChild ? item.SlotId : "hideout", + Upd = item.Upd + }; + } + ); - var formattedRequirements = requirements.Select(item => new BarterScheme{ + var formattedRequirements = requirements.Select( + item => new BarterScheme + { Template = item.Template, Count = item.Count, OnlyFunctional = item.OnlyFunctional, @@ -681,7 +707,8 @@ public class RagfairController formattedItems.ToList(), formattedRequirements.ToList(), loyalLevel, - sellInOnePiece); + sellInOnePiece + ); } /** @@ -692,7 +719,8 @@ public class RagfairController private double CalculateRequirementsPriceInRub(List requirements) { var requirementsPriceInRub = 0d; - foreach (var item in requirements) { + foreach (var item in requirements) + { var requestedItemTpl = item.Template; if (_paymentHelper.IsMoneyTpl(requestedItemTpl)) @@ -710,15 +738,16 @@ public class RagfairController private dynamic GetItemsToListOnFleaFromInventory(PmcData pmcData, List itemIdsFromFleaOfferRequest) { - List > itemsToReturn = []; + List> itemsToReturn = []; var errorMessage = string.Empty; // Count how many items are being sold and multiply the requested amount accordingly - foreach (var itemId in itemIdsFromFleaOfferRequest) { + foreach (var itemId in itemIdsFromFleaOfferRequest) + { var item = pmcData.Inventory.Items.FirstOrDefault((i) => i.Id == itemId); if (item is null) { - errorMessage = _localisationService.GetText("ragfair-unable_to_find_item_in_inventory", new { id = itemId}); + errorMessage = _localisationService.GetText("ragfair-unable_to_find_item_in_inventory", new { id = itemId }); _logger.Error(errorMessage); return new { itemsToReturn, errorMessage }; @@ -748,9 +777,15 @@ public class RagfairController if (playerProfileOffers is null) { _logger.Warning( - _localisationService.GetText("ragfair-unable_to_remove_offer_not_found_in_profile", new { - profileId = sessionId, - offerId = removeRequest.OfferId })); + _localisationService.GetText( + "ragfair-unable_to_remove_offer_not_found_in_profile", + new + { + profileId = sessionId, + offerId = removeRequest.OfferId + } + ) + ); pmcData.RagfairInfo.Offers = new List(); } @@ -759,11 +794,18 @@ public class RagfairController if (playerOfferIndex == -1) { _logger.Error( - _localisationService.GetText("ragfair-offer_not_found_in_profile", new { - offerId = removeRequest.OfferId })); + _localisationService.GetText( + "ragfair-offer_not_found_in_profile", + new + { + offerId = removeRequest.OfferId + } + ) + ); return _httpResponseUtil.AppendErrorToOutput( output, - _localisationService.GetText("ragfair-offer_not_found_in_profile_short")); + _localisationService.GetText("ragfair-offer_not_found_in_profile_short") + ); } var differenceInSeconds = playerProfileOffers[playerOfferIndex].EndTime - _timeUtil.GetTimeStamp(); @@ -789,8 +831,14 @@ public class RagfairController if (playerOfferIndex == -1) { _logger.Warning( - _localisationService.GetText("ragfair-offer_not_found_in_profile", new { - offerId = extendRequest.OfferId })); + _localisationService.GetText( + "ragfair-offer_not_found_in_profile", + new + { + offerId = extendRequest.OfferId + } + ) + ); return _httpResponseUtil.AppendErrorToOutput(output, _localisationService.GetText("ragfair-offer_not_found_in_profile_short")); } @@ -803,7 +851,7 @@ public class RagfairController var sellInOncePiece = playerOffer.SellInOnePiece.GetValueOrDefault(false); if (!sellInOncePiece) { - count = (int) playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0); + count = (int)playerOffer.Items.Sum(offerItem => offerItem.Upd?.StackObjectsCount ?? 0); } var tax = _ragfairTaxService.CalculateTax( @@ -811,7 +859,8 @@ public class RagfairController pmcData, playerOffer.RequirementsCost.Value, count, - sellInOncePiece); + sellInOncePiece + ); var request = CreateBuyTradeRequestObject("RUB", tax); _paymentService.PayMoney(pmcData, request, sessionId, output); @@ -819,7 +868,8 @@ public class RagfairController { return _httpResponseUtil.AppendErrorToOutput( output, - _localisationService.GetText("ragfair-unable_to_pay_commission_fee")); + _localisationService.GetText("ragfair-unable_to_pay_commission_fee") + ); } } @@ -854,7 +904,8 @@ public class RagfairController return _ragfairPriceService.GetAllFleaPrices(); } - public Dictionary GetStaticPrices() { + public Dictionary GetStaticPrices() + { return _ragfairPriceService.GetAllStaticPrices(); } diff --git a/Libraries/Core/Helpers/TraderAssortHelper.cs b/Libraries/Core/Helpers/TraderAssortHelper.cs index 76bf4e1b..8ad4a3d7 100644 --- a/Libraries/Core/Helpers/TraderAssortHelper.cs +++ b/Libraries/Core/Helpers/TraderAssortHelper.cs @@ -92,7 +92,7 @@ public class TraderAssortHelper( continue; } - assortToAdjust.Upd.BuyRestrictionCurrent = assortPurchasesfromTrader[assortId.Key].PurchaseCount; + assortToAdjust.Upd.BuyRestrictionCurrent = (int)assortPurchasesfromTrader[assortId.Key].PurchaseCount; } // Get rid of quest locked assorts diff --git a/Libraries/Core/Helpers/TraderHelper.cs b/Libraries/Core/Helpers/TraderHelper.cs index b2e0001b..f0a9cde0 100644 --- a/Libraries/Core/Helpers/TraderHelper.cs +++ b/Libraries/Core/Helpers/TraderHelper.cs @@ -16,18 +16,22 @@ namespace Core.Helpers; [Injectable] public class TraderHelper( ISptLogger _logger, + DatabaseService _databaseService, + ProfileHelper _profileHelper, + HandbookHelper _handbookHelper, + ItemHelper _itemHelper, + PlayerService _playerService, + LocalisationService _localisationService, + FenceService _fenceService, TimeUtil _timeUtil, RandomUtil _randomUtil, - LocalisationService _localisationService, - ConfigServer _configServer, - ProfileHelper _profileHelper, - ItemHelper _itemHelper, - HandbookHelper _handbookHelper, - DatabaseService _databaseService + ConfigServer _configServer ) { protected TraderConfig _traderConfig = _configServer.GetConfig(); - private Dictionary _highestTraderPriceItems = new(); + protected Dictionary _highestTraderPriceItems = new(); + protected List _gameVersions = [GameEditions.EDGE_OF_DARKNESS, GameEditions.UNHEARD]; + /// /// Get a trader base object, update profile to reflect players current standing in profile @@ -223,7 +227,25 @@ public class TraderHelper( public TraderLoyaltyLevel GetLoyaltyLevel(string traderID, PmcData pmcData) { - throw new NotImplementedException(); + var traderBase = _databaseService.GetTrader(traderID).Base; + + int? loyaltyLevel = null; + if (pmcData.TradersInfo.TryGetValue(traderID, out var traderInfo)) + { + loyaltyLevel = traderInfo.LoyaltyLevel; + } + + if (loyaltyLevel is null or < 1) + { + loyaltyLevel = 1; + } + + if (loyaltyLevel > traderBase.LoyaltyLevels.Count) + { + loyaltyLevel = traderBase.LoyaltyLevels.Count; + } + + return traderBase.LoyaltyLevels[(loyaltyLevel - 1) ?? 1]; } /// @@ -233,10 +255,57 @@ public class TraderHelper( /// New item assort id + count public void AddTraderPurchasesToPlayerProfile( string sessionID, - object newPurchaseDetails, // TODO: TYPE FUCKEY { items: { itemId: string; count: number }[]; traderId: string } + KeyValuePair>, string> newPurchaseDetails, Item itemPurchased) { - throw new NotImplementedException(); + var profile = _profileHelper.GetFullProfile(sessionID); + var traderId = newPurchaseDetails.Value; + + // Iterate over assorts bought and add to profile + foreach (var purchasedItem in newPurchaseDetails.Key) + { + var currentTime = _timeUtil.GetTimeStamp(); + + // Nullguard traderPurchases + profile.TraderPurchases ??= new Dictionary?>(); + // Nullguard traderPurchases for this trader + profile.TraderPurchases[traderId] ??= new Dictionary(); + + // Null guard when dict doesnt exist + + if (profile.TraderPurchases[traderId][purchasedItem.Key] is null) + { + profile.TraderPurchases[traderId][purchasedItem.Key] = new TraderPurchaseData + { + PurchaseCount = purchasedItem.Value, + PurchaseTimestamp = currentTime, + }; + + continue; + } + + if (profile.TraderPurchases[traderId][purchasedItem.Key].PurchaseCount + purchasedItem.Value > + GetAccountTypeAdjustedTraderPurchaseLimit( + (double)itemPurchased.Upd.BuyRestrictionMax, + profile.CharacterData.PmcData.Info.GameVersion + ) + ) + { + throw new Exception( + _localisationService.GetText( + "trader-unable_to_purchase_item_limit_reached", + new + { + traderId = traderId, + limit = itemPurchased.Upd.BuyRestrictionMax, + } + ) + ); + } + + profile.TraderPurchases[traderId][purchasedItem.Key].PurchaseCount += purchasedItem.Value; + profile.TraderPurchases[traderId][purchasedItem.Key].PurchaseTimestamp = currentTime; + } } /// @@ -247,7 +316,12 @@ public class TraderHelper( /// buyRestrictionMax value public double GetAccountTypeAdjustedTraderPurchaseLimit(double buyRestrictionMax, string gameVersion) { - throw new NotImplementedException(); + if (_gameVersions.Contains(gameVersion)) + { + return Math.Floor(buyRestrictionMax * 1.2); + } + + return buyRestrictionMax; } /// @@ -258,7 +332,52 @@ public class TraderHelper( /// highest rouble cost for item public double GetHighestTraderPriceRouble(string tpl) { - throw new NotImplementedException(); + if (_highestTraderPriceItems is not null) + { + return (double)_highestTraderPriceItems[tpl]; + } + + if (_highestTraderPriceItems is null) + { + _highestTraderPriceItems = new Dictionary(); + } + + // Init dict and fill + foreach (var traderName in Traders.TradersDictionary) + { + // Skip some traders + if (traderName.Value == Traders.FENCE) + { + continue; + } + + // Get assorts for trader, skip trader if no assorts found + var traderAssorts = _databaseService.GetTrader(traderName.Value).Assort; + if (traderAssorts is null) + { + continue; + } + + // Get all item assorts that have parentid of hideout (base item and not a mod of other item) + foreach (var item in traderAssorts.Items.Where(x => x.ParentId == "hideout")) + { + // Get barter scheme (contains cost of item) + var barterScheme = traderAssorts.BarterScheme[item.Id].FirstOrDefault().FirstOrDefault(); + + // Convert into roubles + var roubleAmount = barterScheme.Template == Money.ROUBLES + ? barterScheme.Count + : _handbookHelper.InRUB(barterScheme.Count ?? 1, barterScheme.Template); + + // Existing price smaller in dict than current iteration, overwrite + if ((_highestTraderPriceItems[item.Template] ?? 0) < roubleAmount) + { + _highestTraderPriceItems[item.Template] = (int)roubleAmount; + } + } + } + + return (double)_highestTraderPriceItems[tpl]; } /// @@ -268,11 +387,12 @@ public class TraderHelper( /// Rouble price public double GetHighestSellToTraderPrice(string tpl) { - // Find the highest trader price for item - var highestPrice = 1d; // Default price - foreach (var traderName in Traders.TradersDictionary) { + // Find highest trader price for item + var highestPrice = 1; // Default price + foreach (var trader in Traders.TradersDictionary) + { // Get trader and check buy category allows tpl - var traderBase = _databaseService.GetTrader(traderName.Value).Base; + var traderBase = _databaseService.GetTrader(trader.Value).Base; // Skip traders that dont sell if (traderBase is null || !_itemHelper.IsOfBaseclasses(tpl, traderBase.ItemsBuy.Category)) @@ -287,12 +407,13 @@ public class TraderHelper( var itemHandbookPrice = _handbookHelper.GetTemplatePrice(tpl); var priceTraderBuysItemAt = Math.Round( - _randomUtil.GetPercentOfValue(traderBuyBackPricePercent.Value, itemHandbookPrice.Value)); + _randomUtil.GetPercentOfValue(traderBuyBackPricePercent ?? 0, itemHandbookPrice ?? 0) + ); // Price from this trader is higher than highest found, update if (priceTraderBuysItemAt > highestPrice) { - highestPrice = priceTraderBuysItemAt; + highestPrice = (int)priceTraderBuysItemAt; } } @@ -304,9 +425,17 @@ public class TraderHelper( /// /// Traders id /// Traders key - public Trader? GetTraderById(string traderId) + public TradersEnum? GetTraderById(string traderId) { - throw new NotImplementedException(); + var kvp = Traders.TradersDictionary.Where(x => x.Value == traderId); + + if (!kvp.Any()) { + _logger.Error(_localisationService.GetText("trader-unable_to_find_trader_in_enum", traderId)); + + return null; + } + + return kvp.FirstOrDefault().Key; } /// @@ -337,7 +466,7 @@ public class TraderHelper( /// True, values exists in Traders enum as a value public bool TraderEnumHasKey(string key) { - throw new NotImplementedException(); + return Traders.TradersDictionary.Any(x => x.Value == key); } /// @@ -347,7 +476,6 @@ public class TraderHelper( /// True if Traders enum has the param as a value public bool TraderEnumHasValue(string traderId) { - _logger.Error("HACK TraderEnumHasValue"); return Traders.TradersDictionary.ContainsValue(traderId); } } diff --git a/Libraries/Core/Models/Eft/Profile/SptProfile.cs b/Libraries/Core/Models/Eft/Profile/SptProfile.cs index d6d642fd..23eec21f 100644 --- a/Libraries/Core/Models/Eft/Profile/SptProfile.cs +++ b/Libraries/Core/Models/Eft/Profile/SptProfile.cs @@ -38,7 +38,7 @@ public record SptProfile /** Assort purchases made by player since last trader refresh */ [JsonPropertyName("traderPurchases")] - public Dictionary>? TraderPurchases { get; set; } + public Dictionary?>? TraderPurchases { get; set; } /** Achievements earned by player */ [JsonPropertyName("achievements")] @@ -55,7 +55,7 @@ public record SptProfile public record TraderPurchaseData { [JsonPropertyName("count")] - public int? PurchaseCount { get; set; } + public double? PurchaseCount { get; set; } [JsonPropertyName("purchaseTimestamp")] public long? PurchaseTimestamp { get; set; } diff --git a/Libraries/Core/Services/ItemFilterService.cs b/Libraries/Core/Services/ItemFilterService.cs index 82979f9a..0e44646d 100644 --- a/Libraries/Core/Services/ItemFilterService.cs +++ b/Libraries/Core/Services/ItemFilterService.cs @@ -16,8 +16,8 @@ public class ItemFilterService( { protected ItemConfig _itemConfig = _configServer.GetConfig(); - protected HashSet? _lootableItemBlacklistCache; - protected HashSet? _itemBlacklistCache; + protected HashSet? _lootableItemBlacklistCache = new HashSet(); + protected HashSet? _itemBlacklistCache = new HashSet(); /** * Check if the provided template id is blacklisted in config/item.json/blacklist diff --git a/Libraries/Core/Services/LocationLifecycleService.cs b/Libraries/Core/Services/LocationLifecycleService.cs index 4530df81..87d89fcb 100644 --- a/Libraries/Core/Services/LocationLifecycleService.cs +++ b/Libraries/Core/Services/LocationLifecycleService.cs @@ -22,7 +22,7 @@ public class LocationLifecycleService } /** Handle client/match/local/start */ - public void StartLocalRaid(string sessionId, StartLocalRaidRequestData request) + public StartLocalRaidResponseData StartLocalRaid(string sessionId, StartLocalRaidRequestData request) { throw new NotImplementedException(); } diff --git a/Server/Assets/database/settings.json b/Server/Assets/database/settings.json index 86346fde..b3d381fe 100644 --- a/Server/Assets/database/settings.json +++ b/Server/Assets/database/settings.json @@ -15,8 +15,8 @@ }, "FramerateLimit": { "MinFramerateLimit": 30, - "MaxFramerateLobbyLimit": 60, - "MaxFramerateGameLimit": 144 + "MaxFramerateLobbyLimit": 240, + "MaxFramerateGameLimit": 240 }, "ClientSendRateLimit": 120, "TurnOffLogging": false,