166 lines
6.6 KiB
C#
166 lines
6.6 KiB
C#
using SPTarkov.DI.Annotations;
|
|
using SPTarkov.Server.Core.Helpers;
|
|
using SPTarkov.Server.Core.Models.Common;
|
|
using SPTarkov.Server.Core.Models.Eft.Common.Tables;
|
|
using SPTarkov.Server.Core.Models.Spt.Bots;
|
|
using SPTarkov.Server.Core.Models.Spt.Config;
|
|
using SPTarkov.Server.Core.Models.Utils;
|
|
using SPTarkov.Server.Core.Servers;
|
|
using LogLevel = SPTarkov.Server.Core.Models.Spt.Logging.LogLevel;
|
|
|
|
namespace SPTarkov.Server.Core.Services;
|
|
|
|
[Injectable(InjectionType.Singleton)]
|
|
public class BotWeaponModLimitService(ISptLogger<BotWeaponModLimitService> logger, ConfigServer configServer, ItemHelper itemHelper)
|
|
{
|
|
protected readonly BotConfig BotConfig = configServer.GetConfig<BotConfig>();
|
|
|
|
/// <summary>
|
|
/// Initalise mod limits to be used when generating a weapon
|
|
/// </summary>
|
|
/// <param name="botRole">"assault", "bossTagilla" or "pmc"</param>
|
|
/// <returns>BotModLimits object</returns>
|
|
public BotModLimits GetWeaponModLimits(string botRole)
|
|
{
|
|
return new BotModLimits
|
|
{
|
|
Scope = new ItemCount { Count = 0 },
|
|
ScopeMax = BotConfig.Equipment[botRole]?.WeaponModLimits?.ScopeLimit,
|
|
ScopeBaseTypes =
|
|
[
|
|
BaseClasses.OPTIC_SCOPE,
|
|
BaseClasses.ASSAULT_SCOPE,
|
|
BaseClasses.COLLIMATOR,
|
|
BaseClasses.COMPACT_COLLIMATOR,
|
|
BaseClasses.SPECIAL_SCOPE,
|
|
],
|
|
FlashlightLaser = new ItemCount { Count = 0 },
|
|
FlashlightLaserMax = BotConfig.Equipment[botRole]?.WeaponModLimits?.LightLaserLimit,
|
|
FlashlightLaserBaseTypes = [BaseClasses.TACTICAL_COMBO, BaseClasses.FLASHLIGHT, BaseClasses.PORTABLE_RANGE_FINDER],
|
|
};
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if weapon mod item is on limited list + has surpassed the limit set for it <br />
|
|
/// Exception: Always allow ncstar backup mount <br />
|
|
/// Exception: Always allow scopes with a scope for a parent <br />
|
|
/// Exception: Always disallow mounts that hold only scopes once scope limit reached <br />
|
|
/// Exception: Always disallow mounts that hold only flashlights once flashlight limit reached
|
|
/// </summary>
|
|
/// <param name="botRole">role the bot has e.g. assault</param>
|
|
/// <param name="modTemplate">mods template data</param>
|
|
/// <param name="modLimits">limits set for weapon being generated for this bot</param>
|
|
/// <param name="modsParent">The parent of the mod to be checked</param>
|
|
/// <param name="weapon">Array of IItem</param>
|
|
/// <returns>true if over item limit</returns>
|
|
public bool WeaponModHasReachedLimit(
|
|
string botRole,
|
|
TemplateItem modTemplate,
|
|
BotModLimits modLimits,
|
|
TemplateItem modsParent,
|
|
IEnumerable<Item> weapon
|
|
)
|
|
{
|
|
// If mod or mods parent is the NcSTAR MPR45 Backup mount, allow it as it looks cool
|
|
if (modsParent.Id == ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP || modTemplate.Id == ItemTpl.MOUNT_NCSTAR_MPR45_BACKUP)
|
|
{
|
|
// If weapon already has a longer ranged scope on it, allow ncstar to be spawned
|
|
if (
|
|
weapon.Any(item =>
|
|
itemHelper.IsOfBaseclasses(
|
|
item.Template,
|
|
[BaseClasses.ASSAULT_SCOPE, BaseClasses.OPTIC_SCOPE, BaseClasses.SPECIAL_SCOPE]
|
|
)
|
|
)
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Mods parent is scope and mod is scope, allow it (adds those mini-sights to the tops of sights)
|
|
var modIsScope = itemHelper.IsOfBaseclasses(modTemplate.Id, modLimits.ScopeBaseTypes);
|
|
if (itemHelper.IsOfBaseclasses(modsParent.Id, modLimits.ScopeBaseTypes) && modIsScope)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// If mod is a scope , Exit early
|
|
if (modIsScope)
|
|
{
|
|
return WeaponModLimitReached(modTemplate.Id, modLimits.Scope, modLimits.ScopeMax ?? 0, botRole);
|
|
}
|
|
|
|
// Don't allow multiple mounts on a weapon (except when mount is on another mount)
|
|
// Fail when:
|
|
// Over or at scope limit on weapon
|
|
// Item being added is a mount but the parent item is NOT a mount (Allows red dot sub-mounts on mounts)
|
|
// Mount has one slot and it is for a mod_scope
|
|
if (
|
|
modLimits.Scope.Count >= modLimits.ScopeMax
|
|
&& modTemplate.Properties?.Slots?.Count() == 1
|
|
&& itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT)
|
|
&& !itemHelper.IsOfBaseclass(modsParent.Id, BaseClasses.MOUNT)
|
|
&& modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_scope")
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// If mod is a light/laser, return if limit reached
|
|
var modIsLightOrLaser = itemHelper.IsOfBaseclasses(modTemplate.Id, modLimits.FlashlightLaserBaseTypes);
|
|
if (modIsLightOrLaser)
|
|
{
|
|
return WeaponModLimitReached(modTemplate.Id, modLimits.FlashlightLaser, modLimits.FlashlightLaserMax ?? 0, botRole);
|
|
}
|
|
|
|
// Mod is a mount that can hold only flashlights ad limit is reached (don't want to add empty mounts if limit is reached)
|
|
if (
|
|
modLimits.Scope.Count >= modLimits.ScopeMax
|
|
&& modTemplate.Properties?.Slots?.Count() == 1
|
|
&& itemHelper.IsOfBaseclass(modTemplate.Id, BaseClasses.MOUNT)
|
|
&& modTemplate.Properties.Slots.Any(slot => slot.Name == "mod_flashlight")
|
|
)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Check if the specific item type on the weapon has reached the set limit
|
|
/// </summary>
|
|
/// <param name="modTpl">log mod tpl if over type limit</param>
|
|
/// <param name="currentCount">current number of this item on gun</param>
|
|
/// <param name="maxLimit">mod limit allowed</param>
|
|
/// <param name="botRole">role of bot we're checking weapon of</param>
|
|
/// <returns>true if limit reached</returns>
|
|
protected bool WeaponModLimitReached(MongoId modTpl, ItemCount currentCount, int? maxLimit, string botRole)
|
|
{
|
|
// No value or 0
|
|
if (maxLimit is null || maxLimit is 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Has mod limit for bot type been reached
|
|
if (currentCount.Count >= maxLimit)
|
|
{
|
|
if (logger.IsLogEnabled(LogLevel.Debug))
|
|
{
|
|
logger.Debug($"[{botRole}] scope limit reached! tried to add {modTpl} but scope count is {currentCount.Count}");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// Increment scope count
|
|
currentCount.Count++;
|
|
|
|
return false;
|
|
}
|
|
}
|