Added ability to track loot items and prevent more than a pre-defined amount from spawning
Replaced `location.json` `forcedLootSingleSpawnById` with `lootMaxSpawnLimits` Added 5 item limit to `Labrys research notes` #290
This commit is contained in:
@@ -46,94 +46,100 @@
|
||||
"normal": {}
|
||||
},
|
||||
"openZones": {},
|
||||
"forcedLootSingleSpawnById": {
|
||||
"bigmap": [
|
||||
"5ac620eb86f7743a8e6e0da0",
|
||||
"5939e5a786f77461f11c0098",
|
||||
"64e74a3d4d49d23b2c39d319",
|
||||
"6614230055afee107f05e998",
|
||||
"66b22630a6b4e5ec7c02cdb7",
|
||||
"675f80d4fe1b59cf490d3527",
|
||||
"67499d0eeca8acb2d2061639",
|
||||
"675f7acc4076a741a3061566",
|
||||
"675f80d4fe1b59cf490d3527",
|
||||
"675f7f224076a741a3061568",
|
||||
"675f7b168d28a25ec7007dbb"
|
||||
],
|
||||
"interchange": ["64e74a5ac2b4f829615ec336", "667a8ef464eea5fdef0db135"],
|
||||
"lighthouse": [
|
||||
"6331bb0d1aa9f42b804997a6",
|
||||
"6398a0861c712b1e1d4dadf1",
|
||||
"6399f54b0a36db13c823ad21",
|
||||
"64e74a64aac4cd0a7264ecdf",
|
||||
"661666458c2aa9cb1602503b"
|
||||
],
|
||||
"rezervbase": [
|
||||
"64e74a4baac4cd0a7264ecdd",
|
||||
"6398a072e301557ae24cec92",
|
||||
"67499b3eeca8acb2d2061636",
|
||||
"67499b9b909d2013670a5029"
|
||||
],
|
||||
"shoreline": [
|
||||
"64e74a534d49d23b2c39d31b",
|
||||
"661421c7c1f2f548c50ee649",
|
||||
"6614217b6d9d5abcad0ff098",
|
||||
"661423200d240a5f5d0f679b",
|
||||
"6707d1f9571b50abc703b651",
|
||||
"66760b3deb51b08bd40c2b08",
|
||||
"67499adbeca8acb2d2061634",
|
||||
"6614238e0d240a5f5d0f679d",
|
||||
"666073159916667083033cb9"
|
||||
],
|
||||
"tarkovstreets": [
|
||||
"638df4cc7b560b03794a18d2",
|
||||
"638cbc68a63f1b49be6a3010",
|
||||
"638e0057ab150a5f56238960",
|
||||
"63927b29c115f907b14700b9",
|
||||
"638dfc803083a019d447768e",
|
||||
"638e9d5536b3b72c944e2fc7",
|
||||
"6393262086e646067c176aa2",
|
||||
"63989ced706b793c7d60cfef",
|
||||
"63a39e1d234195315d4020bd",
|
||||
"64e74a35aac4cd0a7264ecdb",
|
||||
"64e74a186393886f74114a96",
|
||||
"64e74a1faac4cd0a7264ecd9",
|
||||
"64e73909cd54ef0580746af3",
|
||||
"64e74a2fc2b4f829615ec332",
|
||||
"64e74a274d49d23b2c39d317",
|
||||
"64f09c02b63b74469b6c149f",
|
||||
"64f07f7726cfa02c506f8ac0",
|
||||
"64f69b4267e11a7c6206e010",
|
||||
"64f5b4f71a5f313cb144c06c",
|
||||
"657acb2ac900be5902191ac9",
|
||||
"6582dbf0b8d7830efc45016f",
|
||||
"66687bc89111279d600b5062"
|
||||
],
|
||||
"laboratory": [
|
||||
"6398a4cfb5992f573c6562b3",
|
||||
"64e74a44c2b4f829615ec334",
|
||||
"6711039f9e648049e50b3307",
|
||||
"6707cef3571b50abc703b64f",
|
||||
"6707cd70aab679420007e018",
|
||||
"6707cc67cc1667e49e0f7232",
|
||||
"6707cf827d279daad80fa95f"
|
||||
],
|
||||
"sandbox": ["6575a6ca8778e96ded05a802", "6582bd252b50c61c565828e2"],
|
||||
"factory4_day": [
|
||||
"591093bb86f7747caa7bb2ee",
|
||||
"66c0b39ca1f68fcc1d0c0cc3",
|
||||
"66a0e523e749756c920d02d0",
|
||||
"593a87af86f774122f54a951"
|
||||
],
|
||||
"factory4_night": [
|
||||
"591093bb86f7747caa7bb2ee",
|
||||
"66c0b39ca1f68fcc1d0c0cc3",
|
||||
"66a0e523e749756c920d02d0",
|
||||
"593a87af86f774122f54a951"
|
||||
],
|
||||
"labyrinth": [
|
||||
"679b992329acd1f2f60985a5"
|
||||
]
|
||||
"lootMaxSpawnLimits": {
|
||||
"bigmap": {
|
||||
"5ac620eb86f7743a8e6e0da0": 1,
|
||||
"5939e5a786f77461f11c0098": 1,
|
||||
"64e74a3d4d49d23b2c39d319": 1,
|
||||
"6614230055afee107f05e998": 1,
|
||||
"66b22630a6b4e5ec7c02cdb7": 1,
|
||||
"675f80d4fe1b59cf490d3527": 1,
|
||||
"67499d0eeca8acb2d2061639": 1,
|
||||
"675f7acc4076a741a3061566": 1,
|
||||
"675f80d4fe1b59cf490d3527": 1,
|
||||
"675f7f224076a741a3061568": 1,
|
||||
"675f7b168d28a25ec7007dbb": 1
|
||||
},
|
||||
"interchange": {
|
||||
"64e74a5ac2b4f829615ec336": 1,
|
||||
"667a8ef464eea5fdef0db135": 1
|
||||
},
|
||||
"lighthouse": {
|
||||
"6331bb0d1aa9f42b804997a6": 1,
|
||||
"6398a0861c712b1e1d4dadf1": 1,
|
||||
"6399f54b0a36db13c823ad21": 1,
|
||||
"64e74a64aac4cd0a7264ecdf": 1,
|
||||
"661666458c2aa9cb1602503b": 1
|
||||
},
|
||||
"rezervbase": {
|
||||
"64e74a4baac4cd0a7264ecdd": 1,
|
||||
"6398a072e301557ae24cec92": 1,
|
||||
"67499b3eeca8acb2d2061636": 1,
|
||||
"67499b9b909d2013670a5029": 1
|
||||
},
|
||||
"shoreline": {
|
||||
"64e74a534d49d23b2c39d31b": 1,
|
||||
"661421c7c1f2f548c50ee649": 1,
|
||||
"6614217b6d9d5abcad0ff098": 1,
|
||||
"661423200d240a5f5d0f679b": 1,
|
||||
"6707d1f9571b50abc703b651": 1,
|
||||
"66760b3deb51b08bd40c2b08": 1,
|
||||
"67499adbeca8acb2d2061634": 1,
|
||||
"6614238e0d240a5f5d0f679d": 1,
|
||||
"666073159916667083033cb9": 1
|
||||
},
|
||||
"tarkovstreets": {
|
||||
"638df4cc7b560b03794a18d2": 1,
|
||||
"638cbc68a63f1b49be6a3010": 1,
|
||||
"638e0057ab150a5f56238960": 1,
|
||||
"63927b29c115f907b14700b9": 1,
|
||||
"638dfc803083a019d447768e": 1,
|
||||
"638e9d5536b3b72c944e2fc7": 1,
|
||||
"6393262086e646067c176aa2": 1,
|
||||
"63989ced706b793c7d60cfef": 1,
|
||||
"63a39e1d234195315d4020bd": 1,
|
||||
"64e74a35aac4cd0a7264ecdb": 1,
|
||||
"64e74a186393886f74114a96": 1,
|
||||
"64e74a1faac4cd0a7264ecd9": 1,
|
||||
"64e73909cd54ef0580746af3": 1,
|
||||
"64e74a2fc2b4f829615ec332": 1,
|
||||
"64e74a274d49d23b2c39d317": 1,
|
||||
"64f09c02b63b74469b6c149f": 1,
|
||||
"64f07f7726cfa02c506f8ac0": 1,
|
||||
"64f69b4267e11a7c6206e010": 1,
|
||||
"64f5b4f71a5f313cb144c06c": 1,
|
||||
"657acb2ac900be5902191ac9": 1,
|
||||
"6582dbf0b8d7830efc45016f": 1,
|
||||
"66687bc89111279d600b5062": 1
|
||||
},
|
||||
"laboratory": {
|
||||
"6398a4cfb5992f573c6562b3": 1,
|
||||
"64e74a44c2b4f829615ec334": 1,
|
||||
"6711039f9e648049e50b3307": 1,
|
||||
"6707cef3571b50abc703b64f": 1,
|
||||
"6707cd70aab679420007e018": 1,
|
||||
"6707cc67cc1667e49e0f7232": 1,
|
||||
"6707cf827d279daad80fa95f": 1
|
||||
},
|
||||
"sandbox": {
|
||||
"6575a6ca8778e96ded05a802": 1,
|
||||
"6582bd252b50c61c565828e2": 1
|
||||
},
|
||||
"factory4_day": {
|
||||
"591093bb86f7747caa7bb2ee": 1,
|
||||
"66c0b39ca1f68fcc1d0c0cc3": 1,
|
||||
"66a0e523e749756c920d02d0": 1,
|
||||
"593a87af86f774122f54a951": 1
|
||||
},
|
||||
"factory4_night": {
|
||||
"591093bb86f7747caa7bb2ee": 1,
|
||||
"66c0b39ca1f68fcc1d0c0cc3": 1,
|
||||
"66a0e523e749756c920d02d0": 1,
|
||||
"593a87af86f774122f54a951": 1
|
||||
},
|
||||
"labyrinth": {
|
||||
"679b992329acd1f2f60985a5": 5
|
||||
}
|
||||
},
|
||||
"rogueLighthouseSpawnTimeSettings": {
|
||||
"enabled": false,
|
||||
|
||||
@@ -29,6 +29,7 @@ public class LocationLootGenerator(
|
||||
SeasonalEventService _seasonalEventService,
|
||||
ItemFilterService _itemFilterService,
|
||||
ConfigServer _configServer,
|
||||
CounterTrackerHelper counterTrackerHelper,
|
||||
ICloner _cloner
|
||||
)
|
||||
{
|
||||
@@ -349,7 +350,7 @@ public class LocationLootGenerator(
|
||||
containerDistribution.Add(new ProbabilityObject<string, double>(x, value, value));
|
||||
}
|
||||
|
||||
chosenContainerIds.AddRange(containerDistribution.Draw((int)containerData.ChosenCount));
|
||||
chosenContainerIds.AddRange(containerDistribution.Draw((int) containerData.ChosenCount));
|
||||
|
||||
return chosenContainerIds;
|
||||
}
|
||||
@@ -509,7 +510,8 @@ public class LocationLootGenerator(
|
||||
// Filter out items picked that are already in the above `tplsForced` array
|
||||
var chosenTpls = containerLootPool
|
||||
.Draw(itemCountToAdd, _locationConfig.AllowDuplicateItemsInStaticContainers, lockList)
|
||||
.Where(tpl => !tplsForced.Contains(tpl));
|
||||
.Where(tpl => !tplsForced.Contains(tpl))
|
||||
.Where(tpl => !counterTrackerHelper.IncrementCount(tpl));
|
||||
|
||||
// Add forced loot to chosen item pool
|
||||
var tplsToAddToContainer = tplsForced.Concat(chosenTpls);
|
||||
@@ -695,12 +697,13 @@ public class LocationLootGenerator(
|
||||
/// <param name="dynamicLootDist"></param>
|
||||
/// <param name="staticAmmoDist"></param>
|
||||
/// <param name="locationName">Location to generate loot for</param>
|
||||
/// <param name="spawnLimitedLoot"></param>
|
||||
/// <returns>Array of spawn points with loot in them</returns>
|
||||
public List<SpawnpointTemplate> GenerateDynamicLoot(
|
||||
LooseLoot dynamicLootDist,
|
||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||
string locationName
|
||||
)
|
||||
string locationName,
|
||||
Dictionary<string, int> spawnLimitedLoot)
|
||||
{
|
||||
List<SpawnpointTemplate> loot = [];
|
||||
List<Spawnpoint> dynamicForcedSpawnPoints = [];
|
||||
@@ -726,28 +729,29 @@ public class LocationLootGenerator(
|
||||
dynamicLootDist.Spawnpoints.Where(point => point.Template.IsAlwaysSpawn ?? false)
|
||||
);
|
||||
|
||||
// Add forced loot
|
||||
AddForcedLoot(loot, dynamicForcedSpawnPoints, locationName, staticAmmoDist);
|
||||
|
||||
var allDynamicSpawnPoints = dynamicLootDist.Spawnpoints;
|
||||
// Add forced loot to results
|
||||
AddForcedLoot(loot, dynamicForcedSpawnPoints, locationName, staticAmmoDist, spawnLimitedLoot);
|
||||
|
||||
// Draw from random distribution
|
||||
var desiredSpawnPointCount = Math.Round(
|
||||
GetLooseLootMultiplierForLocation(locationName)
|
||||
* _randomUtil.GetNormallyDistributedRandomNumber(
|
||||
(double)dynamicLootDist.SpawnpointCount.Mean,
|
||||
(double)dynamicLootDist.SpawnpointCount.Std
|
||||
dynamicLootDist.SpawnpointCount.Mean,
|
||||
dynamicLootDist.SpawnpointCount.Std
|
||||
)
|
||||
);
|
||||
|
||||
// Positions not in forced but have 100% chance to spawn
|
||||
List<Spawnpoint> guaranteedLoosePoints = [];
|
||||
|
||||
var blacklistedSpawnPoints = _locationConfig.LooseLootBlacklist.GetValueOrDefault(
|
||||
locationName
|
||||
);
|
||||
|
||||
// Init empty array to hold spawn points, letting us pick them pseudo-randomly
|
||||
var spawnPointArray = new ProbabilityObjectArray<string, Spawnpoint>(_mathUtil, _cloner);
|
||||
|
||||
// Positions not in forced but have 100% chance to spawn
|
||||
List<Spawnpoint> guaranteedLoosePoints = [];
|
||||
|
||||
var allDynamicSpawnPoints = dynamicLootDist.Spawnpoints;
|
||||
foreach (var spawnPoint in allDynamicSpawnPoints)
|
||||
{
|
||||
// Point is blacklisted, skip
|
||||
@@ -793,7 +797,7 @@ public class LocationLootGenerator(
|
||||
if (randomSpawnPointCount > 0 && spawnPointArray.Count > 0)
|
||||
// Add randomly chosen spawn points
|
||||
{
|
||||
foreach (var si in spawnPointArray.Draw((int)randomSpawnPointCount, false))
|
||||
foreach (var si in spawnPointArray.Draw((int) randomSpawnPointCount, false))
|
||||
{
|
||||
chosenSpawnPoints.Add(spawnPointArray.Data(si));
|
||||
}
|
||||
@@ -915,6 +919,12 @@ public class LocationLootGenerator(
|
||||
staticAmmoDist
|
||||
);
|
||||
|
||||
// If count reaches max, skip adding item to loot
|
||||
if (counterTrackerHelper.IncrementCount(createItemResult.Items.FirstOrDefault().Template))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Root id can change when generating a weapon, ensure ids match
|
||||
spawnPoint.Template.Root = createItemResult.Items.FirstOrDefault().Id;
|
||||
|
||||
@@ -922,6 +932,7 @@ public class LocationLootGenerator(
|
||||
spawnPoint.Template.Items = createItemResult.Items;
|
||||
|
||||
loot.Add(spawnPoint.Template);
|
||||
|
||||
}
|
||||
|
||||
return loot;
|
||||
@@ -933,19 +944,20 @@ public class LocationLootGenerator(
|
||||
/// <param name="lootLocationTemplates">List to add forced loot spawn locations to</param>
|
||||
/// <param name="forcedSpawnPoints">Forced loot locations that must be added</param>
|
||||
/// <param name="locationName">Name of map currently having force loot created for</param>
|
||||
/// <param name="staticAmmoDist"></param>
|
||||
/// <param name="spawnLimitedLoot"></param>
|
||||
protected void AddForcedLoot(
|
||||
List<SpawnpointTemplate> lootLocationTemplates,
|
||||
List<Spawnpoint> forcedSpawnPoints,
|
||||
string locationName,
|
||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist
|
||||
)
|
||||
Dictionary<string, List<StaticAmmoDetails>> staticAmmoDist,
|
||||
Dictionary<string, int> spawnLimitedLoot)
|
||||
{
|
||||
var lootToForceSingleAmountOnMap =
|
||||
_locationConfig.ForcedLootSingleSpawnById.GetValueOrDefault(locationName);
|
||||
if (lootToForceSingleAmountOnMap is not null)
|
||||
|
||||
if (spawnLimitedLoot is not null)
|
||||
// Process loot items defined as requiring only 1 spawn position as they appear in multiple positions on the map
|
||||
{
|
||||
foreach (var itemTpl in lootToForceSingleAmountOnMap)
|
||||
foreach (var (itemTpl, itemSpawnCountMax) in spawnLimitedLoot)
|
||||
{
|
||||
// Get all spawn positions for item tpl in forced loot array
|
||||
var items = forcedSpawnPoints.Where(forcedSpawnPoint =>
|
||||
@@ -969,7 +981,7 @@ public class LocationLootGenerator(
|
||||
_cloner
|
||||
);
|
||||
foreach (var si in items)
|
||||
// use locationId as template.Id is the same across all items
|
||||
// Use locationId as template.Id is the same across all items
|
||||
{
|
||||
spawnPointArray.Add(
|
||||
new ProbabilityObject<string, Spawnpoint>(
|
||||
@@ -980,8 +992,8 @@ public class LocationLootGenerator(
|
||||
);
|
||||
}
|
||||
|
||||
// Choose 1 out of all found spawn positions for spawn id and add to loot array
|
||||
foreach (var spawnPointLocationId in spawnPointArray.Draw(1, false))
|
||||
// Choose count from config of spawn positions for spawn id and add to loot array
|
||||
foreach (var spawnPointLocationId in spawnPointArray.Draw(itemSpawnCountMax, false))
|
||||
{
|
||||
var itemToAdd = items.FirstOrDefault(item =>
|
||||
item.LocationId == spawnPointLocationId
|
||||
@@ -1001,6 +1013,12 @@ public class LocationLootGenerator(
|
||||
staticAmmoDist
|
||||
);
|
||||
|
||||
// If count reaches max, skip adding item to loot
|
||||
if (counterTrackerHelper.IncrementCount(itemTpl))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update root ID with the dynamically generated ID
|
||||
lootItem.Root = createItemResult.Items.FirstOrDefault().Id;
|
||||
lootItem.Items = createItemResult.Items;
|
||||
@@ -1018,7 +1036,7 @@ public class LocationLootGenerator(
|
||||
var firstLootItemTpl = forcedLootLocation.Template.Items.FirstOrDefault().Template;
|
||||
|
||||
// Skip spawn positions processed already
|
||||
if (lootToForceSingleAmountOnMap?.Contains(firstLootItemTpl) ?? false)
|
||||
if (spawnLimitedLoot?.ContainsKey(firstLootItemTpl) ?? false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using SPTarkov.DI.Annotations;
|
||||
|
||||
namespace SPTarkov.Server.Core.Helpers
|
||||
{
|
||||
[Injectable]
|
||||
public class CounterTrackerHelper
|
||||
{
|
||||
private Dictionary<string, int> _maxCounts = new();
|
||||
private readonly Dictionary<string, int> _trackedCounts = new();
|
||||
|
||||
/// <summary>
|
||||
/// Add dictionary of keys and their matching limits to track
|
||||
/// </summary>
|
||||
/// <param name="maxCounts">Values to store</param>
|
||||
public void AddDataToTrack(Dictionary<string, int> maxCounts)
|
||||
{
|
||||
_maxCounts = maxCounts;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increment the counter for passed in key, get back value determining if max value passed
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <param name="countToIncrementBy"></param>
|
||||
/// <returns>True = above max count</returns>
|
||||
public bool IncrementCount(string key, int countToIncrementBy = 1)
|
||||
{
|
||||
// Not tracked, skip
|
||||
if (!_maxCounts.ContainsKey(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_trackedCounts.TryAdd(key, 0);
|
||||
_trackedCounts[key] += countToIncrementBy;
|
||||
|
||||
return _trackedCounts[key] > _maxCounts[key];
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
_trackedCounts.Clear();
|
||||
_maxCounts.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@ public record SpawnpointCount
|
||||
public Dictionary<string, object> ExtensionData { get; set; }
|
||||
|
||||
[JsonPropertyName("mean")]
|
||||
public double? Mean { get; set; }
|
||||
public required double Mean { get; set; }
|
||||
|
||||
[JsonPropertyName("std")]
|
||||
public double? Std { get; set; }
|
||||
public required double Std { get; set; }
|
||||
}
|
||||
|
||||
public record SpawnpointTemplate
|
||||
|
||||
@@ -34,10 +34,10 @@ public record LocationConfig : BaseConfig
|
||||
public required Dictionary<string, HashSet<string>> OpenZones { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Key = map id, value = item tpls that should only have one forced loot spawn position
|
||||
/// Key = map id, value = dict of item tpls that should only have x forced loot spawn position
|
||||
/// </summary>
|
||||
[JsonPropertyName("forcedLootSingleSpawnById")]
|
||||
public required Dictionary<string, HashSet<string>> ForcedLootSingleSpawnById { get; set; }
|
||||
[JsonPropertyName("lootMaxSpawnLimits")]
|
||||
public required Dictionary<string, Dictionary<string, int>> LootMaxSpawnLimits { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// How many attempts should be taken to fit an item into a container before giving up
|
||||
|
||||
@@ -54,6 +54,7 @@ public class LocationLifecycleService
|
||||
protected TraderConfig _traderConfig;
|
||||
protected TraderHelper _traderHelper;
|
||||
protected BtrDeliveryService _btrDeliveryService;
|
||||
private readonly CounterTrackerHelper _counterTrackerHelper;
|
||||
|
||||
public LocationLifecycleService(
|
||||
ISptLogger<LocationLifecycleService> logger,
|
||||
@@ -84,7 +85,8 @@ public class LocationLifecycleService
|
||||
QuestHelper questHelper,
|
||||
InsuranceService insuranceService,
|
||||
MatchBotDetailsCacheService matchBotDetailsCacheService,
|
||||
BtrDeliveryService btrDeliveryService
|
||||
BtrDeliveryService btrDeliveryService,
|
||||
CounterTrackerHelper counterTrackerHelper
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -116,6 +118,7 @@ public class LocationLifecycleService
|
||||
_insuranceService = insuranceService;
|
||||
_matchBotDetailsCacheService = matchBotDetailsCacheService;
|
||||
_btrDeliveryService = btrDeliveryService;
|
||||
_counterTrackerHelper = counterTrackerHelper;
|
||||
|
||||
_locationConfig = _configServer.GetConfig<LocationConfig>();
|
||||
_inRaidConfig = _configServer.GetConfig<InRaidConfig>();
|
||||
@@ -390,13 +393,13 @@ public class LocationLifecycleService
|
||||
return locationBaseClone;
|
||||
}
|
||||
|
||||
// Add cusom pmcs to map every time its run
|
||||
// Add custom pmcs to map every time its run
|
||||
_pmcWaveGenerator.ApplyWaveChangesToMap(locationBaseClone);
|
||||
|
||||
// Adjust raid based on whether this is a scav run
|
||||
LocationConfig? locationConfigClone = null;
|
||||
var raidAdjustments = _profileActivityService
|
||||
.GetProfileActivityRaidData(sessionId)
|
||||
.GetProfileActivityRaidData(sessionId)?
|
||||
.RaidAdjustments;
|
||||
if (raidAdjustments is not null)
|
||||
{
|
||||
@@ -406,6 +409,11 @@ public class LocationLifecycleService
|
||||
|
||||
var staticAmmoDist = _cloner.Clone(location.StaticAmmo);
|
||||
|
||||
var itemsWithSpawnCountLimits = _cloner.Clone(_locationConfig.LootMaxSpawnLimits.GetValueOrDefault(name.ToLower()));
|
||||
|
||||
// Store items with spawn count limits inside so they can be accessed later inside static/dynamic loot spawn methods
|
||||
_counterTrackerHelper.AddDataToTrack(itemsWithSpawnCountLimits);
|
||||
|
||||
// Create containers and add loot to them
|
||||
var staticLoot = _locationLootGenerator.GenerateStaticContainers(
|
||||
locationBaseClone,
|
||||
@@ -418,7 +426,8 @@ public class LocationLifecycleService
|
||||
var dynamicSpawnPoints = _locationLootGenerator.GenerateDynamicLoot(
|
||||
dynamicLootDistClone,
|
||||
staticAmmoDist,
|
||||
name.ToLower()
|
||||
name.ToLower(),
|
||||
itemsWithSpawnCountLimits
|
||||
);
|
||||
|
||||
// Push chosen spawn points into returned object
|
||||
@@ -446,6 +455,9 @@ public class LocationLifecycleService
|
||||
_profileActivityService.GetProfileActivityRaidData(sessionId).RaidAdjustments = null;
|
||||
}
|
||||
|
||||
// Clean up tracker
|
||||
_counterTrackerHelper.Clear();
|
||||
|
||||
return locationBaseClone;
|
||||
}
|
||||
|
||||
@@ -614,7 +626,7 @@ public class LocationLifecycleService
|
||||
// Check if new standing has leveled up trader
|
||||
_traderHelper.LevelUp(fenceId, pmcData);
|
||||
pmcData.TradersInfo[fenceId].LoyaltyLevel = Math.Max(
|
||||
(int)pmcData.TradersInfo[fenceId].LoyaltyLevel,
|
||||
(int) pmcData.TradersInfo[fenceId].LoyaltyLevel,
|
||||
1
|
||||
);
|
||||
|
||||
@@ -652,7 +664,7 @@ public class LocationLifecycleService
|
||||
// Check if new standing has leveled up trader
|
||||
_traderHelper.LevelUp(fenceId, pmcData);
|
||||
pmcData.TradersInfo[fenceId].LoyaltyLevel = Math.Max(
|
||||
(int)pmcData.TradersInfo[fenceId].LoyaltyLevel,
|
||||
(int) pmcData.TradersInfo[fenceId].LoyaltyLevel,
|
||||
1
|
||||
);
|
||||
|
||||
@@ -684,7 +696,7 @@ public class LocationLifecycleService
|
||||
fenceStanding += Math.Max(baseGain / extractCount, 0.01);
|
||||
|
||||
// Ensure fence loyalty level is not above/below the range -7 to 15
|
||||
var newFenceStanding = Math.Min(Math.Max((double)fenceStanding, -7), 15);
|
||||
var newFenceStanding = Math.Min(Math.Max((double) fenceStanding, -7), 15);
|
||||
_logger.Debug(
|
||||
$"Old vs new fence standing: {pmcData.TradersInfo[fenceId].Standing}, {newFenceStanding}"
|
||||
);
|
||||
@@ -988,7 +1000,7 @@ public class LocationLifecycleService
|
||||
// Clamp fence standing
|
||||
var currentFenceStanding = postRaidProfile.TradersInfo[fenceId].Standing;
|
||||
pmcProfile.TradersInfo[fenceId].Standing = Math.Min(
|
||||
Math.Max((double)currentFenceStanding, -7),
|
||||
Math.Max((double) currentFenceStanding, -7),
|
||||
15
|
||||
); // Ensure it stays between -7 and 15
|
||||
|
||||
|
||||
Reference in New Issue
Block a user