0
0
mirror of https://github.com/sp-tarkov/server.git synced 2025-02-13 09:50:43 -05:00
server/project/src/services/BotWeaponModLimitService.ts

184 lines
6.9 KiB
TypeScript
Raw Normal View History

import { ItemHelper } from "@spt/helpers/ItemHelper";
import { IItem } from "@spt/models/eft/common/tables/IItem";
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "@spt/models/enums/BaseClasses";
import { ConfigTypes } from "@spt/models/enums/ConfigTypes";
import { ItemTpl } from "@spt/models/enums/ItemTpl";
import { IBotConfig } from "@spt/models/spt/config/IBotConfig";
import { ILogger } from "@spt/models/spt/utils/ILogger";
import { ConfigServer } from "@spt/servers/ConfigServer";
import { inject, injectable } from "tsyringe";
2023-03-03 15:23:46 +00:00
export class BotModLimits {
2023-03-03 15:23:46 +00:00
scope: ItemCount;
scopeMax: number;
scopeBaseTypes: string[];
flashlightLaser: ItemCount;
flashlightLaserMax: number;
flashlgihtLaserBaseTypes: string[];
}
export class ItemCount {
2023-03-03 15:23:46 +00:00
count: number;
}
@injectable()
export class BotWeaponModLimitService {
2023-03-03 15:23:46 +00:00
protected botConfig: IBotConfig;
constructor(
@inject("PrimaryLogger") protected logger: ILogger,
2023-03-03 15:23:46 +00:00
@inject("ConfigServer") protected configServer: ConfigServer,
2023-11-15 20:35:05 -05:00
@inject("ItemHelper") protected itemHelper: ItemHelper,
) {
2023-03-03 15:23:46 +00:00
this.botConfig = this.configServer.getConfig(ConfigTypes.BOT);
}
/**
* Initalise mod limits to be used when generating a weapon
* @param botRole "assault", "bossTagilla" or "pmc"
* @returns BotModLimits object
*/
public getWeaponModLimits(botRole: string): BotModLimits {
2023-03-03 15:23:46 +00:00
return {
2023-11-15 20:35:05 -05:00
scope: { count: 0 },
2023-03-03 15:23:46 +00:00
scopeMax: this.botConfig.equipment[botRole]?.weaponModLimits?.scopeLimit,
2023-11-15 20:35:05 -05:00
scopeBaseTypes: [
BaseClasses.OPTIC_SCOPE,
BaseClasses.ASSAULT_SCOPE,
BaseClasses.COLLIMATOR,
BaseClasses.COMPACT_COLLIMATOR,
BaseClasses.SPECIAL_SCOPE,
],
flashlightLaser: { count: 0 },
2023-03-03 15:23:46 +00:00
flashlightLaserMax: this.botConfig.equipment[botRole]?.weaponModLimits?.lightLaserLimit,
2023-11-15 20:35:05 -05:00
flashlgihtLaserBaseTypes: [
BaseClasses.TACTICAL_COMBO,
BaseClasses.FLASHLIGHT,
BaseClasses.PORTABLE_RANGE_FINDER,
],
2023-03-03 15:23:46 +00:00
};
}
/**
* Check if weapon mod item is on limited list + has surpassed the limit set for it
* Exception: Always allow ncstar backup mount
* Exception: Always allow scopes with a scope for a parent
* Exception: Always disallow mounts that hold only scopes once scope limit reached
* Exception: Always disallow mounts that hold only flashlights once flashlight limit reached
* @param botRole role the bot has e.g. assault
* @param modTemplate mods template data
* @param modLimits limits set for weapon being generated for this bot
* @param modsParent The parent of the mod to be checked
* @returns true if over item limit
*/
2023-11-15 20:35:05 -05:00
public weaponModHasReachedLimit(
botRole: string,
modTemplate: ITemplateItem,
modLimits: BotModLimits,
modsParent: ITemplateItem,
weapon: IItem[],
): boolean {
2023-03-03 15:23:46 +00:00
// 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
) {
2023-03-03 15:23:46 +00:00
// If weapon already has a longer ranged scope on it, allow ncstar to be spawned
2023-11-15 20:35:05 -05:00
if (
weapon.some((item) =>
this.itemHelper.isOfBaseclasses(item._tpl, [
2023-11-15 20:35:05 -05:00
BaseClasses.ASSAULT_SCOPE,
BaseClasses.OPTIC_SCOPE,
BaseClasses.SPECIAL_SCOPE,
]),
2023-11-15 20:35:05 -05:00
)
) {
2023-03-03 15:23:46 +00:00
return false;
}
return true;
}
// Mods parent is scope and mod is scope, allow it (adds those mini-sights to the tops of sights)
2023-03-03 15:23:46 +00:00
const modIsScope = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.scopeBaseTypes);
if (this.itemHelper.isOfBaseclasses(modsParent._id, modLimits.scopeBaseTypes) && modIsScope) {
2023-03-03 15:23:46 +00:00
return false;
}
// If mod is a scope , Exit early
if (modIsScope) {
2023-03-03 15:23:46 +00:00
return this.weaponModLimitReached(modTemplate._id, modLimits.scope, modLimits.scopeMax, botRole);
}
// Don't allow multple 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 its for a mod_scope
2023-11-15 20:35:05 -05:00
if (
modLimits.scope.count >= modLimits.scopeMax &&
modTemplate._props.Slots?.length === 1 &&
this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) &&
!this.itemHelper.isOfBaseclass(modsParent._id, BaseClasses.MOUNT) &&
modTemplate._props.Slots.some((slot) => slot._name === "mod_scope")
) {
2023-03-03 15:23:46 +00:00
return true;
}
// If mod is a light/laser, return if limit reached
const modIsLightOrLaser = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.flashlgihtLaserBaseTypes);
if (modIsLightOrLaser) {
2023-11-15 20:35:05 -05:00
return this.weaponModLimitReached(
modTemplate._id,
modLimits.flashlightLaser,
modLimits.flashlightLaserMax,
botRole,
);
2023-03-03 15:23:46 +00:00
}
// Mod is a mount that can hold only flashlights ad limit is reached (dont want to add empty mounts if limit is reached)
2023-11-15 20:35:05 -05:00
if (
modLimits.scope.count >= modLimits.scopeMax &&
modTemplate._props.Slots?.length === 1 &&
this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT) &&
modTemplate._props.Slots.some((slot) => slot._name === "mod_flashlight")
) {
2023-03-03 15:23:46 +00:00
return true;
}
return false;
}
/**
* Check if the specific item type on the weapon has reached the set limit
* @param modTpl log mod tpl if over type limit
* @param currentCount current number of this item on gun
* @param maxLimit mod limit allowed
* @param botRole role of bot we're checking weapon of
* @returns true if limit reached
*/
2023-11-15 20:35:05 -05:00
protected weaponModLimitReached(
modTpl: string,
currentCount: { count: number },
2023-11-15 20:35:05 -05:00
maxLimit: number,
botRole: string,
): boolean {
2023-03-03 15:23:46 +00:00
// No value or 0
if (!maxLimit) {
2023-03-03 15:23:46 +00:00
return false;
}
// Has mod limit for bot type been reached
if (currentCount.count >= maxLimit) {
2023-11-15 20:35:05 -05:00
// this.logger.debug(`[${botRole}] scope limit reached! tried to add ${modTpl} but scope count is ${currentCount.count}`);
2023-03-03 15:23:46 +00:00
return true;
}
// Increment scope count
currentCount.count++;
return false;
}
2023-11-15 20:35:05 -05:00
}