2024-05-21 17:59:04 +00:00
import { MinMax } from "@spt/models/common/MinMax" ;
2024-09-24 12:47:29 +01:00
import { IBotType , IDifficultyCategories } from "@spt/models/eft/common/tables/IBotType" ;
2024-05-21 17:59:04 +00:00
import { ConfigTypes } from "@spt/models/enums/ConfigTypes" ;
2024-10-19 12:43:38 +01:00
import { EquipmentFilters , IBotConfig , IRandomisationDetails } from "@spt/models/spt/config/IBotConfig" ;
2024-05-21 17:59:04 +00:00
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig" ;
import { ILogger } from "@spt/models/spt/utils/ILogger" ;
import { ConfigServer } from "@spt/servers/ConfigServer" ;
2024-05-28 22:24:52 +01:00
import { DatabaseService } from "@spt/services/DatabaseService" ;
2024-05-21 17:59:04 +00:00
import { RandomUtil } from "@spt/utils/RandomUtil" ;
2024-10-18 11:39:51 +01:00
import { max } from "date-fns" ;
2024-07-23 11:12:53 -04:00
import { inject , injectable } from "tsyringe" ;
2023-03-03 15:23:46 +00:00
@injectable ( )
2024-07-23 11:12:53 -04:00
export class BotHelper {
2023-03-03 15:23:46 +00:00
protected botConfig : IBotConfig ;
2023-10-10 11:03:20 +00:00
protected pmcConfig : IPmcConfig ;
2023-03-03 15:23:46 +00:00
constructor (
2024-05-28 14:04:20 +00:00
@inject ( "PrimaryLogger" ) protected logger : ILogger ,
2024-05-28 22:24:52 +01:00
@inject ( "DatabaseService" ) protected databaseService : DatabaseService ,
2023-03-03 15:23:46 +00:00
@inject ( "RandomUtil" ) protected randomUtil : RandomUtil ,
2023-11-13 11:07:59 -05:00
@inject ( "ConfigServer" ) protected configServer : ConfigServer ,
2024-07-23 11:12:53 -04:00
) {
2023-03-03 15:23:46 +00:00
this . botConfig = this . configServer . getConfig ( ConfigTypes . BOT ) ;
2023-10-10 11:03:20 +00:00
this . pmcConfig = this . configServer . getConfig ( ConfigTypes . PMC ) ;
2023-03-03 15:23:46 +00:00
}
/ * *
* Get a template object for the specified botRole from bots . types db
* @param role botRole to get template for
* @returns IBotType object
* /
2024-07-23 11:12:53 -04:00
public getBotTemplate ( role : string ) : IBotType {
2024-05-28 22:24:52 +01:00
return this . databaseService . getBots ( ) . types [ role . toLowerCase ( ) ] ;
2023-03-03 15:23:46 +00:00
}
/ * *
* Is the passed in bot role a PMC ( usec / bear / pmc )
* @param botRole bot role to check
* @returns true if is pmc
* /
2024-07-23 11:12:53 -04:00
public isBotPmc ( botRole : string ) : boolean {
2024-06-06 16:59:44 +00:00
return [ "usec" , "bear" , "pmc" , "pmcbear" , "pmcusec" ] . includes ( botRole ? . toLowerCase ( ) ) ;
2023-03-03 15:23:46 +00:00
}
2024-07-23 11:12:53 -04:00
public isBotBoss ( botRole : string ) : boolean {
2024-05-17 15:32:41 -04:00
return this . botConfig . bosses . some ( ( x ) = > x . toLowerCase ( ) === botRole ? . toLowerCase ( ) ) ;
2023-03-03 15:23:46 +00:00
}
2024-07-23 11:12:53 -04:00
public isBotFollower ( botRole : string ) : boolean {
2023-11-05 20:29:10 +00:00
return botRole ? . toLowerCase ( ) . startsWith ( "follower" ) ;
2023-03-03 15:23:46 +00:00
}
/ * *
* Add a bot to the FRIENDLY_BOT_TYPES array
* @param difficultySettings bot settings to alter
* @param typeToAdd bot type to add to friendly list
* /
2024-09-24 12:47:29 +01:00
public addBotToFriendlyList ( difficultySettings : IDifficultyCategories , typeToAdd : string ) : void {
2023-03-03 15:23:46 +00:00
const friendlyBotTypesKey = "FRIENDLY_BOT_TYPES" ;
// Null guard
2024-07-23 11:12:53 -04:00
if ( ! difficultySettings . Mind [ friendlyBotTypesKey ] ) {
2023-03-03 15:23:46 +00:00
difficultySettings . Mind [ friendlyBotTypesKey ] = [ ] ;
}
( < string [ ] > difficultySettings . Mind [ friendlyBotTypesKey ] ) . push ( typeToAdd ) ;
}
/ * *
* Add a bot to the REVENGE_BOT_TYPES array
* @param difficultySettings bot settings to alter
* @param typesToAdd bot type to add to revenge list
* /
2024-09-24 12:47:29 +01:00
public addBotToRevengeList ( difficultySettings : IDifficultyCategories , typesToAdd : string [ ] ) : void {
2023-03-03 15:23:46 +00:00
const revengePropKey = "REVENGE_BOT_TYPES" ;
// Nothing to add
2024-07-23 11:12:53 -04:00
if ( ! typesToAdd ) {
2023-03-03 15:23:46 +00:00
return ;
}
// Null guard
2024-07-23 11:12:53 -04:00
if ( ! difficultySettings . Mind [ revengePropKey ] ) {
2023-03-03 15:23:46 +00:00
difficultySettings . Mind [ revengePropKey ] = [ ] ;
}
const revengeArray = < string [ ] > difficultySettings . Mind [ revengePropKey ] ;
2024-07-23 11:12:53 -04:00
for ( const botTypeToAdd of typesToAdd ) {
if ( ! revengeArray . includes ( botTypeToAdd ) ) {
2023-03-03 15:23:46 +00:00
revengeArray . push ( botTypeToAdd ) ;
}
}
}
2024-09-23 23:01:47 +01:00
public rollChanceToBePmc ( botConvertMinMax : MinMax ) : boolean {
return this . randomUtil . getChance100 ( this . randomUtil . getInt ( botConvertMinMax . min , botConvertMinMax . max ) ) ;
2023-03-03 15:23:46 +00:00
}
2024-09-23 22:56:22 +01:00
protected getPmcConversionValuesForLocation ( location : string ) {
const result = this . pmcConfig . convertIntoPmcChance [ location . toLowerCase ( ) ] ;
if ( ! result ) {
this . pmcConfig . convertIntoPmcChance . default ;
}
return result ;
}
2024-06-27 14:09:26 +00:00
/ * *
* is the provided role a PMC , case - agnostic
* @param botRole Role to check
* @returns True if role is PMC
* /
2024-07-23 11:12:53 -04:00
public botRoleIsPmc ( botRole : string ) : boolean {
2023-11-13 11:07:59 -05:00
return [ this . pmcConfig . usecType . toLowerCase ( ) , this . pmcConfig . bearType . toLowerCase ( ) ] . includes (
botRole . toLowerCase ( ) ,
) ;
2023-03-03 15:23:46 +00:00
}
/ * *
* Get randomization settings for bot from config / bot . json
* @param botLevel level of bot
* @param botEquipConfig bot equipment json
* @returns RandomisationDetails
* /
2024-05-27 20:06:07 +00:00
public getBotRandomizationDetails (
botLevel : number ,
botEquipConfig : EquipmentFilters ,
2024-10-19 12:43:38 +01:00
) : IRandomisationDetails | undefined {
2023-03-03 15:23:46 +00:00
// No randomisation details found, skip
2024-07-23 11:12:53 -04:00
if ( ! botEquipConfig || Object . keys ( botEquipConfig ) . length === 0 || ! botEquipConfig . randomisation ) {
2024-05-27 20:06:07 +00:00
return undefined ;
2023-03-03 15:23:46 +00:00
}
2023-11-13 11:07:59 -05:00
2024-09-28 23:29:08 +01:00
return botEquipConfig . randomisation . find (
( randDetails ) = > botLevel >= randDetails . levelRange . min && botLevel <= randDetails . levelRange . max ,
) ;
2023-03-03 15:23:46 +00:00
}
/ * *
2024-06-06 16:59:44 +00:00
* Choose between pmcBEAR and pmcUSEC at random based on the % defined in pmcConfig . isUsec
2023-03-03 15:23:46 +00:00
* @returns pmc role
* /
2024-07-23 11:12:53 -04:00
public getRandomizedPmcRole ( ) : string {
2024-05-17 15:32:41 -04:00
return this . randomUtil . getChance100 ( this . pmcConfig . isUsec ) ? this . pmcConfig.usecType : this.pmcConfig.bearType ;
2023-03-03 15:23:46 +00:00
}
/ * *
2024-06-06 16:59:44 +00:00
* Get the corresponding side when pmcBEAR or pmcUSEC is passed in
2023-03-03 15:23:46 +00:00
* @param botRole role to get side for
* @returns side ( usec / bear )
* /
2024-07-23 11:12:53 -04:00
public getPmcSideByRole ( botRole : string ) : string {
switch ( botRole . toLowerCase ( ) ) {
2023-10-10 11:03:20 +00:00
case this . pmcConfig . bearType . toLowerCase ( ) :
2023-03-03 15:23:46 +00:00
return "Bear" ;
2023-10-10 11:03:20 +00:00
case this . pmcConfig . usecType . toLowerCase ( ) :
2023-03-03 15:23:46 +00:00
return "Usec" ;
default :
return this . getRandomizedPmcSide ( ) ;
}
}
/ * *
* Get a randomized PMC side based on bot config value 'isUsec'
* @returns pmc side as string
* /
2024-07-23 11:12:53 -04:00
protected getRandomizedPmcSide ( ) : string {
2024-05-07 23:57:08 -04:00
return this . randomUtil . getChance100 ( this . pmcConfig . isUsec ) ? "Usec" : "Bear" ;
2023-03-03 15:23:46 +00:00
}
2024-05-22 13:26:35 +01:00
2024-10-18 11:39:51 +01:00
/ * *
* Get a name from a PMC that fits the desired length
* @param maxLength Max length of name , inclusive
* @param side OPTIONAL - what side PMC to get name from ( usec / bear )
* @returns name of PMC
* /
public getPmcNicknameOfMaxLength ( maxLength : number , side? : string ) : string {
const randomType = side ? side : this.randomUtil.getInt ( 0 , 1 ) === 0 ? "usec" : "bear" ;
2024-10-18 19:10:28 +01:00
const allNames = this . databaseService . getBots ( ) . types [ randomType . toLowerCase ( ) ] . firstName ;
2024-10-18 11:39:51 +01:00
const filteredNames = allNames . filter ( ( name ) = > name . length <= maxLength ) ;
if ( filteredNames . length === 0 ) {
this . logger . warning (
` Unable to filter: ${ randomType } PMC names to only those under: ${ maxLength } , none found that match that criteria, selecting from entire name pool instead ` ,
) ;
return this . randomUtil . getStringArrayValue ( allNames ) ;
}
return this . randomUtil . getStringArrayValue ( filteredNames ) ;
2024-05-22 13:26:35 +01:00
}
2023-11-13 11:07:59 -05:00
}