Server/project/src/services/BotWeaponModLimitService.ts
2023-03-03 15:23:46 +00:00

155 lines
6.1 KiB
TypeScript

import { inject, injectable } from "tsyringe";
import { ItemHelper } from "../helpers/ItemHelper";
import { Item } from "../models/eft/common/tables/IItem";
import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { BaseClasses } from "../models/enums/BaseClasses";
import { ConfigTypes } from "../models/enums/ConfigTypes";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
export class BotModLimits
{
scope: ItemCount;
scopeMax: number;
scopeBaseTypes: string[];
flashlightLaser: ItemCount;
flashlightLaserMax: number;
flashlgihtLaserBaseTypes: string[];
}
export class ItemCount
{
count: number;
}
@injectable()
export class BotWeaponModLimitService
{
protected botConfig: IBotConfig;
constructor(
@inject("WinstonLogger") protected logger: ILogger,
@inject("ConfigServer") protected configServer: ConfigServer,
@inject("ItemHelper") protected itemHelper: ItemHelper
)
{
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
{
return {
scope: {count: 0},
scopeMax: this.botConfig.equipment[botRole]?.weaponModLimits?.scopeLimit,
scopeBaseTypes: [BaseClasses.OPTIC_SCOPE, BaseClasses.ASSAULT_SCOPE, BaseClasses.COLLIMATOR, BaseClasses.COMPACT_COLLIMATOR, BaseClasses.SPECIAL_SCOPE],
flashlightLaser: {count: 0},
flashlightLaserMax: this.botConfig.equipment[botRole]?.weaponModLimits?.lightLaserLimit,
flashlgihtLaserBaseTypes: [BaseClasses.TACTICAL_COMBO, BaseClasses.FLASHLIGHT, BaseClasses.PORTABLE_RANGE_FINDER]
};
}
/**
* 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
*/
public weaponModHasReachedLimit(botRole: string, modTemplate: ITemplateItem, modLimits: BotModLimits, modsParent: ITemplateItem, weapon: Item[]): boolean
{
// If mod or mods parent is the NcSTAR MPR45 Backup mount, allow it as it looks cool
const ncSTARTpl = "5649a2464bdc2d91118b45a8";
if (modsParent._id === ncSTARTpl || modTemplate._id === ncSTARTpl)
{
// If weapon already has a longer ranged scope on it, allow ncstar to be spawned
if (weapon.some(x => this.itemHelper.isOfBaseclasses(x._tpl, [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)
const modIsScope = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.scopeBaseTypes);
if (this.itemHelper.isOfBaseclasses(modsParent._id, modLimits.scopeBaseTypes) && modIsScope)
{
return false;
}
// If mod is a scope, return if limit reached
if (modIsScope)
{
return this.weaponModLimitReached(modTemplate._id, modLimits.scope, modLimits.scopeMax, botRole);
}
// Mod is a mount that can hold only scopes and limit is reached (dont want to add empty mounts if limit is reached)
if (this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT)
&& modTemplate._props.Slots.some(x => x._name === "mod_scope")
&& modTemplate._props.Slots.length === 1
&& modLimits.scope.count >= modLimits.scopeMax)
{
return true;
}
// If mod is a light/laser, return if limit reached
const modIsLightOrLaser = this.itemHelper.isOfBaseclasses(modTemplate._id, modLimits.flashlgihtLaserBaseTypes);
if (modIsLightOrLaser)
{
return this.weaponModLimitReached(modTemplate._id, modLimits.flashlightLaser, modLimits.flashlightLaserMax, botRole);
}
// Mod is a mount that can hold only flashlights ad limit is reached (dont want to add empty mounts if limit is reached)
if (this.itemHelper.isOfBaseclass(modTemplate._id, BaseClasses.MOUNT)
&& modTemplate._props.Slots.some(x => x._name === "mod_flashlight")
&& modTemplate._props.Slots.length === 1
&& modLimits.scope.count >= modLimits.scopeMax)
{
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
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected weaponModLimitReached(modTpl: string, currentCount: { count: number; }, maxLimit: number, botRole: string): boolean
{
// No value or 0
if (!maxLimit)
{
return false;
}
// Has mod limit for bot type been reached
if (currentCount.count >= maxLimit)
{
//this.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;
}
}