Implemented RagfairTaxService
This commit is contained in:
@@ -1,57 +1,216 @@
|
|||||||
using SptCommon.Annotations;
|
using Core.Helpers;
|
||||||
using Core.Models.Eft.Common;
|
using Core.Models.Eft.Common;
|
||||||
using Core.Models.Eft.Common.Tables;
|
using Core.Models.Eft.Common.Tables;
|
||||||
using Core.Models.Eft.Ragfair;
|
using Core.Models.Eft.Ragfair;
|
||||||
|
using Core.Models.Enums;
|
||||||
|
using Core.Models.Utils;
|
||||||
|
using Core.Utils.Cloners;
|
||||||
|
using SptCommon.Annotations;
|
||||||
|
|
||||||
namespace Core.Services;
|
namespace Core.Services;
|
||||||
|
|
||||||
[Injectable(InjectionType.Singleton)]
|
[Injectable(InjectionType.Singleton)]
|
||||||
public class RagfairTaxService
|
public class RagfairTaxService(
|
||||||
|
ISptLogger<RagfairTaxService> _logger,
|
||||||
|
DatabaseService _databaseService,
|
||||||
|
RagfairPriceService _ragfairPriceService,
|
||||||
|
ItemHelper _itemHelper,
|
||||||
|
ProfileHelper _profileHelper,
|
||||||
|
ICloner _cloner
|
||||||
|
)
|
||||||
{
|
{
|
||||||
|
protected Dictionary<string, StorePlayerOfferTaxAmountRequestData> _playerOfferTaxCache = new();
|
||||||
|
|
||||||
public void StoreClientOfferTaxValue(string sessionId, StorePlayerOfferTaxAmountRequestData offer)
|
public void StoreClientOfferTaxValue(string sessionId, StorePlayerOfferTaxAmountRequestData offer)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_playerOfferTaxCache[offer.Id] = offer;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ClearStoredOfferTaxById(string offerIdToRemove)
|
public void ClearStoredOfferTaxById(string offerIdToRemove)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
_playerOfferTaxCache.Remove(offerIdToRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
public StorePlayerOfferTaxAmountRequestData GetStoredClientOfferTaxValueById(string offerIdToGet)
|
public StorePlayerOfferTaxAmountRequestData GetStoredClientOfferTaxValueById(string offerIdToGet)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return _playerOfferTaxCache[offerIdToGet];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
// This method, along with CalculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice".
|
* // This method, along with CalculateItemWorth, is trying to mirror the client-side code found in the method "CalculateTaxPrice".
|
||||||
// It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary.
|
* // It's structured to resemble the client-side code as closely as possible - avoid making any big structure changes if it's not necessary.
|
||||||
* @param item Item being sold on flea
|
* * @param item Item being sold on flea
|
||||||
* @param pmcData player profile
|
* * @param pmcData player profile
|
||||||
* @param requirementsValue
|
* * @param requirementsValue
|
||||||
* @param offerItemCount Number of offers being created
|
* * @param offerItemCount Number of offers being created
|
||||||
* @param sellInOnePiece
|
* * @param sellInOnePiece
|
||||||
* @returns Tax in roubles
|
* * @returns Tax in roubles
|
||||||
*/
|
*/
|
||||||
public double CalculateTax(
|
public double CalculateTax(
|
||||||
Item item,
|
Item item,
|
||||||
PmcData pmcData,
|
PmcData pmcData,
|
||||||
double requirementsValue,
|
double? requirementsValue,
|
||||||
int offerItemCount,
|
int? offerItemCount,
|
||||||
bool sellInOnePiece)
|
bool sellInOnePiece)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
if (requirementsValue is null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offerItemCount is null)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var globals = _databaseService.GetGlobals();
|
||||||
|
|
||||||
|
var itemTemplate = _itemHelper.GetItem(item.Template).Value;
|
||||||
|
var itemWorth = CalculateItemWorth(item, itemTemplate, offerItemCount.Value, pmcData);
|
||||||
|
var requirementsPrice = requirementsValue * (sellInOnePiece ? 1 : offerItemCount);
|
||||||
|
|
||||||
|
var itemTaxMult = globals.Configuration.RagFair.CommunityItemTax / 100.0;
|
||||||
|
var requirementTaxMult = globals.Configuration.RagFair.CommunityRequirementTax / 100.0;
|
||||||
|
|
||||||
|
var itemPriceMult = Math.Log10(itemWorth / requirementsPrice.Value);
|
||||||
|
var requirementPriceMult = Math.Log10(requirementsPrice.Value / itemWorth);
|
||||||
|
|
||||||
|
if (requirementsPrice >= itemWorth)
|
||||||
|
{
|
||||||
|
requirementPriceMult = Math.Pow(requirementPriceMult, 1.08);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
itemPriceMult = Math.Pow(itemPriceMult, 1.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
itemPriceMult = Math.Pow(4.0, itemPriceMult);
|
||||||
|
requirementPriceMult = Math.Pow(4.0, requirementPriceMult);
|
||||||
|
|
||||||
|
var hideoutFleaTaxDiscountBonusSum = _profileHelper.GetBonusValueFromProfile(
|
||||||
|
pmcData,
|
||||||
|
BonusType.RagfairCommission
|
||||||
|
);
|
||||||
|
// A negative bonus implies a lower discount, since we subtract later, invert the value here
|
||||||
|
var taxDiscountPercent = -(hideoutFleaTaxDiscountBonusSum / 100.0);
|
||||||
|
|
||||||
|
var tax =
|
||||||
|
itemWorth * itemTaxMult * itemPriceMult + requirementsPrice * requirementTaxMult * requirementPriceMult;
|
||||||
|
var discountedTax = tax * (1.0 - taxDiscountPercent);
|
||||||
|
var itemComissionMult = itemTemplate.Properties.RagFairCommissionModifier.HasValue
|
||||||
|
? itemTemplate.Properties.RagFairCommissionModifier.Value
|
||||||
|
: 1;
|
||||||
|
|
||||||
|
if (item.Upd.Buff is not null)
|
||||||
|
{
|
||||||
|
var buffType = item.Upd.Buff.BuffType;
|
||||||
|
var itemEnhancementSettings =
|
||||||
|
_databaseService.GetGlobals().Configuration.RepairSettings.ItemEnhancementSettings;
|
||||||
|
var priceModiferValue = buffType switch
|
||||||
|
{
|
||||||
|
"DamageReduction" => itemEnhancementSettings.DamageReduction.PriceModifierValue.Value,
|
||||||
|
"MalfunctionProtections" => itemEnhancementSettings.MalfunctionProtections.PriceModifierValue.Value,
|
||||||
|
"WeaponSpread" => itemEnhancementSettings.WeaponSpread.PriceModifierValue.Value,
|
||||||
|
_ => 1d
|
||||||
|
};
|
||||||
|
discountedTax *= 1.0 + Math.Abs(item.Upd.Buff.Value.Value - 1.0) * priceModiferValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxValue = Math.Round(discountedTax.Value * itemComissionMult);
|
||||||
|
_logger.Debug("Tax Calculated to be: {taxValue}");
|
||||||
|
|
||||||
|
return taxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is trying to replicate the item worth calculation method found in the client code.
|
// This method is trying to replicate the item worth calculation method found in the client code.
|
||||||
// Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring.
|
// Any inefficiencies or style issues are intentional and should not be fixed, to preserve the client-side code mirroring.
|
||||||
protected double CalculateItemWorth(
|
protected double CalculateItemWorth(
|
||||||
Dictionary<string, object> item,
|
Item item,
|
||||||
Dictionary<string, object> itemTemplate,
|
TemplateItem itemTemplate,
|
||||||
int itemCount,
|
int itemCount,
|
||||||
Dictionary<string, object> pmcData,
|
PmcData pmcData,
|
||||||
bool isRootItem = true)
|
bool isRootItem = true)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var worth = _ragfairPriceService.GetFleaPriceForItem(item.Template);
|
||||||
|
|
||||||
|
// In client, all item slots are traversed and any items contained within have their values added
|
||||||
|
if (isRootItem)
|
||||||
|
{
|
||||||
|
// Since we get a flat list of all child items, we only want to recurse from parent item
|
||||||
|
var itemChildren = _itemHelper.FindAndReturnChildrenAsItems(pmcData.Inventory.Items, item.Id);
|
||||||
|
if (itemChildren.Count > 1)
|
||||||
|
{
|
||||||
|
var itemChildrenClone = _cloner.Clone(itemChildren); // Clone is expensive, only run if necessary
|
||||||
|
foreach (var child in itemChildrenClone.Where(child => child.Id != item.Id))
|
||||||
|
{
|
||||||
|
child.Upd ??= new Upd();
|
||||||
|
|
||||||
|
worth += CalculateItemWorth(
|
||||||
|
child,
|
||||||
|
_itemHelper.GetItem(child.Template).Value,
|
||||||
|
(int)(child.Upd.StackObjectsCount ?? 1),
|
||||||
|
pmcData,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var upd = item.Upd ??= new Upd();
|
||||||
|
|
||||||
|
if (upd.Dogtag is not null)
|
||||||
|
{
|
||||||
|
worth *= upd.Dogtag.Level.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemTemplate.Properties is null)
|
||||||
|
{
|
||||||
|
_logger.Warning($"Item: {item.Id} lacks _props and cannot have its worth calculated properly");
|
||||||
|
|
||||||
|
return worth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.Key is not null && (itemTemplate.Properties.MaximumNumberOfUsage ?? 0) > 0)
|
||||||
|
{
|
||||||
|
worth =
|
||||||
|
worth /
|
||||||
|
(itemTemplate.Properties.MaximumNumberOfUsage ?? 1) *
|
||||||
|
((itemTemplate.Properties.MaximumNumberOfUsage ?? 1) - upd.Key.NumberOfUsages.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.Resource is not null && (itemTemplate.Properties.MaxResource ?? 0) > 0)
|
||||||
|
{
|
||||||
|
worth = (double)(worth * 0.1 +
|
||||||
|
(worth * 0.9 / (itemTemplate.Properties.MaxResource ?? 1) * upd.Resource.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.SideEffect is not null && (itemTemplate.Properties.MaxResource ?? 0) > 0)
|
||||||
|
{
|
||||||
|
worth = (double)(worth * 0.1 +
|
||||||
|
worth * 0.9 / (itemTemplate.Properties.MaxResource ?? 1) * upd.SideEffect.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.MedKit is not null && (itemTemplate.Properties.MaxHpResource ?? 0) > 0)
|
||||||
|
{
|
||||||
|
worth = worth / (itemTemplate.Properties.MaxHpResource ?? 1) * upd.MedKit.HpResource.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.FoodDrink is not null && (itemTemplate.Properties.MaxResource ?? 0) > 0)
|
||||||
|
{
|
||||||
|
worth = worth / (itemTemplate.Properties.MaxResource ?? 1) * upd.FoodDrink.HpPercent.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (upd.Repairable is not null && (itemTemplate.Properties.ArmorClass ?? 0) > 0)
|
||||||
|
{
|
||||||
|
var num2 = 0.01 * Math.Pow(0.0, upd.Repairable.MaxDurability.Value);
|
||||||
|
worth =
|
||||||
|
worth * (upd.Repairable.MaxDurability.Value / (itemTemplate.Properties.Durability ?? 1) - num2) -
|
||||||
|
Math.Floor(
|
||||||
|
(itemTemplate.Properties.RepairCost ?? 0) *
|
||||||
|
(upd.Repairable.MaxDurability.Value - upd.Repairable.Durability.Value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return worth * itemCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user