diff --git a/Libraries/Core/Controllers/RagfairController.cs b/Libraries/Core/Controllers/RagfairController.cs index 8febe3a6..98e97c75 100644 --- a/Libraries/Core/Controllers/RagfairController.cs +++ b/Libraries/Core/Controllers/RagfairController.cs @@ -512,9 +512,95 @@ public class RagfairController * @param output Response to send to client * @returns IItemEventRouterResponse */ - private ItemEventRouterResponse CreateMultiOffer(string sessionId, AddOfferRequestData offerRequest, SptProfile fullProfile, ItemEventRouterResponse output) + private ItemEventRouterResponse CreateMultiOffer(string sessionID, AddOfferRequestData offerRequest, SptProfile fullProfile, ItemEventRouterResponse output) { - throw new NotImplementedException(); + var pmcData = fullProfile.CharacterData.PmcData; + var itemsToListCount = offerRequest.Items.Count; // Does not count stack size, only items + + // multi-offers are all the same item, + // Get first item and its children and use as template + var firstListingAndChidren = _itemHelper.FindAndReturnChildrenAsItems( + pmcData.Inventory.Items, + offerRequest.Items[0]); + + // Find items to be listed on flea (+ children) from player inventory + var result = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items); + if (result.Items is null || !string.IsNullOrEmpty(result.ErrorMessage)) + { + _httpResponseUtil.AppendErrorToOutput(output, result.ErrorMessage); + } + + // Total count of items summed using their stack counts + var stackCountTotal = _ragfairOfferHelper.GetTotalStackCountSize(result.Items); + + // When listing identical items on flea, condense separate items into one stack with a merged stack count + // e.g. 2 ammo items, stackObjectCount = 3 for each, will result in 1 stack of 6 + + firstListingAndChidren[0].Upd ??= new Upd{ }; + + firstListingAndChidren[0].Upd.StackObjectsCount = stackCountTotal; + + // Create flea object + var offer = CreatePlayerOffer(sessionID, offerRequest.Requirements, firstListingAndChidren, false); + + // This is the item that will be listed on flea, has merged stackObjectCount + var newRootOfferItem = offer.Items[0]; + + // Average offer price for single item (or whole weapon) + var averages = GetItemMinAvgMaxFleaPriceValues(new GetMarketPriceRequestData{ TemplateId = offer.Items[0].Template }); + var averageOfferPrice = averages.Avg; + + // Check for and apply item price modifer if it exists in config + if (_ragfairConfig.Dynamic.ItemPriceMultiplier.TryGetValue(newRootOfferItem.Template, out var itemPriceModifer)) + { + averageOfferPrice *= itemPriceModifer; + } + + // Get average of item+children quality + var qualityMultiplier = _itemHelper.GetItemQualityModifierForItems(offer.Items, true); + + // Multiply single item price by quality + averageOfferPrice *= qualityMultiplier; + + // Get price player listed items for in roubles + var playerListedPriceInRub = CalculateRequirementsPriceInRub(offerRequest.Requirements); + + // Roll sale chance + var sellChancePercent = _ragfairSellHelper.CalculateSellChance( + averageOfferPrice.Value, + playerListedPriceInRub, + qualityMultiplier); + + // Create array of sell times for items listed + offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal); + + // Subtract flea market fee from stash + if (_ragfairConfig.Sell.Fees) + { + var taxFeeChargeFailed = ChargePlayerTaxFee( + sessionID, + newRootOfferItem, + pmcData, + playerListedPriceInRub, + (int)stackCountTotal, + offerRequest, + output); + if (taxFeeChargeFailed) + { + return output; + } + } + + // Add offer to players profile + add to client response + fullProfile.CharacterData.PmcData.RagfairInfo.Offers.Add(offer); + output.ProfileChanges[sessionID].RagFairOffers.Add(offer); + + // Remove items from inventory after creating offer + foreach (var itemToRemove in offerRequest.Items) { + _inventoryHelper.RemoveItem(pmcData, itemToRemove, sessionID, output); + } + + return output; } /** @@ -549,9 +635,9 @@ public class RagfairController // Find items to be listed on flea from player inventory var result = GetItemsToListOnFleaFromInventory(pmcData, offerRequest.Items); - if (result.Items is null || result.error is not null) + if (result.Items is null || result.ErrorMessage is not null) { - _httpResponseUtil.AppendErrorToOutput(output, result.errorMessage); + _httpResponseUtil.AppendErrorToOutput(output, result.ErrorMessage); } // Total count of items summed using their stack counts @@ -589,7 +675,7 @@ public class RagfairController playerListedPriceInRub, qualityMultiplier ); - offer.SellResult = _ragfairSellHelper.RollForSale(sellChancePercent, stackCountTotal); + offer.SellResults = _ragfairSellHelper.RollForSale(sellChancePercent, (int)stackCountTotal); // Subtract flea market fee from stash if (_ragfairConfig.Sell.Fees) @@ -599,7 +685,7 @@ public class RagfairController rootItem, pmcData, playerListedPriceInRub, - stackCountTotal, + (int)stackCountTotal, offerRequest, output ); @@ -736,7 +822,7 @@ public class RagfairController return requirementsPriceInRub; } - private dynamic GetItemsToListOnFleaFromInventory(PmcData pmcData, List itemIdsFromFleaOfferRequest) + private GetItemsToListOnFleaFromInventoryResult GetItemsToListOnFleaFromInventory(PmcData pmcData, List itemIdsFromFleaOfferRequest) { List> itemsToReturn = []; var errorMessage = string.Empty; @@ -750,7 +836,7 @@ public class RagfairController errorMessage = _localisationService.GetText("ragfair-unable_to_find_item_in_inventory", new { id = itemId }); _logger.Error(errorMessage); - return new { itemsToReturn, errorMessage }; + return new GetItemsToListOnFleaFromInventoryResult { Items = itemsToReturn, ErrorMessage = errorMessage }; } item = _itemHelper.FixItemStackCount(item); @@ -762,10 +848,16 @@ public class RagfairController errorMessage = _localisationService.GetText("ragfair-unable_to_find_requested_items_in_inventory"); _logger.Error(errorMessage); - return new { ErrorMessage = errorMessage }; + return new GetItemsToListOnFleaFromInventoryResult { ErrorMessage = errorMessage }; } - return new { Items = itemsToReturn, ErrorMessage = errorMessage }; + return new GetItemsToListOnFleaFromInventoryResult { Items = itemsToReturn, ErrorMessage = errorMessage }; + } + + public record GetItemsToListOnFleaFromInventoryResult + { + public List>? Items { get; set; } + public string? ErrorMessage { get; set; } } public ItemEventRouterResponse RemoveOffer(RemoveOfferRequestData removeRequest, string sessionId)