Files
SPT-Server-Build/Libraries/SPTarkov.Server.Core/Services/BotWeaponModLimitService.cs
T

203 lines
7.2 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.Enums;
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;
}
}