Added system to allow adjustment of static spawn weights via config

reduced `Power substation utility cabin key` on customs to 60% of original weight
This commit is contained in:
Chomp
2025-10-03 20:28:39 +01:00
parent c9575c9b30
commit 6e2286ca5b
5 changed files with 91 additions and 13 deletions
@@ -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;
}
@@ -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
/// </summary>
[JsonPropertyName("looseLootSpawnPointAdjustments")]
public required Dictionary<string, Dictionary<string, double>> LooseLootSpawnPointAdjustments { get; set; }
/// <summary>
/// Reduce weighting of static items per location
/// // value = percentage of original weight to use
/// </summary>
[JsonPropertyName("staticItemWeightReduction")]
public required Dictionary<string, Dictionary<MongoId, double>> StaticItemWeightReduction { get; set; }
}
@@ -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;
});
}
}
@@ -80,6 +80,34 @@ public class RandomUtil(ISptLogger<RandomUtil> logger, ICloner cloner)
return Math.Round(num, toFixed);
}
/// <summary>
/// Calculates the percentage of a given number and returns the result.
/// </summary>
/// <param name="percent">The percentage to calculate.</param>
/// <param name="number">The number to calculate the percentage of.</param>
/// <param name="toFixed">The number of decimal places to round the result to (default is 2).</param>
/// <returns>The calculated percentage of the given number, rounded to the specified number of decimal places.</returns>
public virtual int GetPercentOfValue(double percent, int number, int toFixed = 2)
{
var num = percent * (number / 100);
return (int)Math.Round(num, toFixed);
}
/// <summary>
/// Calculates the percentage of a given number and returns the result.
/// </summary>
/// <param name="percent">The percentage to calculate.</param>
/// <param name="number">The number to calculate the percentage of.</param>
/// <param name="toFixed">The number of decimal places to round the result to (default is 2).</param>
/// <returns>The calculated percentage of the given number, rounded to the specified number of decimal places.</returns>
public virtual float GetPercentOfValue(double percent, float number, int toFixed = 2)
{
var num = percent * (number / 100);
return (float)Math.Round(num, toFixed);
}
/// <summary>
/// Reduces a given number by a specified percentage.
/// </summary>