Improved GetRandomizedResourceValue + GenerateExtraPropertiesForItem handling of values

Explicit handling of value == 1
Prevent returned value being below 1
Allow caller to force `StackObjectsCount` property
Renamed returned object
This commit is contained in:
Chomp
2025-09-14 10:17:49 +01:00
parent 11ae50875a
commit 0c68d56ee1
@@ -1,6 +1,7 @@
using System.Collections.Frozen;
using SPTarkov.DI.Annotations;
using SPTarkov.Server.Core.Constants;
using SPTarkov.Server.Core.Extensions;
using SPTarkov.Server.Core.Models.Common;
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
using SPTarkov.Server.Core.Models.Enums;
@@ -47,19 +48,21 @@ public class BotGeneratorHelper(
/// </summary>
/// <param name="itemTemplate">Item extra properties are being generated for</param>
/// <param name="botRole">Used by weapons to randomize the durability values. Null for non-equipped items</param>
/// <param name="forceStackObjectsCount">Force property on item</param>
/// <returns>Item Upd object with extra properties</returns>
public Upd GenerateExtraPropertiesForItem(TemplateItem? itemTemplate, string? botRole = null)
public Upd? GenerateExtraPropertiesForItem(TemplateItem? itemTemplate, string? botRole = null, bool forceStackObjectsCount = false)
{
// Get raid settings, if no raid, default to day
var raidSettings = profileActivityService.GetFirstProfileActivityRaidData()?.RaidConfiguration;
// BotRole property exists, we have specific bot randomisation values to make use of
RandomisedResourceDetails? randomisationSettings = null;
if (botRole is not null)
{
BotConfig.LootItemResourceRandomization.TryGetValue(botRole, out randomisationSettings);
}
Upd itemProperties = new();
Upd itemUpd = new();
var hasProperties = false;
if (itemTemplate?.Properties?.MaxDurability is not null && itemTemplate.Properties.MaxDurability > 0)
@@ -67,32 +70,32 @@ public class BotGeneratorHelper(
if (itemTemplate.Properties.WeapClass is not null)
{
// Is weapon
itemProperties.Repairable = GenerateWeaponRepairableProperties(itemTemplate, botRole);
itemUpd.Repairable = GenerateWeaponRepairableProperties(itemTemplate, botRole);
hasProperties = true;
}
else if (itemTemplate.Properties.ArmorClass is not null)
{
// Is armor
itemProperties.Repairable = GenerateArmorRepairableProperties(itemTemplate, botRole);
itemUpd.Repairable = GenerateArmorRepairableProperties(itemTemplate, botRole);
hasProperties = true;
}
}
if (itemTemplate?.Properties?.HasHinge ?? false)
{
itemProperties.Togglable = new UpdTogglable { On = true };
itemUpd.Togglable = new UpdTogglable { On = true };
hasProperties = true;
}
if (itemTemplate?.Properties?.Foldable ?? false)
{
itemProperties.Foldable = new UpdFoldable { Folded = false };
itemUpd.Foldable = new UpdFoldable { Folded = false };
hasProperties = true;
}
if (itemTemplate?.Properties?.WeapFireType?.Count == 0)
{
itemProperties.FireMode = itemTemplate.Properties.WeapFireType.Contains("fullauto")
itemUpd.FireMode = itemTemplate.Properties.WeapFireType.Contains("fullauto")
? new UpdFireMode { FireMode = "fullauto" }
: new UpdFireMode { FireMode = randomUtil.GetArrayValue(itemTemplate.Properties.WeapFireType) };
hasProperties = true;
@@ -100,7 +103,7 @@ public class BotGeneratorHelper(
if (itemTemplate?.Properties?.MaxHpResource is not null)
{
itemProperties.MedKit = new UpdMedKit
itemUpd.MedKit = new UpdMedKit
{
HpResource = GetRandomizedResourceValue(itemTemplate.Properties.MaxHpResource ?? 0, randomisationSettings?.Meds),
};
@@ -109,7 +112,7 @@ public class BotGeneratorHelper(
if (itemTemplate?.Properties?.MaxResource is not null && itemTemplate.Properties?.FoodUseTime is not null)
{
itemProperties.FoodDrink = new UpdFoodDrink
itemUpd.FoodDrink = new UpdFoodDrink
{
HpPercent = GetRandomizedResourceValue(itemTemplate.Properties.MaxResource ?? 0, randomisationSettings?.Food),
};
@@ -124,7 +127,7 @@ public class BotGeneratorHelper(
? equipmentSettings?.LightIsActiveNightChancePercent ?? 50
: equipmentSettings?.LightIsActiveDayChancePercent ?? 25;
itemProperties.Light = new UpdLight { IsActive = randomUtil.GetChance100(lightLaserActiveChance), SelectedMode = 0 };
itemUpd.Light = new UpdLight { IsActive = randomUtil.GetChance100(lightLaserActiveChance), SelectedMode = 0 };
hasProperties = true;
}
else if (itemTemplate?.Parent == BaseClasses.TACTICAL_COMBO)
@@ -132,7 +135,7 @@ public class BotGeneratorHelper(
// Get chance from botconfig for bot type, use 50% if no value found
var lightLaserActiveChance = equipmentSettings?.LaserIsActiveChancePercent ?? 50;
itemProperties.Light = new UpdLight { IsActive = randomUtil.GetChance100(lightLaserActiveChance), SelectedMode = 0 };
itemUpd.Light = new UpdLight { IsActive = randomUtil.GetChance100(lightLaserActiveChance), SelectedMode = 0 };
hasProperties = true;
}
@@ -144,7 +147,7 @@ public class BotGeneratorHelper(
? equipmentSettings?.NvgIsActiveChanceNightPercent ?? 90
: equipmentSettings?.NvgIsActiveChanceDayPercent ?? 15;
itemProperties.Togglable = new UpdTogglable { On = randomUtil.GetChance100(nvgActiveChance) };
itemUpd.Togglable = new UpdTogglable { On = randomUtil.GetChance100(nvgActiveChance) };
hasProperties = true;
}
@@ -152,12 +155,18 @@ public class BotGeneratorHelper(
if ((itemTemplate?.Properties?.HasHinge ?? false) && (itemTemplate.Properties.FaceShieldComponent ?? false))
{
var faceShieldActiveChance = equipmentSettings?.FaceShieldIsActiveChancePercent ?? 75;
itemProperties.Togglable = new UpdTogglable { On = randomUtil.GetChance100(faceShieldActiveChance) };
itemUpd.Togglable = new UpdTogglable { On = randomUtil.GetChance100(faceShieldActiveChance) };
hasProperties = true;
}
// Get chance from botconfig for bot type, use 75% if no value found
return hasProperties ? itemProperties : null;
if (forceStackObjectsCount)
{
// Ensure property is set
itemUpd.StackObjectsCount ??= 1;
}
// Some items (weapon mods) may not have any props, and we don't want an empty Upd object
return hasProperties ? itemUpd : null;
}
/// <summary>
@@ -168,17 +177,22 @@ public class BotGeneratorHelper(
/// <returns>Randomized value from maxHpResource</returns>
protected double GetRandomizedResourceValue(double maxResource, RandomisedResourceValues? randomizationValues)
{
if (randomizationValues is null)
if (randomizationValues is null || randomUtil.GetChance100(randomizationValues.ChanceMaxResourcePercent))
{
return maxResource;
}
if (randomUtil.GetChance100(randomizationValues.ChanceMaxResourcePercent))
if (maxResource.Approx(1))
{
return maxResource;
return 1;
}
return randomUtil.GetDouble(randomUtil.GetPercentOfValue(randomizationValues.ResourcePercent, maxResource, 0), maxResource);
var min = randomUtil.GetPercentOfValue(randomizationValues.ResourcePercent, maxResource, 0);
// Using food at 0 causes client to error
var clampedMin = Math.Clamp(min, 1, min);
return randomUtil.GetDouble(clampedMin, maxResource);
}
/// <summary>