diff --git a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/loot.json b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/loot.json index e2a987ed..473b4d84 100644 --- a/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/loot.json +++ b/Libraries/SPTarkov.Server.Assets/SPT_Data/configs/loot.json @@ -8,5 +8,10 @@ "bigmap": {}, "rezervbase": {}, "tarkovstreets": {} + }, + "staticItemWeightReduction":{ + "bigmap":{ + "5ad5d49886f77455f9731921": 60 + } } } diff --git a/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs b/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs index fd33d04f..c4a190a4 100644 --- a/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs +++ b/Libraries/SPTarkov.Server.Core/Helpers/BotWeaponGeneratorHelper.cs @@ -27,10 +27,9 @@ public class BotWeaponGeneratorHelper( { var randomizedMagazineCount = Math.Max(GetRandomizedMagazineCount(magCounts), 1); // Never return lower than 1 to prevent a multiplication by 0 var parentItem = itemHelper.GetItem(magTemplate.Parent).Value; - if (parentItem is null) { - logger.Error("Parent item is null when trying to get randomized bullet count"); + logger.Error($"Parent item null when trying to get randomized bullet count for: {magTemplate.Id}"); return null; } diff --git a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LootConfig.cs b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LootConfig.cs index b052b0a2..75706682 100644 --- a/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LootConfig.cs +++ b/Libraries/SPTarkov.Server.Core/Models/Spt/Config/LootConfig.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Eft.Common; namespace SPTarkov.Server.Core.Models.Spt.Config; @@ -19,4 +20,11 @@ public record LootConfig : BaseConfig /// [JsonPropertyName("looseLootSpawnPointAdjustments")] public required Dictionary> LooseLootSpawnPointAdjustments { get; set; } + + /// + /// Reduce weighting of static items per location + /// // value = percentage of original weight to use + /// + [JsonPropertyName("staticItemWeightReduction")] + public required Dictionary> StaticItemWeightReduction { get; set; } } diff --git a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs index 6c46cba1..5fa0f24e 100644 --- a/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs +++ b/Libraries/SPTarkov.Server.Core/Services/PostDbLoadService.cs @@ -6,6 +6,7 @@ using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Utils; using SPTarkov.Server.Core.Servers; +using SPTarkov.Server.Core.Utils; using SPTarkov.Server.Core.Utils.Cloners; namespace SPTarkov.Server.Core.Services; @@ -21,6 +22,7 @@ public class PostDbLoadService( ItemBaseClassService itemBaseClassService, RaidWeatherService raidWeatherService, ConfigServer configServer, + RandomUtil randomUtil, ICloner cloner ) { @@ -42,6 +44,8 @@ public class PostDbLoadService( // add items gets left out,causing warnings itemBaseClassService.HydrateItemBaseClassCache(); + ReduceStaticItemWeight(); + AddCustomLooseLootPositions(); MergeCustomAchievements(); @@ -321,30 +325,30 @@ public class PostDbLoadService( protected void AddCustomLooseLootPositions() { var looseLootPositionsToAdd = LootConfig.LooseLoot; - foreach (var (mapId, positionsToAdd) in looseLootPositionsToAdd) + foreach (var (locationId, positionsToAdd) in looseLootPositionsToAdd) { - if (mapId is null) + if (locationId is null) { - logger.Warning(serverLocalisationService.GetText("location-unable_to_add_custom_loot_position", mapId)); + logger.Warning(serverLocalisationService.GetText("location-unable_to_add_custom_loot_position", locationId)); continue; } databaseService - .GetLocation(mapId) - .LooseLoot.AddTransformer(looselootData => + .GetLocation(locationId) + .LooseLoot.AddTransformer(looseLootData => { - if (looselootData is null) + if (looseLootData is null) { - logger.Warning(serverLocalisationService.GetText("location-map_has_no_loose_loot_data", mapId)); + logger.Warning(serverLocalisationService.GetText("location-map_has_no_loose_loot_data", locationId)); - return looselootData; + return looseLootData; } foreach (var positionToAdd in positionsToAdd) { // Exists already, add new items to existing positions pool - var existingLootPosition = looselootData.Spawnpoints.FirstOrDefault(x => + var existingLootPosition = looseLootData.Spawnpoints.FirstOrDefault(x => x.Template.Id == positionToAdd.Template.Id ); @@ -360,10 +364,44 @@ public class PostDbLoadService( } // New position, add entire object - looselootData.Spawnpoints = looselootData.Spawnpoints.Append(positionToAdd); + looseLootData.Spawnpoints = looseLootData.Spawnpoints.Append(positionToAdd); } - return looselootData; + return looseLootData; + }); + } + } + + protected void ReduceStaticItemWeight() + { + foreach (var (locationId, itemTplWeightDict) in LootConfig.StaticItemWeightReduction) + { + databaseService + .GetLocation(locationId) + .StaticLoot.AddTransformer(staticLootData => + { + if (staticLootData is null) + { + return staticLootData; + } + + foreach (var (itemTpl, percentAdjustment) in itemTplWeightDict) + { + foreach (var loot in staticLootData) + { + var itemsWithTpl = loot.Value.ItemDistribution.Where(item => item.Tpl == itemTpl); + foreach (var itemToAdjust in itemsWithTpl) + { + itemToAdjust.RelativeProbability = randomUtil.GetPercentOfValue( + percentAdjustment, + itemToAdjust.RelativeProbability.Value, + 0 + ); + } + } + } + + return staticLootData; }); } } diff --git a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs index f14c7e4c..05e4cf60 100644 --- a/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs +++ b/Libraries/SPTarkov.Server.Core/Utils/RandomUtil.cs @@ -80,6 +80,34 @@ public class RandomUtil(ISptLogger logger, ICloner cloner) return Math.Round(num, toFixed); } + /// + /// Calculates the percentage of a given number and returns the result. + /// + /// The percentage to calculate. + /// The number to calculate the percentage of. + /// The number of decimal places to round the result to (default is 2). + /// The calculated percentage of the given number, rounded to the specified number of decimal places. + public virtual int GetPercentOfValue(double percent, int number, int toFixed = 2) + { + var num = percent * (number / 100); + + return (int)Math.Round(num, toFixed); + } + + /// + /// Calculates the percentage of a given number and returns the result. + /// + /// The percentage to calculate. + /// The number to calculate the percentage of. + /// The number of decimal places to round the result to (default is 2). + /// The calculated percentage of the given number, rounded to the specified number of decimal places. + public virtual float GetPercentOfValue(double percent, float number, int toFixed = 2) + { + var num = percent * (number / 100); + + return (float)Math.Round(num, toFixed); + } + /// /// Reduces a given number by a specified percentage. ///