4ac12ef70a
These are the formatting & linting configuration changes from the `3.8.0` branch and the changes that they make to the overall project. The majority of these changes are from running two commands: `npm run lint:fix` `npm run style:fix` This has already been run on the `3.8.0` branch and this PR should make `master` play nicer when it comes to merges going forward. There are now four VSCode plugins recommended for server development. They've been added to the workspace file and a user should get a UI notification when the workspace is opened if they're not installed. The four plugins are: https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig https://marketplace.visualstudio.com/items?itemName=dprint.dprint https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint https://marketplace.visualstudio.com/items?itemName=biomejs.biome Once installed they should just work within the workspace. Also, be sure to `npm i` to get the new dprint application. Co-authored-by: Refringe <brownelltyler@gmail.com> Reviewed-on: https://dev.sp-tarkov.com/SPT-AKI/Server/pulls/168
194 lines
6.7 KiB
TypeScript
194 lines
6.7 KiB
TypeScript
import { inject, injectable } from "tsyringe";
|
|
|
|
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
|
import { Item } from "@spt-aki/models/eft/common/tables/IItem";
|
|
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
|
|
import { BaseClasses } from "@spt-aki/models/enums/BaseClasses";
|
|
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
|
import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig";
|
|
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
|
import { ConfigServer } from "@spt-aki/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;
|
|
}
|
|
}
|