Added config system to adjust raid hostility settings

Removed `enemyTypes` from pmcconfig
This commit is contained in:
Dev 2024-09-18 11:36:45 +01:00
parent f52283f3b3
commit 3952b34e29
3 changed files with 124 additions and 40 deletions

View File

@ -773,43 +773,44 @@
"max": 0
}
},
"enemyTypes": [
"assault",
"marksman",
"pmcBot",
"bossBully",
"bossKilla",
"bossKojaniy",
"bossGluhar",
"bossSanitar",
"bossTagilla",
"bossKnight",
"bossZryachiy",
"bossBoar",
"bossBoarSniper",
"bossKolontay",
"bossPartisan",
"followerBully",
"followerKojaniy",
"followerGluharAssault",
"followerGluharSecurity",
"followerGluharScout",
"followerGluharSnipe",
"followerSanitar",
"followerBirdEye",
"followerBigPipe",
"followerZryachiy",
"followerBoar",
"followerBoarClose1",
"followerBoarClose2",
"followerKolontayAssault",
"followerKolontaySecurity",
"arenaFighter",
"arenaFighterEvent",
"crazyAssaultEvent",
"sectantWarrior",
"sectantPriest"
],
"hostilitySettings": {
"pmcbear": {
"additionalEnemyTypes": [
"bossPartizan"
],
"ChancedEnemies": [{
"EnemyChance": 100,
"Role": "assault"
}, {
"EnemyChance": 100,
"Role": "marksman"
}, {
"EnemyChance": 85,
"Role": "pmcUSEC"
}
],
"BearEnemyChance": 85,
"UsecEnemyChance": 100
},
"pmcbear": {
"additionalEnemyTypes": [
"bossPartizan"
],
"ChancedEnemies": [{
"EnemyChance": 100,
"Role": "assault"
}, {
"EnemyChance": 100,
"Role": "marksman"
}, {
"EnemyChance": 85,
"Role": "pmcBEAR"
}
],
"BearEnemyChance": 85,
"UsecEnemyChance": 100
}
},
"forceHealingItemsIntoSecure": true,
"addPrefixToSameNamePMCAsPlayerChance": 40,
"allPMCsHavePlayerNameWithRandomPrefixChance": 1,

View File

@ -1,4 +1,5 @@
import { MinMax } from "@spt/models/common/MinMax";
import { IChancedEnemy } from "@spt/models/eft/common/ILocationBase";
import { MemberCategory } from "@spt/models/enums/MemberCategory";
import { IBaseConfig } from "@spt/models/spt/config/IBaseConfig";
@ -37,20 +38,30 @@ export interface IPmcConfig extends IBaseConfig {
maxVestLootTotalRub: number;
/** Percentage chance a bot from a wave is converted into a PMC, key = bot wildspawn tpye (assault/exusec), value: min+max chance to be converted */
convertIntoPmcChance: Record<string, MinMax>;
/** WildSpawnType bots PMCs should see as hostile */
enemyTypes: string[];
/** How many levels above player level can a PMC be */
botRelativeLevelDeltaMax: number;
/** How many levels below player level can a PMC be */
botRelativeLevelDeltaMin: number;
/** Force a number of healing items into PMCs secure container to ensure they can heal */
forceHealingItemsIntoSecure: boolean;
hostilitySettings: Record<string, IHostilitySettings>;
allPMCsHavePlayerNameWithRandomPrefixChance: number;
locationSpecificPmcLevelOverride: Record<string, MinMax>;
/** Should secure container loot from usec.json/bear.json be added to pmc bots secure */
addSecureContainerLootFromBotConfig: boolean;
}
export interface IHostilitySettings {
/** Bot roles that are 100% an enemy */
additionalEnemyTypes?: string[];
/** Objects that determine the % chance another bot type is an enemy */
ChancedEnemies?: IChancedEnemy[];
BearEnemyChance?: number;
UsecEnemyChance?: number;
/** Bot roles that are 100% an friendly */
additionalFriendlyTypes?: string[];
}
export interface PmcTypes {
usec: string;
bear: string;

View File

@ -21,6 +21,7 @@ import { Traders } from "@spt/models/enums/Traders";
import { IHideoutConfig } from "@spt/models/spt/config/IHideoutConfig";
import { IInRaidConfig } from "@spt/models/spt/config/IInRaidConfig";
import { ILocationConfig } from "@spt/models/spt/config/ILocationConfig";
import { IPmcConfig } from "@spt/models/spt/config/IPmcConfig";
import { IRagfairConfig } from "@spt/models/spt/config/IRagfairConfig";
import { ITraderConfig } from "@spt/models/spt/config/ITraderConfig";
import { IRaidChanges } from "@spt/models/spt/location/IRaidChanges";
@ -50,6 +51,7 @@ export class LocationLifecycleService {
protected ragfairConfig: IRagfairConfig;
protected hideoutConfig: IHideoutConfig;
protected locationConfig: ILocationConfig;
protected pmcConfig: IPmcConfig;
constructor(
@inject("PrimaryLogger") protected logger: ILogger,
@ -83,6 +85,7 @@ export class LocationLifecycleService {
this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR);
this.hideoutConfig = this.configServer.getConfig(ConfigTypes.HIDEOUT);
this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION);
this.pmcConfig = this.configServer.getConfig(ConfigTypes.PMC);
}
/** Handle client/match/local/start */
@ -96,6 +99,9 @@ export class LocationLifecycleService {
locationLoot: this.generateLocationAndLoot(request.location),
};
// Apply changes from pmcConfig to bot hostility values
this.adjustBotHostilitySettings(result.locationLoot);
// Clear bot cache ready for a fresh raid
this.botGenerationCacheService.clearStoredBots();
this.botNameService.clearNameCache();
@ -104,7 +110,73 @@ export class LocationLifecycleService {
}
/**
* Generate a maps base location and loot
* Adjust the bot hostility values prior to entering a raid
* @param location map to adjust values of
*/
protected adjustBotHostilitySettings(location: ILocationBase): void {
for (const botId in this.pmcConfig.hostilitySettings) {
const configHostilityChanges = this.pmcConfig.hostilitySettings[botId];
const locationBotHostilityDetails = location.BotLocationModifier.AdditionalHostilitySettings.find(
(botSettings) => botSettings.BotRole.toLowerCase() === botId,
);
// No matching bot in config, skip
if (!locationBotHostilityDetails) {
this.logger.warning(
`No bot: ${botId} hostility values found on: ${location.Id}, can only edit existing. Skipping`,
);
continue;
}
// Add new permanent enemies if they don't already exist
if (configHostilityChanges.additionalEnemyTypes) {
for (const enemyTypeToAdd of configHostilityChanges.additionalEnemyTypes) {
if (!locationBotHostilityDetails.AlwaysEnemies.includes(enemyTypeToAdd)) {
locationBotHostilityDetails.AlwaysEnemies.push(enemyTypeToAdd);
}
}
}
// Add/edit chance settings
if (configHostilityChanges.ChancedEnemies) {
for (const chanceDetailsToApply of configHostilityChanges.ChancedEnemies) {
const locationBotDetails = locationBotHostilityDetails.ChancedEnemies.find(
(botChance) => botChance.Role === chanceDetailsToApply.Role,
);
if (locationBotDetails) {
// Existing
locationBotDetails.EnemyChance = chanceDetailsToApply.EnemyChance;
} else {
// Add new
locationBotHostilityDetails.ChancedEnemies.push(chanceDetailsToApply);
}
}
}
// Add new permanent friends if they don't already exist
if (configHostilityChanges.additionalFriendlyTypes) {
for (const friendlyTypeToAdd of configHostilityChanges.additionalFriendlyTypes) {
if (!locationBotHostilityDetails.AlwaysFriends.includes(friendlyTypeToAdd)) {
locationBotHostilityDetails.AlwaysFriends.push(friendlyTypeToAdd);
}
}
}
// Adjust bear hostility chance
if (typeof configHostilityChanges.BearEnemyChance !== "undefined") {
locationBotHostilityDetails.BearEnemyChance = configHostilityChanges.BearEnemyChance;
}
// Adjust usec hostility chance
if (typeof configHostilityChanges.UsecEnemyChance !== "undefined") {
locationBotHostilityDetails.UsecEnemyChance = configHostilityChanges.UsecEnemyChance;
}
}
}
/**
* Generate a maps base location (cloned) and loot
* @param name Map name
* @returns ILocationBase
*/