Archived
Updated Progressive Bot System
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
[General]
|
||||
gameName=spt
|
||||
modid=0
|
||||
version=d2025.1.3.0
|
||||
version=d2025.1.7.0
|
||||
newestVersion=
|
||||
category="1,"
|
||||
nexusFileStatus=1
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Acids Progressive Bot System",
|
||||
"version": "1.3.1",
|
||||
"version": "1.4.0-alpha",
|
||||
"sptVersion": "~3.10",
|
||||
"loadBefore": [],
|
||||
"loadAfter": [
|
||||
|
||||
+854
-870
File diff suppressed because it is too large
Load Diff
+1
@@ -558,6 +558,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
|
||||
+864
-872
File diff suppressed because it is too large
Load Diff
+1
@@ -614,6 +614,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
|
||||
+872
-894
File diff suppressed because it is too large
Load Diff
+866
-912
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -866,6 +866,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -877,7 +878,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+851
-911
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -798,6 +798,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -809,7 +810,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+852
-912
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -784,6 +784,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -795,7 +796,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+851
-911
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -764,6 +764,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -775,7 +776,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+68
-90
@@ -23,6 +23,33 @@ export class BotConfigs
|
||||
protected botConfig: IBotConfig;
|
||||
protected pmcConfig: IPmcConfig;
|
||||
|
||||
private pmcLimitedCategories = {
|
||||
"5448e8d04bdc2ddf718b4569": 1,
|
||||
"5448e8d64bdc2dce718b4568": 1,
|
||||
"5448f39d4bdc2d0a728b4568": 1,
|
||||
"5448f3a64bdc2d60728b456a": 2,
|
||||
"5448f3ac4bdc2dce718b4569": 1,
|
||||
"5448f3a14bdc2d27728b4569": 1,
|
||||
"5c99f98d86f7745c314214b3": 1,
|
||||
"5c164d2286f774194c5e69fa": 1,
|
||||
"550aa4cd4bdc2dd8348b456c": 2,
|
||||
"55818add4bdc2d5b648b456f": 1,
|
||||
"55818ad54bdc2ddc698b4569": 1,
|
||||
"55818aeb4bdc2ddc698b456a": 1,
|
||||
"55818ae44bdc2dde698b456c": 1,
|
||||
"55818af64bdc2d5b648b4570": 1,
|
||||
"5448e54d4bdc2dcc718b4568": 1,
|
||||
"5447e1d04bdc2dff2f8b4567": 1,
|
||||
"5a341c4686f77469e155819e": 1,
|
||||
"55818b164bdc2ddc698b456c": 2,
|
||||
"5448bc234bdc2d3c308b4569": 2,
|
||||
"543be5dd4bdc2deb348b4569": 1,
|
||||
"543be5cb4bdc2deb348b4568": 2,
|
||||
"5485a8684bdc2da71d8b4567": 2,
|
||||
"5d650c3e815116009f6201d2": 2,
|
||||
"543be6564bdc2df4348b4568": 1
|
||||
}
|
||||
|
||||
constructor(
|
||||
@inject("IDatabaseTables") protected tables: IDatabaseTables,
|
||||
@inject("DatabaseService") protected database: DatabaseService,
|
||||
@@ -40,25 +67,33 @@ export class BotConfigs
|
||||
|
||||
public initialize(): void
|
||||
{
|
||||
if (!ModConfig.config.disablePMCTierGeneration)
|
||||
{
|
||||
this.setPMCItemLimits();
|
||||
this.setPMCLoot();
|
||||
this.setPMCScopeWhitelist();
|
||||
this.setPMCSlotIDsToMakeRequired();
|
||||
if (ModConfig.config.gameVersionWeight) this.setPMCGameVersionWeights();
|
||||
}
|
||||
if (!ModConfig.config.disableScavTierGeneration)
|
||||
{
|
||||
if (ModConfig.config.addAllKeysToScavs || ModConfig.config.addOnlyKeyCardsToScavs || ModConfig.config.addOnlyMechanicalKeysToScavs) this.pushScavKeys();
|
||||
if (!ModConfig.config.scavLoot) this.removeScavLoot();
|
||||
}
|
||||
|
||||
this.clearNoLongerNeededBotDetails();
|
||||
this.configureBotExperienceLevels();
|
||||
this.configurePlateWeightings();
|
||||
this.configureWeaponDurability();
|
||||
this.adjustNVG();
|
||||
this.setLootItemResourceRandomization();
|
||||
this.setPMCItemLimits();
|
||||
this.setPMCLoot();
|
||||
this.setPMCScopeWhitelist();
|
||||
this.setPMCSlotIDsToMakeRequired();
|
||||
this.removeThermalGoggles(ModConfig.config.enableT7Thermals);
|
||||
if (ModConfig.config.gameVersionWeight) this.setPMCGameVersionWeights();
|
||||
if (ModConfig.config.addAllKeysToScavs || ModConfig.config.addOnlyKeyCardsToScavs || ModConfig.config.addOnlyMechanicalKeysToScavs) this.pushScavKeys();
|
||||
|
||||
if (ModConfig.config.enableCustomPlateChances) this.setPlateChances();
|
||||
if (ModConfig.config.forceStock) this.setForceStock();
|
||||
if (ModConfig.config.forceDustCover) this.setForceDustCover();
|
||||
if (ModConfig.config.forceScopeSlot) this.setForceScopes();
|
||||
if (ModConfig.config.forceWeaponModLimits) this.setWeaponModLimits();
|
||||
if (!ModConfig.config.scavLoot) this.removeScavLoot();
|
||||
if (ModConfig.config.enableScavEqualEquipmentTiering) this.setIdenticalScavWeights();
|
||||
if (ModConfig.config.enableCustomLevelDeltas) this.setLevelDeltas();
|
||||
if (ModConfig.config.enableScavCustomLevelDeltas) this.setScavLevelDeltas();
|
||||
@@ -319,21 +354,24 @@ export class BotConfigs
|
||||
|
||||
private setPMCItemLimits(): void
|
||||
{
|
||||
this.botConfig.itemSpawnLimits.pmc["60098ad7c2240c0fe85c570a"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["590c678286f77426c9660122"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["5e831507ea0a7c419c2f9bd9"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["590c661e86f7741e566b646a"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["544fb45d4bdc2dee738b4568"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["5e8488fa988a8701445df1e4"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["544fb37f4bdc2dee738b4567"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["5448e8d04bdc2ddf718b4569"] = 1;
|
||||
this.botConfig.itemSpawnLimits.pmc["5448e8d64bdc2dce718b4568"] = 1;
|
||||
// Clear PMC item limits
|
||||
this.botConfig.itemSpawnLimits.pmc = {}
|
||||
|
||||
// Go through custom limits and add them
|
||||
for (const [item, count] of Object.entries(this.pmcLimitedCategories))
|
||||
{
|
||||
this.botConfig.itemSpawnLimits.pmc[item] = count;
|
||||
}
|
||||
}
|
||||
|
||||
private setPMCLoot(): void
|
||||
{
|
||||
const allBots = this.database.getTables().bots.types;
|
||||
|
||||
this.pmcConfig.looseWeaponInBackpackLootMinMax.min = 0;
|
||||
this.pmcConfig.looseWeaponInBackpackLootMinMax.max = 0;
|
||||
this.botConfig.equipment.pmc.randomisation = [];
|
||||
|
||||
if (ModConfig.config.pmcLoot)
|
||||
{
|
||||
if (ModConfig.config.pmcLootBlacklistItems.length > 0)
|
||||
@@ -345,77 +383,22 @@ export class BotConfigs
|
||||
this.pmcConfig.pocketLoot.blacklist.push(item);
|
||||
}
|
||||
}
|
||||
for (const level in this.tierInformation.lootRandomization)
|
||||
{
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["0"] = 1
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["3"] = 2
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["5"] = 5
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["8"] = 6
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["10"] = 5
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["12"] = 4
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["15"] = 4
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["20"] = 3
|
||||
this.tierInformation.lootRandomization[level].generation.backpackLoot.weights["23"] = 1
|
||||
|
||||
this.tierInformation.lootRandomization[level].generation.pocketLoot.weights["0"] = 1
|
||||
this.tierInformation.lootRandomization[level].generation.pocketLoot.weights["1"] = 3
|
||||
this.tierInformation.lootRandomization[level].generation.pocketLoot.weights["2"] = 4
|
||||
this.tierInformation.lootRandomization[level].generation.pocketLoot.weights["3"] = 2
|
||||
this.tierInformation.lootRandomization[level].generation.pocketLoot.weights["4"] = 1
|
||||
|
||||
this.tierInformation.lootRandomization[level].generation.vestLoot.weights["0"] = 1
|
||||
this.tierInformation.lootRandomization[level].generation.vestLoot.weights["1"] = 2
|
||||
this.tierInformation.lootRandomization[level].generation.vestLoot.weights["2"] = 3
|
||||
this.tierInformation.lootRandomization[level].generation.vestLoot.weights["3"] = 2
|
||||
this.tierInformation.lootRandomization[level].generation.vestLoot.weights["4"] = 1
|
||||
}
|
||||
for (const tierObject in this.tierInformation.tiers)
|
||||
{
|
||||
const tierNumber = this.tierInformation.tiers[tierObject].tier
|
||||
const tierJson = this.apbsEquipmentGetter.getTierChancesJson(tierNumber);
|
||||
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["0"] = 4
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["1"] = 15
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["2"] = 40
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["3"] = 10
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["4"] = 8
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["5"] = 2
|
||||
tierJson.pmcUSEC.chances.generation.items.backpackLoot.weights["10"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["0"] = 4
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["1"] = 15
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["2"] = 40
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["3"] = 10
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["4"] = 8
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["5"] = 2
|
||||
tierJson.pmcBEAR.chances.generation.items.backpackLoot.weights["10"] = 1
|
||||
|
||||
tierJson.pmcUSEC.chances.generation.items.pocketLoot.weights["0"] = 4
|
||||
tierJson.pmcUSEC.chances.generation.items.pocketLoot.weights["1"] = 9
|
||||
tierJson.pmcUSEC.chances.generation.items.pocketLoot.weights["2"] = 1
|
||||
tierJson.pmcUSEC.chances.generation.items.pocketLoot.weights["3"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.pocketLoot.weights["0"] = 4
|
||||
tierJson.pmcBEAR.chances.generation.items.pocketLoot.weights["1"] = 9
|
||||
tierJson.pmcBEAR.chances.generation.items.pocketLoot.weights["2"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.pocketLoot.weights["3"] = 1
|
||||
|
||||
tierJson.pmcUSEC.chances.generation.items.vestLoot.weights["0"] = 2
|
||||
tierJson.pmcUSEC.chances.generation.items.vestLoot.weights["1"] = 12
|
||||
tierJson.pmcUSEC.chances.generation.items.vestLoot.weights["2"] = 1
|
||||
tierJson.pmcUSEC.chances.generation.items.vestLoot.weights["3"] = 1
|
||||
tierJson.pmcUSEC.chances.generation.items.vestLoot.weights["4"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.vestLoot.weights["0"] = 2
|
||||
tierJson.pmcBEAR.chances.generation.items.vestLoot.weights["1"] = 12
|
||||
tierJson.pmcBEAR.chances.generation.items.vestLoot.weights["2"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.vestLoot.weights["3"] = 1
|
||||
tierJson.pmcBEAR.chances.generation.items.vestLoot.weights["4"] = 1
|
||||
}
|
||||
this.botConfig.equipment.pmc.randomisation = this.tierInformation.lootRandomization;
|
||||
}
|
||||
else
|
||||
if (!ModConfig.config.pmcLoot)
|
||||
{
|
||||
this.botConfig.disableLootOnBotTypes.push("pmcusec", "pmcbear")
|
||||
}
|
||||
|
||||
for (const botType in allBots)
|
||||
{
|
||||
this.botConfig.equipment.pmc.randomisation = this.tierInformation.lootRandomization;
|
||||
if (botType == "pmcbear" || botType == "pmcusec")
|
||||
{
|
||||
allBots[botType].inventory.items.Backpack = {};
|
||||
allBots[botType].inventory.items.Pockets = {};
|
||||
allBots[botType].inventory.items.TacticalVest = {};
|
||||
allBots[botType].inventory.items.SpecialLoot = {};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private setPMCScopeWhitelist(): void
|
||||
@@ -514,12 +497,7 @@ export class BotConfigs
|
||||
|
||||
private removeScavLoot(): void
|
||||
{
|
||||
this.tables.bots.types.assault.inventory.items.Backpack = {}
|
||||
this.tables.bots.types.assault.inventory.items.Pockets = {}
|
||||
this.tables.bots.types.assault.inventory.items.TacticalVest = {}
|
||||
this.tables.bots.types.marksman.inventory.items.Backpack = {}
|
||||
this.tables.bots.types.marksman.inventory.items.Pockets = {}
|
||||
this.tables.bots.types.marksman.inventory.items.TacticalVest = {}
|
||||
this.botConfig.disableLootOnBotTypes.push("assault", "marksman");
|
||||
}
|
||||
|
||||
private setIdenticalScavWeights(): void
|
||||
|
||||
+8
-34
@@ -40,6 +40,8 @@ import { RaidInformation } from "../Globals/RaidInformation";
|
||||
import { ModInformation } from "../Globals/ModInformation";
|
||||
import { APBSTester } from "../Utils/APBSTester";
|
||||
import { vanillaButtpads } from "../Globals/VanillaItemLists";
|
||||
import { APBSLogger } from "../Utils/APBSLogger";
|
||||
import { Logging } from "../Enums/Logging";
|
||||
|
||||
/** Handle profile related client events */
|
||||
@injectable()
|
||||
@@ -70,7 +72,8 @@ export class APBSBotEquipmentModGenerator extends BotEquipmentModGenerator
|
||||
@inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter,
|
||||
@inject("RaidInformation") protected raidInformation: RaidInformation,
|
||||
@inject("ModInformation") protected modInformation: ModInformation,
|
||||
@inject("APBSTester") protected apbsTester: APBSTester
|
||||
@inject("APBSTester") protected apbsTester: APBSTester,
|
||||
@inject("APBSLogger") protected apbsLogger: APBSLogger
|
||||
)
|
||||
{
|
||||
super(logger,
|
||||
@@ -101,43 +104,14 @@ export class APBSBotEquipmentModGenerator extends BotEquipmentModGenerator
|
||||
const botRole = settings.botData.role;
|
||||
const tier = this.apbsTierGetter.getTierByLevel(settings.botData.level);
|
||||
const tieredModPool = this.apbsEquipmentGetter.getModsByBotRole(botRole, tier)
|
||||
|
||||
let spawnChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tier);
|
||||
let compatibleModsPool = tieredModPool[parentTemplate._id]
|
||||
let actualModPool = tieredModPool;
|
||||
let spawnChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tier);
|
||||
|
||||
// Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed
|
||||
if ((ModConfig.config.disableBossTierGeneration && (botRole.includes("boss") || botRole.includes("sectant") || botRole.includes("arena"))) || botRole == "bosslegion" || botRole == "bosspunisher")
|
||||
{
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
}
|
||||
if (ModConfig.config.disableBossFollowerTierGeneration && botRole.includes("follower"))
|
||||
{
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
}
|
||||
if (ModConfig.config.disableRaiderRogueTierGeneration && (botRole.includes("exusec") || botRole.includes("pmcbot")))
|
||||
{
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
}
|
||||
if (ModConfig.config.disablePMCTierGeneration && (botRole.includes("pmcusec") || botRole.includes("pmcbear")))
|
||||
{
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
}
|
||||
if (ModConfig.config.disableScavTierGeneration && (botRole.includes("assault") || botRole.includes("marksman")))
|
||||
{
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
}
|
||||
if (botRole.includes("infected") || botRole.includes("spirit") || botRole.includes("skier") || botRole.includes("peacemaker") || botRole.includes("gifter"))
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: generateModsForEquipment`);
|
||||
spawnChances = settings.spawnChances;
|
||||
compatibleModsPool = settings.modPool[parentTemplate._id];
|
||||
actualModPool = settings.modPool;
|
||||
|
||||
+17
-84
@@ -31,6 +31,9 @@ import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { WeatherHelper } from "@spt/helpers/WeatherHelper";
|
||||
import { BotEquipmentFilterService } from "@spt/services/BotEquipmentFilterService";
|
||||
import { IGetRaidConfigurationRequestData } from "@spt/models/eft/match/IGetRaidConfigurationRequestData";
|
||||
import { RaidInformation } from "../Globals/RaidInformation";
|
||||
import { APBSLogger } from "../Utils/APBSLogger";
|
||||
import { Logging } from "../Enums/Logging";
|
||||
|
||||
/** Handle profile related client events */
|
||||
@injectable()
|
||||
@@ -57,7 +60,9 @@ export class APBSBotInventoryGenerator extends BotInventoryGenerator
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter,
|
||||
@inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter,
|
||||
@inject("APBSBotWeaponGenerator") protected apbsBotWeaponGenerator: APBSBotWeaponGenerator
|
||||
@inject("APBSBotWeaponGenerator") protected apbsBotWeaponGenerator: APBSBotWeaponGenerator,
|
||||
@inject("RaidInformation") protected raidInformation: RaidInformation,
|
||||
@inject("APBSLogger") protected apbsLogger: APBSLogger
|
||||
)
|
||||
{
|
||||
super(logger,
|
||||
@@ -90,8 +95,8 @@ export class APBSBotInventoryGenerator extends BotInventoryGenerator
|
||||
): PmcInventory
|
||||
{
|
||||
const templateInventory = botJsonTemplate.inventory;
|
||||
let wornItemChances = botJsonTemplate.chances;
|
||||
const itemGenerationLimitsMinMax = botJsonTemplate.generation;
|
||||
const wornItemChances = botJsonTemplate.chances;
|
||||
const itemGenerationLimitsMinMax: IGeneration = botJsonTemplate.generation;
|
||||
|
||||
// Generate base inventory with no items
|
||||
const botInventory = this.generateInventoryBase();
|
||||
@@ -110,55 +115,22 @@ export class APBSBotInventoryGenerator extends BotInventoryGenerator
|
||||
chosenGameVersion,
|
||||
raidConfig
|
||||
);
|
||||
// Roll weapon spawns (primary/secondary/holster) and generate a weapon for each roll that passed
|
||||
if (((botRole.includes("boss") || botRole.includes("sectant") || botRole.includes("arena")) && ModConfig.config.disableBossTierGeneration) || botRole == "bosslegion" || botRole == "bosspunisher")
|
||||
{
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
if (botRole.includes("follower") && ModConfig.config.disableBossFollowerTierGeneration)
|
||||
{
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
if ((botRole.includes("exusec") || botRole.includes("pmcbot")) && !ModConfig.config.disableRaiderRogueTierGeneration)
|
||||
{
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
if (botRole.includes("pmc") && ModConfig.config.disablePMCTierGeneration)
|
||||
{
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
if ((botRole.includes("assault") || botRole.includes("marksman")) && ModConfig.config.disableScavTierGeneration)
|
||||
{
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
|
||||
if (botRole.includes("infected") || botRole.includes("spirit") || botRole.includes("skier") || botRole.includes("peacemaker") || botRole.includes("gifter"))
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: generateInventory`);
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
|
||||
return botInventory;
|
||||
}
|
||||
|
||||
// APBS generation chances instead
|
||||
const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel);
|
||||
wornItemChances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo);
|
||||
this.generateAndAddWeaponsToBot(templateInventory, wornItemChances, sessionId, botInventory, botRole, isPmc, itemGenerationLimitsMinMax, botLevel);
|
||||
const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo);
|
||||
const generation = chances.generation;
|
||||
|
||||
this.generateAndAddWeaponsToBot(templateInventory, chances, sessionId, botInventory, botRole, isPmc, generation, botLevel);
|
||||
this.botLootGenerator.generateLoot(sessionId, botJsonTemplate, isPmc, botRole, botInventory, botLevel);
|
||||
|
||||
return botInventory;
|
||||
@@ -178,48 +150,9 @@ export class APBSBotInventoryGenerator extends BotInventoryGenerator
|
||||
let modPool = this.apbsEquipmentGetter.getModsByBotRole(botRole, tierInfo);
|
||||
let apbsBot = true;
|
||||
|
||||
if ((ModConfig.config.disableBossTierGeneration && (botRole.includes("boss") || botRole.includes("sectant") || botRole.includes("arena"))) || botRole == "bosslegion" || botRole == "bosspunisher")
|
||||
{
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
modPool = settings.modPool;
|
||||
apbsBot = false;
|
||||
}
|
||||
if (ModConfig.config.disableBossFollowerTierGeneration && botRole.includes("follower"))
|
||||
{
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
modPool = settings.modPool;
|
||||
apbsBot = false;
|
||||
}
|
||||
if (ModConfig.config.disableRaiderRogueTierGeneration && (botRole.includes("exusec") || botRole.includes("pmcbot")))
|
||||
{
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
modPool = settings.modPool;
|
||||
apbsBot = false;
|
||||
}
|
||||
if (ModConfig.config.disablePMCTierGeneration && (botRole.includes("pmcusec") || botRole.includes("pmcbear")))
|
||||
{
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
modPool = settings.modPool;
|
||||
apbsBot = false;
|
||||
}
|
||||
if (ModConfig.config.disableScavTierGeneration && (botRole.includes("assault") || botRole.includes("marksman")))
|
||||
{
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
modPool = settings.modPool;
|
||||
apbsBot = false;
|
||||
}
|
||||
if (botRole.includes("infected") || botRole.includes("spirit") || botRole.includes("skier") || botRole.includes("peacemaker") || botRole.includes("gifter"))
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: generateEquipment`);
|
||||
equipmentPool = settings.rootEquipmentPool;
|
||||
randomisationDetails = settings.randomisationDetails;
|
||||
wornItemChances = settings.spawnChances;
|
||||
|
||||
+475
@@ -0,0 +1,475 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { IBotType, IGenerationWeightingItems } from "@spt/models/eft/common/tables/IBotType";
|
||||
|
||||
import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter";
|
||||
import { APBSTierGetter } from "../Utils/APBSTierGetter";
|
||||
import { RagfairPriceService } from "@spt/services/RagfairPriceService";
|
||||
import { PMCLootGenerator } from "@spt/generators/PMCLootGenerator";
|
||||
import { BotLootCacheService } from "@spt/services/BotLootCacheService";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { DatabaseServer } from "@spt/servers/DatabaseServer";
|
||||
import { LocalisationService } from "@spt/services/LocalisationService";
|
||||
import { ICloner } from "@spt/utils/cloners/ICloner";
|
||||
import { BaseClasses } from "@spt/models/enums/BaseClasses";
|
||||
import { IBotLootCache, LootCacheType } from "@spt/models/spt/bots/IBotLootCache";
|
||||
import { RaidInformation } from "../Globals/RaidInformation";
|
||||
import { APBSLogger } from "../Utils/APBSLogger";
|
||||
import { Logging } from "../Enums/Logging";
|
||||
|
||||
@injectable()
|
||||
export class APBSBotLootCacheService extends BotLootCacheService
|
||||
{
|
||||
protected apbsLootCache: Record<string, IBotLootCache>;
|
||||
|
||||
constructor(
|
||||
@inject("PrimaryLogger") protected logger: ILogger,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("DatabaseServer") protected databaseServer: DatabaseServer,
|
||||
@inject("PMCLootGenerator") protected pmcLootGenerator: PMCLootGenerator,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService,
|
||||
@inject("PrimaryCloner") protected cloner: ICloner,
|
||||
@inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter,
|
||||
@inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter,
|
||||
@inject("RaidInformation") protected raidInformation: RaidInformation,
|
||||
@inject("APBSLogger") protected apbsLogger: APBSLogger
|
||||
)
|
||||
{
|
||||
super(logger,
|
||||
itemHelper,
|
||||
databaseServer,
|
||||
pmcLootGenerator,
|
||||
localisationService,
|
||||
ragfairPriceService,
|
||||
cloner)
|
||||
this.apbsClearCache();
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
public apbsClearCache(): void
|
||||
{
|
||||
this.apbsLootCache = {};
|
||||
}
|
||||
|
||||
public apbsBotRoleExistsInCache(combinedBotRoleTier: string): boolean
|
||||
{
|
||||
return !!this.apbsLootCache[combinedBotRoleTier];
|
||||
}
|
||||
|
||||
public apbsInitCacheForBotRole(combinedBotRoleTier: string): void
|
||||
{
|
||||
this.apbsLootCache[combinedBotRoleTier] = {
|
||||
backpackLoot: {},
|
||||
pocketLoot: {},
|
||||
vestLoot: {},
|
||||
secureLoot: {},
|
||||
combinedPoolLoot: {},
|
||||
|
||||
specialItems: {},
|
||||
grenadeItems: {},
|
||||
drugItems: {},
|
||||
foodItems: {},
|
||||
drinkItems: {},
|
||||
currencyItems: {},
|
||||
healingItems: {},
|
||||
stimItems: {}
|
||||
};
|
||||
}
|
||||
|
||||
public apbsGetLootFromCache(
|
||||
botRole: string,
|
||||
isPmc: boolean,
|
||||
lootType: LootCacheType,
|
||||
botJsonTemplate: IBotType,
|
||||
botLevel: number
|
||||
): Record<string, number>
|
||||
{
|
||||
const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel).toString();
|
||||
const combinedBotRoleTier = botRole + tierInfo;
|
||||
if (!this.apbsBotRoleExistsInCache(combinedBotRoleTier))
|
||||
{
|
||||
this.apbsInitCacheForBotRole(combinedBotRoleTier);
|
||||
|
||||
this.apbsAddLootToCache(botRole, isPmc, botJsonTemplate, botLevel);
|
||||
}
|
||||
|
||||
let result = undefined;
|
||||
switch (lootType)
|
||||
{
|
||||
case LootCacheType.SPECIAL:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].specialItems;
|
||||
break;
|
||||
case LootCacheType.BACKPACK:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].backpackLoot;
|
||||
break;
|
||||
case LootCacheType.POCKET:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].pocketLoot;
|
||||
break;
|
||||
case LootCacheType.VEST:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].vestLoot;
|
||||
break;
|
||||
case LootCacheType.SECURE:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].secureLoot;
|
||||
break;
|
||||
case LootCacheType.COMBINED:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].combinedPoolLoot;
|
||||
break;
|
||||
case LootCacheType.HEALING_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].healingItems;
|
||||
break;
|
||||
case LootCacheType.GRENADE_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].grenadeItems;
|
||||
break;
|
||||
case LootCacheType.DRUG_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].drugItems;
|
||||
break;
|
||||
case LootCacheType.FOOD_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].foodItems;
|
||||
break;
|
||||
case LootCacheType.DRINK_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].drinkItems;
|
||||
break;
|
||||
case LootCacheType.CURRENCY_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].currencyItems;
|
||||
break;
|
||||
case LootCacheType.STIM_ITEMS:
|
||||
result = this.apbsLootCache[combinedBotRoleTier].stimItems;
|
||||
break;
|
||||
default:
|
||||
this.logger.error(
|
||||
this.localisationService.getText("bot-loot_type_not_found", {
|
||||
lootType: lootType,
|
||||
botRole: botRole,
|
||||
isPmc: isPmc
|
||||
})
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return this.cloner.clone(result);
|
||||
}
|
||||
|
||||
public apbsAddLootToCache(botRole: string, isPmc: boolean, botJsonTemplate: IBotType, botLevel: number): void
|
||||
{
|
||||
const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel);
|
||||
const combinedBotRoleTier = botRole + tierInfo;
|
||||
const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo);
|
||||
let realWhitelist: IGenerationWeightingItems = chances.generation.items;
|
||||
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: addLootToCache`);
|
||||
realWhitelist = botJsonTemplate.generation.items;
|
||||
}
|
||||
|
||||
// the full pool of loot we use to create the various sub-categories with
|
||||
const lootPool = botJsonTemplate.inventory.items;
|
||||
|
||||
// Flatten all individual slot loot pools into one big pool, while filtering out potentially missing templates
|
||||
const specialLootPool: Record<string, number> = {};
|
||||
const backpackLootPool: Record<string, number> = {};
|
||||
const pocketLootPool: Record<string, number> = {};
|
||||
const vestLootPool: Record<string, number> = {};
|
||||
const secureLootTPool: Record<string, number> = {};
|
||||
const combinedLootPool: Record<string, number> = {};
|
||||
|
||||
if (isPmc)
|
||||
{
|
||||
// Replace lootPool from bot json with our own generated list for PMCs
|
||||
lootPool.Backpack = this.cloner.clone(this.pmcLootGenerator.generatePMCBackpackLootPool(botRole));
|
||||
lootPool.Pockets = this.cloner.clone(this.pmcLootGenerator.generatePMCPocketLootPool(botRole));
|
||||
lootPool.TacticalVest = this.cloner.clone(this.pmcLootGenerator.generatePMCVestLootPool(botRole));
|
||||
}
|
||||
|
||||
// Backpack/Pockets etc
|
||||
for (const [slot, pool] of Object.entries(lootPool))
|
||||
{
|
||||
// No items to add, skip
|
||||
if (Object.keys(pool).length === 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Sort loot pool into separate buckets
|
||||
switch (slot.toLowerCase())
|
||||
{
|
||||
case "specialloot":
|
||||
this.addItemsToPool(specialLootPool, pool);
|
||||
break;
|
||||
case "pockets":
|
||||
this.addItemsToPool(pocketLootPool, pool);
|
||||
break;
|
||||
case "tacticalvest":
|
||||
this.addItemsToPool(vestLootPool, pool);
|
||||
break;
|
||||
case "securedcontainer":
|
||||
this.addItemsToPool(secureLootTPool, pool);
|
||||
break;
|
||||
case "backpack":
|
||||
this.addItemsToPool(backpackLootPool, pool);
|
||||
break;
|
||||
default:
|
||||
this.logger.warning(`How did you get here ${slot}`);
|
||||
}
|
||||
|
||||
// Add all items (if any) to combined pool (excluding secure)
|
||||
if (Object.keys(pool).length > 0 && slot.toLowerCase() !== "securedcontainer")
|
||||
{
|
||||
this.addItemsToPool(combinedLootPool, pool);
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted special items to bot if any exist
|
||||
const specialLootItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.specialItems.whitelist)?.length > 0
|
||||
? realWhitelist.specialItems.whitelist
|
||||
: {};
|
||||
|
||||
// no whitelist, find and assign from combined item pool
|
||||
if (Object.keys(specialLootItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(specialLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (!(this.isBulletOrGrenade(itemTemplate._props) || this.isMagazine(itemTemplate._props)))
|
||||
{
|
||||
specialLootItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted healing items to bot if any exist
|
||||
const healingItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.healing.whitelist)?.length > 0
|
||||
? realWhitelist.healing.whitelist
|
||||
: {};
|
||||
|
||||
// No whitelist, find and assign from combined item pool
|
||||
if (Object.keys(healingItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (
|
||||
this.isMedicalItem(itemTemplate._props) &&
|
||||
itemTemplate._parent !== BaseClasses.STIMULATOR &&
|
||||
itemTemplate._parent !== BaseClasses.DRUGS
|
||||
)
|
||||
{
|
||||
healingItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted drugs to bot if any exist
|
||||
const drugItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.drugs.whitelist)?.length > 0
|
||||
? realWhitelist.drugs.whitelist
|
||||
: {};
|
||||
|
||||
// no drugs whitelist, find and assign from combined item pool
|
||||
if (Object.keys(drugItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.DRUGS)
|
||||
{
|
||||
drugItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted food to bot if any exist
|
||||
const foodItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.food.whitelist)?.length > 0
|
||||
? realWhitelist.food.whitelist
|
||||
: {};
|
||||
|
||||
// No food whitelist, find and assign from combined item pool
|
||||
if (Object.keys(foodItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.FOOD))
|
||||
{
|
||||
foodItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted drink to bot if any exist
|
||||
const drinkItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.food.whitelist)?.length > 0
|
||||
? realWhitelist.food.whitelist
|
||||
: {};
|
||||
|
||||
// No drink whitelist, find and assign from combined item pool
|
||||
if (Object.keys(drinkItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.DRINK))
|
||||
{
|
||||
drinkItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted currency to bot if any exist
|
||||
const currencyItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.currency.whitelist)?.length > 0
|
||||
? realWhitelist.currency.whitelist
|
||||
: {};
|
||||
|
||||
// No currency whitelist, find and assign from combined item pool
|
||||
if (Object.keys(currencyItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.MONEY))
|
||||
{
|
||||
currencyItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted stims to bot if any exist
|
||||
const stimItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.stims.whitelist)?.length > 0
|
||||
? realWhitelist.stims.whitelist
|
||||
: {};
|
||||
|
||||
// No whitelist, find and assign from combined item pool
|
||||
if (Object.keys(stimItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.isMedicalItem(itemTemplate._props) && itemTemplate._parent === BaseClasses.STIMULATOR)
|
||||
{
|
||||
stimItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign whitelisted grenades to bot if any exist
|
||||
const grenadeItems: Record<string, number> =
|
||||
Object.keys(realWhitelist.grenades.whitelist)?.length > 0
|
||||
? realWhitelist.grenades.whitelist
|
||||
: {};
|
||||
|
||||
// no whitelist, find and assign from combined item pool
|
||||
if (Object.keys(grenadeItems).length === 0)
|
||||
{
|
||||
for (const [tpl, weight] of Object.entries(combinedLootPool))
|
||||
{
|
||||
const itemTemplate = this.itemHelper.getItem(tpl)[1];
|
||||
if (this.isGrenade(itemTemplate._props))
|
||||
{
|
||||
grenadeItems[tpl] = weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get backpack loot (excluding magazines, bullets, grenades, drink, food and healing/stim items)
|
||||
const filteredBackpackItems = {};
|
||||
for (const itemKey of Object.keys(backpackLootPool))
|
||||
{
|
||||
const itemResult = this.itemHelper.getItem(itemKey);
|
||||
if (!itemResult[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const itemTemplate = itemResult[1];
|
||||
if (
|
||||
this.isBulletOrGrenade(itemTemplate._props) ||
|
||||
this.isMagazine(itemTemplate._props) ||
|
||||
this.isMedicalItem(itemTemplate._props) ||
|
||||
this.isGrenade(itemTemplate._props) ||
|
||||
this.isFood(itemTemplate._id) ||
|
||||
this.isDrink(itemTemplate._id) ||
|
||||
this.isCurrency(itemTemplate._id)
|
||||
)
|
||||
{
|
||||
// Is type we dont want as backpack loot, skip
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredBackpackItems[itemKey] = backpackLootPool[itemKey];
|
||||
}
|
||||
|
||||
// Get pocket loot (excluding magazines, bullets, grenades, drink, food medical and healing/stim items)
|
||||
const filteredPocketItems = {};
|
||||
for (const itemKey of Object.keys(pocketLootPool))
|
||||
{
|
||||
const itemResult = this.itemHelper.getItem(itemKey);
|
||||
if (!itemResult[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const itemTemplate = itemResult[1];
|
||||
if (
|
||||
this.isBulletOrGrenade(itemTemplate._props) ||
|
||||
this.isMagazine(itemTemplate._props) ||
|
||||
this.isMedicalItem(itemTemplate._props) ||
|
||||
this.isGrenade(itemTemplate._props) ||
|
||||
this.isFood(itemTemplate._id) ||
|
||||
this.isDrink(itemTemplate._id) ||
|
||||
this.isCurrency(itemTemplate._id) ||
|
||||
!("Height" in itemTemplate._props) || // lacks height
|
||||
!("Width" in itemTemplate._props) // lacks width
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredPocketItems[itemKey] = pocketLootPool[itemKey];
|
||||
}
|
||||
|
||||
// Get vest loot (excluding magazines, bullets, grenades, medical and healing/stim items)
|
||||
const filteredVestItems = {};
|
||||
for (const itemKey of Object.keys(vestLootPool))
|
||||
{
|
||||
const itemResult = this.itemHelper.getItem(itemKey);
|
||||
if (!itemResult[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
const itemTemplate = itemResult[1];
|
||||
if (
|
||||
this.isBulletOrGrenade(itemTemplate._props) ||
|
||||
this.isMagazine(itemTemplate._props) ||
|
||||
this.isMedicalItem(itemTemplate._props) ||
|
||||
this.isGrenade(itemTemplate._props) ||
|
||||
this.isFood(itemTemplate._id) ||
|
||||
this.isDrink(itemTemplate._id) ||
|
||||
this.isCurrency(itemTemplate._id)
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
filteredVestItems[itemKey] = vestLootPool[itemKey];
|
||||
}
|
||||
|
||||
this.apbsLootCache[combinedBotRoleTier].healingItems = healingItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].drugItems = drugItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].foodItems = foodItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].drinkItems = drinkItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].currencyItems = currencyItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].stimItems = stimItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].grenadeItems = grenadeItems;
|
||||
|
||||
this.apbsLootCache[combinedBotRoleTier].specialItems = specialLootItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].backpackLoot = filteredBackpackItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].pocketLoot = filteredPocketItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].vestLoot = filteredVestItems;
|
||||
this.apbsLootCache[combinedBotRoleTier].secureLoot = secureLootTPool;
|
||||
}
|
||||
}
|
||||
+118
-31
@@ -23,6 +23,12 @@ import { BotLootGenerator } from "@spt/generators/BotLootGenerator";
|
||||
|
||||
import { APBSEquipmentGetter } from "../Utils/APBSEquipmentGetter";
|
||||
import { APBSTierGetter } from "../Utils/APBSTierGetter";
|
||||
import { APBSBotLootCacheService } from "./APBSBotLootCacheService";
|
||||
import { RaidInformation } from "../Globals/RaidInformation";
|
||||
import { APBSLogger } from "../Utils/APBSLogger";
|
||||
import { Logging } from "../Enums/Logging";
|
||||
import { ITemplateItem } from "@spt/models/eft/common/tables/ITemplateItem";
|
||||
import { IItemSpawnLimitSettings } from "@spt/models/spt/bots/IItemSpawnLimitSettings";
|
||||
|
||||
/** Handle profile related client events */
|
||||
@injectable()
|
||||
@@ -45,7 +51,10 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("PrimaryCloner") protected cloner: ICloner,
|
||||
@inject("APBSEquipmentGetter") protected apbsEquipmentGetter: APBSEquipmentGetter,
|
||||
@inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter
|
||||
@inject("APBSTierGetter") protected apbsTierGetter: APBSTierGetter,
|
||||
@inject("RaidInformation") protected raidInformation: RaidInformation,
|
||||
@inject("APBSBotLootCacheService") protected apbsBotLootCacheService: APBSBotLootCacheService,
|
||||
@inject("APBSLogger") protected apbsLogger: APBSLogger
|
||||
)
|
||||
{
|
||||
super(logger,
|
||||
@@ -73,11 +82,19 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
botInventory: PmcInventory,
|
||||
botLevel: number
|
||||
): void
|
||||
{// Limits on item types to be added as loot
|
||||
|
||||
{
|
||||
// Limits on item types to be added as loot
|
||||
const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel);
|
||||
const chances = this.apbsEquipmentGetter.getSpawnChancesByBotRole(botRole, tierInfo);
|
||||
const itemCounts: IGenerationWeightingItems = chances.generation.items;
|
||||
let itemCounts: IGenerationWeightingItems = chances.generation.items;
|
||||
let useOriginalLootCache = false;
|
||||
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: generateLoot`);
|
||||
itemCounts = botJsonTemplate.generation.items;
|
||||
useOriginalLootCache = true;
|
||||
}
|
||||
|
||||
if (
|
||||
!itemCounts.backpackLoot.weights
|
||||
@@ -101,22 +118,16 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
let backpackLootCount = Number(
|
||||
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.backpackLoot.weights)
|
||||
);
|
||||
let pocketLootCount = Number(
|
||||
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.pocketLoot.weights)
|
||||
);
|
||||
let pocketLootCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.pocketLoot.weights));
|
||||
let vestLootCount = this.weightedRandomHelper.getWeightedValue<number>(itemCounts.vestLoot.weights);
|
||||
const specialLootItemCount = Number(
|
||||
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.specialItems.weights)
|
||||
);
|
||||
const specialLootItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.specialItems.weights));
|
||||
const healingItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.healing.weights));
|
||||
const drugItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.drugs.weights));
|
||||
|
||||
const foodItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.food.weights));
|
||||
const drinkItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.drink.weights));
|
||||
|
||||
let currencyItemCount = Number(
|
||||
this.weightedRandomHelper.getWeightedValue<number>(itemCounts.currency.weights)
|
||||
);
|
||||
let currencyItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.currency.weights));
|
||||
|
||||
const stimItemCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.stims.weights));
|
||||
const grenadeCount = Number(this.weightedRandomHelper.getWeightedValue<number>(itemCounts.grenades.weights));
|
||||
@@ -146,7 +157,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Special items
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
specialLootItemCount,
|
||||
botInventory,
|
||||
@@ -159,12 +172,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Healing items / Meds
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.HEALING_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
healingItemCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -172,12 +187,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Drugs
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.DRUG_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
drugItemCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -185,12 +202,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Food
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
foodItemCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -198,12 +217,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Drink
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
drinkItemCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -211,12 +232,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Currency
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
currencyItemCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -224,7 +247,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Stims
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.STIM_ITEMS, botJsonTemplate, botLevel),
|
||||
containersBotHasAvailable,
|
||||
stimItemCount,
|
||||
botInventory,
|
||||
@@ -237,12 +262,14 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Grenades
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.GRENADE_ITEMS, botJsonTemplate, botLevel),
|
||||
[EquipmentSlots.POCKETS, EquipmentSlots.TACTICAL_VEST], // Can't use containersBotHasEquipped as we dont want grenades added to backpack
|
||||
grenadeCount,
|
||||
botInventory,
|
||||
botRole,
|
||||
undefined,
|
||||
botItemLimits,
|
||||
0,
|
||||
isPmc,
|
||||
containersIdFull
|
||||
@@ -269,7 +296,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
const backpackLootRoubleTotal = this.getBackpackRoubleTotalByLevel(botLevel, isPmc);
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.BACKPACK, botJsonTemplate, botLevel),
|
||||
[EquipmentSlots.BACKPACK],
|
||||
backpackLootCount,
|
||||
botInventory,
|
||||
@@ -286,7 +315,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
{
|
||||
// Vest
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.VEST, botJsonTemplate, botLevel),
|
||||
[EquipmentSlots.TACTICAL_VEST],
|
||||
vestLootCount,
|
||||
botInventory,
|
||||
@@ -300,7 +331,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
|
||||
// Pockets
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.POCKET, botJsonTemplate, botLevel),
|
||||
[EquipmentSlots.POCKETS],
|
||||
pocketLootCount,
|
||||
botInventory,
|
||||
@@ -317,7 +350,9 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig))
|
||||
{
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate),
|
||||
useOriginalLootCache ?
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate) :
|
||||
this.apbsBotLootCacheService.apbsGetLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate, botLevel),
|
||||
[EquipmentSlots.SECURED_CONTAINER],
|
||||
50,
|
||||
botInventory,
|
||||
@@ -328,5 +363,57 @@ export class APBSBotLootGenerator extends BotLootGenerator
|
||||
containersIdFull
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
protected override itemHasReachedSpawnLimit(
|
||||
itemTemplate: ITemplateItem,
|
||||
botRole: string,
|
||||
itemSpawnLimits: IItemSpawnLimitSettings
|
||||
): boolean
|
||||
{
|
||||
// PMCs and scavs have different sections of bot config for spawn limits
|
||||
if (!!itemSpawnLimits && Object.keys(itemSpawnLimits.globalLimits).length === 0)
|
||||
{
|
||||
// No items found in spawn limit, drop out
|
||||
return false;
|
||||
}
|
||||
|
||||
// No spawn limits, skipping
|
||||
if (!itemSpawnLimits)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const idToCheckFor = this.getMatchingIdFromSpawnLimits(itemTemplate, itemSpawnLimits.globalLimits);
|
||||
if (!idToCheckFor)
|
||||
{
|
||||
// ParentId or tplid not found in spawnLimits, not a spawn limited item, skip
|
||||
return false;
|
||||
}
|
||||
|
||||
// Increment item count with this bot type
|
||||
itemSpawnLimits.currentLimits[idToCheckFor]++;
|
||||
|
||||
// Check if over limit
|
||||
if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor])
|
||||
{
|
||||
// Prevent edge-case of small loot pools + code trying to add limited item over and over infinitely
|
||||
if (itemSpawnLimits.currentLimits[idToCheckFor] > itemSpawnLimits.globalLimits[idToCheckFor] * 10)
|
||||
{
|
||||
this.logger.debug(
|
||||
this.localisationService.getText("bot-item_spawn_limit_reached_skipping_item", {
|
||||
botRole: botRole,
|
||||
itemName: itemTemplate._name,
|
||||
attempts: itemSpawnLimits.currentLimits[idToCheckFor]
|
||||
})
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+3
-27
@@ -85,37 +85,13 @@ export class APBSBotWeaponGenerator extends BotWeaponGenerator
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
|
||||
// Config disable checks to flip to default weapon gen
|
||||
if ((ModConfig.config.disableBossTierGeneration && (botRole.includes("boss") || botRole.includes("sectant") || botRole.includes("arena"))) || botRole == "bosslegion" || botRole == "bosspunisher")
|
||||
// Check if bot disabled, if it is - use SPT code
|
||||
if (!this.raidInformation.isBotEnabled(botRole))
|
||||
{
|
||||
this.apbsLogger.log(Logging.DEBUG, `${botRole} is disabled - TRACE: generateRandomWeapon`);
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
if (ModConfig.config.disableBossFollowerTierGeneration && botRole.includes("follower"))
|
||||
{
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
if (ModConfig.config.disableRaiderRogueTierGeneration && (botRole.includes("exusec") || botRole.includes("pmcbot")))
|
||||
{
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
if (ModConfig.config.disablePMCTierGeneration && (botRole.includes("pmcusec") || botRole.includes("pmcbear")))
|
||||
{
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
if (ModConfig.config.disableScavTierGeneration && (botRole.includes("assault") || botRole.includes("marksman")))
|
||||
{
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
if (botRole.includes("infected") || botRole.includes("spirit") || botRole.includes("skier") || botRole.includes("peacemaker") || botRole.includes("gifter"))
|
||||
{
|
||||
const weaponTpl = this.pickWeightedWeaponTplFromPool(equipmentSlot, botTemplateInventory);
|
||||
return this.generateWeaponByTpl(sessionId, weaponTpl, equipmentSlot, botTemplateInventory, weaponParentId, modChances, botRole, isPmc, botLevel);
|
||||
}
|
||||
|
||||
// If not disabled via config, all bots follow this custom generation
|
||||
const tierInfo = this.apbsTierGetter.getTierByLevel(botLevel);
|
||||
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotGenerator } from "@spt/generators/BotGenerator";
|
||||
import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper";
|
||||
import { BotHelper } from "@spt/helpers/BotHelper";
|
||||
import { ItemHelper } from "@spt/helpers/ItemHelper";
|
||||
import { ProfileHelper } from "@spt/helpers/ProfileHelper";
|
||||
import { IPmcData } from "@spt/models/eft/common/IPmcData";
|
||||
import { IBotInfoSettings } from "@spt/models/eft/common/tables/IBotBase";
|
||||
import { IBotType } from "@spt/models/eft/common/tables/IBotType";
|
||||
import { MemberCategory } from "@spt/models/enums/MemberCategory";
|
||||
import { ILogger } from "@spt/models/spt/utils/ILogger";
|
||||
import { ConfigServer } from "@spt/servers/ConfigServer";
|
||||
import { SaveServer } from "@spt/servers/SaveServer";
|
||||
import { BotLootCacheService } from "@spt/services/BotLootCacheService";
|
||||
import { DatabaseService } from "@spt/services/DatabaseService";
|
||||
import { FenceService } from "@spt/services/FenceService";
|
||||
import { LocalisationService } from "@spt/services/LocalisationService";
|
||||
import { HashUtil } from "@spt/utils/HashUtil";
|
||||
import { RandomUtil } from "@spt/utils/RandomUtil";
|
||||
import { ICloner } from "@spt/utils/cloners/ICloner";
|
||||
import { PlayerScavGenerator } from "@spt/generators/PlayerScavGenerator";
|
||||
import { APBSBotLootCacheService } from "./APBSBotLootCacheService";
|
||||
|
||||
@injectable()
|
||||
export class APBSPlayerScavGenerator extends PlayerScavGenerator
|
||||
{
|
||||
constructor(
|
||||
@inject("PrimaryLogger") protected logger: ILogger,
|
||||
@inject("RandomUtil") protected randomUtil: RandomUtil,
|
||||
@inject("DatabaseService") protected databaseService: DatabaseService,
|
||||
@inject("HashUtil") protected hashUtil: HashUtil,
|
||||
@inject("ItemHelper") protected itemHelper: ItemHelper,
|
||||
@inject("BotGeneratorHelper") protected botGeneratorHelper: BotGeneratorHelper,
|
||||
@inject("SaveServer") protected saveServer: SaveServer,
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("BotHelper") protected botHelper: BotHelper,
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@inject("BotLootCacheService") protected botLootCacheService: BotLootCacheService,
|
||||
@inject("LocalisationService") protected localisationService: LocalisationService,
|
||||
@inject("BotGenerator") protected botGenerator: BotGenerator,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
@inject("PrimaryCloner") protected cloner: ICloner,
|
||||
@inject("APBSBotLootCacheService") protected apbsBotLootCacheService: APBSBotLootCacheService
|
||||
)
|
||||
{
|
||||
super(logger,
|
||||
randomUtil,
|
||||
databaseService,
|
||||
hashUtil,
|
||||
itemHelper,
|
||||
botGeneratorHelper,
|
||||
saveServer,
|
||||
profileHelper,
|
||||
botHelper,
|
||||
fenceService,
|
||||
botLootCacheService,
|
||||
localisationService,
|
||||
botGenerator,
|
||||
configServer,
|
||||
cloner)
|
||||
}
|
||||
|
||||
public generate(sessionID: string): IPmcData
|
||||
{
|
||||
// get karma level from profile
|
||||
const profile = this.saveServer.getProfile(sessionID);
|
||||
const profileCharactersClone = this.cloner.clone(profile.characters);
|
||||
const pmcDataClone = profileCharactersClone.pmc;
|
||||
const existingScavDataClone = profileCharactersClone.scav;
|
||||
|
||||
const scavKarmaLevel = this.getScavKarmaLevel(pmcDataClone);
|
||||
|
||||
// use karma level to get correct karmaSettings
|
||||
const playerScavKarmaSettings = this.playerScavConfig.karmaLevel[scavKarmaLevel];
|
||||
if (!playerScavKarmaSettings)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("scav-missing_karma_settings", scavKarmaLevel));
|
||||
}
|
||||
|
||||
this.logger.debug(`generated player scav loadout with karma level ${scavKarmaLevel}`);
|
||||
|
||||
// Edit baseBotNode values
|
||||
const baseBotNode: IBotType = this.constructBotBaseTemplate(playerScavKarmaSettings.botTypeForLoot);
|
||||
this.adjustBotTemplateWithKarmaSpecificSettings(playerScavKarmaSettings, baseBotNode);
|
||||
|
||||
let scavData = this.botGenerator.generatePlayerScav(
|
||||
sessionID,
|
||||
playerScavKarmaSettings.botTypeForLoot.toLowerCase(),
|
||||
"easy",
|
||||
baseBotNode,
|
||||
pmcDataClone
|
||||
);
|
||||
|
||||
// Remove cached bot data after scav was generated
|
||||
this.botLootCacheService.clearCache();
|
||||
this.apbsBotLootCacheService.apbsClearCache();
|
||||
|
||||
// Add scav metadata
|
||||
scavData.savage = undefined;
|
||||
scavData.aid = pmcDataClone.aid;
|
||||
scavData.TradersInfo = pmcDataClone.TradersInfo;
|
||||
scavData.Info.Settings = {} as IBotInfoSettings;
|
||||
scavData.Info.Bans = [];
|
||||
scavData.Info.RegistrationDate = pmcDataClone.Info.RegistrationDate;
|
||||
scavData.Info.GameVersion = pmcDataClone.Info.GameVersion;
|
||||
scavData.Info.MemberCategory = MemberCategory.UNIQUE_ID;
|
||||
scavData.Info.lockedMoveCommands = true;
|
||||
scavData.RagfairInfo = pmcDataClone.RagfairInfo;
|
||||
scavData.UnlockedInfo = pmcDataClone.UnlockedInfo;
|
||||
|
||||
// Persist previous scav data into new scav
|
||||
scavData._id = existingScavDataClone._id ?? pmcDataClone.savage;
|
||||
scavData.sessionId = existingScavDataClone.sessionId ?? pmcDataClone.sessionId;
|
||||
scavData.Skills = this.getScavSkills(existingScavDataClone);
|
||||
scavData.Stats = this.getScavStats(existingScavDataClone);
|
||||
scavData.Info.Level = this.getScavLevel(existingScavDataClone);
|
||||
scavData.Info.Experience = this.getScavExperience(existingScavDataClone);
|
||||
scavData.Quests = existingScavDataClone.Quests ?? [];
|
||||
scavData.TaskConditionCounters = existingScavDataClone.TaskConditionCounters ?? {};
|
||||
scavData.Notes = existingScavDataClone.Notes ?? { Notes: [] };
|
||||
scavData.WishList = existingScavDataClone.WishList ?? {};
|
||||
scavData.Encyclopedia = pmcDataClone.Encyclopedia ?? {};
|
||||
|
||||
// Add additional items to player scav as loot
|
||||
this.addAdditionalLootToPlayerScavContainers(playerScavKarmaSettings.lootItemsToAddChancePercent, scavData, [
|
||||
"TacticalVest",
|
||||
"Pockets",
|
||||
"Backpack"
|
||||
]);
|
||||
|
||||
// Remove secure container
|
||||
scavData = this.profileHelper.removeSecureContainer(scavData);
|
||||
|
||||
// Set cooldown timer
|
||||
scavData = this.setScavCooldownTimer(scavData, pmcDataClone);
|
||||
|
||||
// Add scav to the profile
|
||||
this.saveServer.getProfile(sessionID).characters.scav = scavData;
|
||||
|
||||
return scavData;
|
||||
}
|
||||
}
|
||||
+1
-14
@@ -38,20 +38,7 @@ export class APBSBotLevelGenerator
|
||||
container.afterResolution("BotLevelGenerator", (_t, result: BotLevelGenerator) =>
|
||||
{
|
||||
result.generateBotLevel = (levelDetails: MinMax, botGenerationDetails: IBotGenerationDetails, bot: APBSIBotBase): IRandomisedBotLevelResult =>
|
||||
{
|
||||
|
||||
/*
|
||||
TESTING TIER DEVIATION - Since botGenerationDetails isn't passed to the relevant methods, this is more difficult that anticipated. This logic works for the tier, but since selection is based on level..oof.
|
||||
-2 to +1 tier
|
||||
|
||||
const lowerDeviation = (Math.floor(Math.random() * 2) - 2);
|
||||
const upperDeviation = (Math.floor(Math.random() * 2));
|
||||
const minTier = (tier + lowerDeviation) <= 0 ? 1 : tier + lowerDeviation
|
||||
const maxTier = (tier + upperDeviation) >= 7 ? 7 : tier + upperDeviation
|
||||
const newTier = this.randomUtil.getInt(minTier, maxTier)
|
||||
console.log(`Original Tier: ${tier} - New Tier ${newTier}`)
|
||||
*/
|
||||
|
||||
{
|
||||
if (this.modInformation.testMode && this.modInformation.testBotRole.includes(botGenerationDetails.role.toLowerCase()))
|
||||
{
|
||||
const level = this.profileHelper.getPmcProfile(this.raidInformation.sessionId)?.Info?.Level;
|
||||
|
||||
+86
-1
@@ -1,4 +1,5 @@
|
||||
import { injectable, inject } from "tsyringe";
|
||||
import { injectable } from "tsyringe";
|
||||
import { ModConfig } from "./ModConfig";
|
||||
|
||||
@injectable()
|
||||
export class RaidInformation
|
||||
@@ -81,4 +82,88 @@ export class RaidInformation
|
||||
"ShortRange": 80
|
||||
}
|
||||
}
|
||||
|
||||
public alwaysDisabledBots = [
|
||||
"shooterbtr",
|
||||
"skier",
|
||||
"peacemaker",
|
||||
"gifter",
|
||||
"infectedassault",
|
||||
"infectedcivil",
|
||||
"infectedlaborant",
|
||||
"infectedpmc",
|
||||
"infectedtagilla",
|
||||
"bosslegion",
|
||||
"bosspunisher"
|
||||
]
|
||||
public isBotEnabled(botType: string): boolean
|
||||
{
|
||||
botType = botType.toLowerCase();
|
||||
switch (botType)
|
||||
{
|
||||
case "pmcbear":
|
||||
case "pmcusec":
|
||||
if (ModConfig.config.disablePMCTierGeneration) return false;
|
||||
return true;
|
||||
case "cursedassault":
|
||||
case "marksman":
|
||||
case "assault":
|
||||
if (ModConfig.config.disableScavTierGeneration) return false;
|
||||
return true;
|
||||
case "arenafighterevent":
|
||||
case "exusec":
|
||||
if (ModConfig.config.disableRaiderRogueTierGeneration) return false;
|
||||
return true;
|
||||
case "bossbully":
|
||||
case "bosstagilla":
|
||||
case "bosspartisan":
|
||||
case "bossgluhar":
|
||||
case "bosskilla":
|
||||
case "bosskojaniy":
|
||||
case "bosssanitar":
|
||||
case "bossknight":
|
||||
case "bosszryachiy":
|
||||
case "bosstest":
|
||||
case "bosskolontay":
|
||||
case "bossboar":
|
||||
case "bossboarSniper":
|
||||
case "sectantpriest":
|
||||
if (ModConfig.config.disableBossTierGeneration) return false;
|
||||
return true;
|
||||
case "sectantwarrior":
|
||||
case "followerboarblose1":
|
||||
case "followerboarclose2":
|
||||
case "followerkolontayassault":
|
||||
case "followerkolontaysecurity":
|
||||
case "followerbully":
|
||||
case "followergluharassault":
|
||||
case "followergluharscout":
|
||||
case "followergluharsecurity":
|
||||
case "followergluharsnipe":
|
||||
case "followerkojaniy":
|
||||
case "followersanitar":
|
||||
case "followertagilla":
|
||||
case "followerbirdeye":
|
||||
case "followerbigpipe":
|
||||
case "followerzryachiy":
|
||||
case "followertest":
|
||||
case "followerboar":
|
||||
if (ModConfig.config.disableBossFollowerTierGeneration) return false;
|
||||
return true;
|
||||
case "shooterbtr":
|
||||
case "skier":
|
||||
case "peacemaker":
|
||||
case "gifter":
|
||||
case "infectedassault":
|
||||
case "infectedcivil":
|
||||
case "infectedlaborant":
|
||||
case "infectedpmc":
|
||||
case "infectedtagilla":
|
||||
case "bosslegion":
|
||||
case "bosspunisher":
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
-339
@@ -370,343 +370,4 @@ export class TierInformation
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
public lootRandomization = [
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 1,
|
||||
"max": 15
|
||||
},
|
||||
"generation": {
|
||||
"drugs": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"grenades": {
|
||||
"weights": {
|
||||
"0": 45,
|
||||
"1": 35,
|
||||
"2": 1
|
||||
},
|
||||
"whitelist": {
|
||||
"5710c24ad2720bc3458b45a3": 25,
|
||||
"58d3db5386f77426186285a0": 25,
|
||||
"5448be9a4bdc2dfd2f8b456a": 25
|
||||
}
|
||||
},
|
||||
"healing": {
|
||||
"weights": {
|
||||
"0": 10,
|
||||
"1": 85,
|
||||
"2": 20
|
||||
},
|
||||
"whitelist": {
|
||||
"5755356824597772cb798962": 4,
|
||||
"590c661e86f7741e566b646a": 9,
|
||||
"544fb45d4bdc2dee738b4568": 2,
|
||||
"5e831507ea0a7c419c2f9bd9": 6
|
||||
}
|
||||
},
|
||||
"backpackLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"pocketLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"vestLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"magazines": {
|
||||
"weights": {
|
||||
"0": 0,
|
||||
"1": 10,
|
||||
"2": 55,
|
||||
"3": 25
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"stims": {
|
||||
"weights": {
|
||||
"0": 100,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {
|
||||
"544fb3f34bdc2d03748b456a": 25,
|
||||
"5c0e530286f7747fa1419862": 65
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 16,
|
||||
"max": 30
|
||||
},
|
||||
"generation": {
|
||||
"drugs": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"grenades": {
|
||||
"weights": {
|
||||
"0": 15,
|
||||
"1": 35,
|
||||
"2": 5,
|
||||
"3": 0
|
||||
},
|
||||
"whitelist": {
|
||||
"5710c24ad2720bc3458b45a3": 25,
|
||||
"58d3db5386f77426186285a0": 25,
|
||||
"5448be9a4bdc2dfd2f8b456a": 25,
|
||||
"5e32f56fcb6d5863cc5e5ee4": 5,
|
||||
"5e340dcdcb6d5863cc5e5efb": 1
|
||||
|
||||
}
|
||||
},
|
||||
"healing": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 25,
|
||||
"2": 65,
|
||||
"3": 10
|
||||
},
|
||||
"whitelist": {
|
||||
"60098ad7c2240c0fe85c570a": 15,
|
||||
"590c678286f77426c9660122": 10,
|
||||
"5e8488fa988a8701445df1e4": 12
|
||||
}
|
||||
},
|
||||
"backpackLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"pocketLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"vestLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"magazines": {
|
||||
"weights": {
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 55,
|
||||
"3": 25
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"stims": {
|
||||
"weights": {
|
||||
"0": 75,
|
||||
"1": 20,
|
||||
"2": 5
|
||||
},
|
||||
"whitelist": {
|
||||
"544fb3f34bdc2d03748b456a": 1,
|
||||
"5c0e530286f7747fa1419862": 65,
|
||||
"5c0e534186f7747fa1419867": 12,
|
||||
"5c0e531d86f7747fa23f4d42": 8,
|
||||
"5ed51652f6c34d2cc26336a1": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 31,
|
||||
"max": 45
|
||||
},
|
||||
"generation": {
|
||||
"drugs": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"grenades": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 15,
|
||||
"2": 25,
|
||||
"3": 10
|
||||
},
|
||||
"whitelist": {
|
||||
"5710c24ad2720bc3458b45a3": 15,
|
||||
"58d3db5386f77426186285a0": 15,
|
||||
"5448be9a4bdc2dfd2f8b456a": 15,
|
||||
"5e32f56fcb6d5863cc5e5ee4": 45,
|
||||
"5e340dcdcb6d5863cc5e5efb": 20,
|
||||
"617fd91e5539a84ec44ce155": 5,
|
||||
"618a431df1eb8e24b8741deb": 5
|
||||
}
|
||||
},
|
||||
"healing": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 15,
|
||||
"2": 65,
|
||||
"3": 30,
|
||||
"4": 5
|
||||
},
|
||||
"whitelist": {
|
||||
"60098ad7c2240c0fe85c570a": 45,
|
||||
"590c678286f77426c9660122": 20,
|
||||
"5e8488fa988a8701445df1e4": 45
|
||||
}
|
||||
},
|
||||
"backpackLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"pocketLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"vestLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"magazines": {
|
||||
"weights": {
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 55,
|
||||
"3": 25
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"stims": {
|
||||
"weights": {
|
||||
"0": 50,
|
||||
"1": 20,
|
||||
"2": 5
|
||||
},
|
||||
"whitelist": {
|
||||
"544fb3f34bdc2d03748b456a": 1,
|
||||
"5c0e530286f7747fa1419862": 65,
|
||||
"5c0e534186f7747fa1419867": 12,
|
||||
"5c0e531d86f7747fa23f4d42": 8,
|
||||
"5ed51652f6c34d2cc26336a1": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"levelRange": {
|
||||
"min": 46,
|
||||
"max": 100
|
||||
},
|
||||
"generation": {
|
||||
"drugs": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"grenades": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 15,
|
||||
"2": 20,
|
||||
"3": 15
|
||||
},
|
||||
"whitelist": {
|
||||
"5710c24ad2720bc3458b45a3": 1,
|
||||
"58d3db5386f77426186285a0": 1,
|
||||
"5448be9a4bdc2dfd2f8b456a": 1,
|
||||
"5e32f56fcb6d5863cc5e5ee4": 35,
|
||||
"5e340dcdcb6d5863cc5e5efb": 35,
|
||||
"617fd91e5539a84ec44ce155": 10,
|
||||
"618a431df1eb8e24b8741deb": 10
|
||||
|
||||
}
|
||||
},
|
||||
"healing": {
|
||||
"weights": {
|
||||
"0": 1,
|
||||
"1": 15,
|
||||
"2": 35,
|
||||
"3": 75,
|
||||
"4": 20
|
||||
},
|
||||
"whitelist": {
|
||||
"60098ad7c2240c0fe85c570a": 45,
|
||||
"590c678286f77426c9660122": 20,
|
||||
"5e8488fa988a8701445df1e4": 45
|
||||
}
|
||||
},
|
||||
"backpackLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"pocketLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"vestLoot": {
|
||||
"weights": {
|
||||
"0": 1
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"magazines": {
|
||||
"weights": {
|
||||
"0": 0,
|
||||
"1": 1,
|
||||
"2": 25,
|
||||
"3": 55
|
||||
},
|
||||
"whitelist": {}
|
||||
},
|
||||
"stims": {
|
||||
"weights": {
|
||||
"0": 50,
|
||||
"1": 20,
|
||||
"2": 5
|
||||
},
|
||||
"whitelist": {
|
||||
"544fb3f34bdc2d03748b456a": 1,
|
||||
"5c0e530286f7747fa1419862": 65,
|
||||
"5c0e534186f7747fa1419867": 12,
|
||||
"5c0e531d86f7747fa23f4d42": 8,
|
||||
"5ed51652f6c34d2cc26336a1": 17
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
+7
-1
@@ -27,6 +27,7 @@ import { BotGeneratorHelper } from "@spt/helpers/BotGeneratorHelper";
|
||||
import { BotWeaponGeneratorHelper } from "@spt/helpers/BotWeaponGeneratorHelper";
|
||||
import { BotWeaponModLimitService } from "@spt/services/BotWeaponModLimitService";
|
||||
import { RepairService } from "@spt/services/RepairService";
|
||||
import { SeasonalEventService } from "@spt/services/SeasonalEventService";
|
||||
import { VFS } from "@spt/utils/VFS";
|
||||
|
||||
// Custom
|
||||
@@ -52,7 +53,8 @@ import { BlacklistHelper } from "./Helpers/BlacklistHelper";
|
||||
import { RealismHelper } from "./Helpers/RealismHelper";
|
||||
import { APBSTester } from "./Utils/APBSTester";
|
||||
import { APBSAttachmentChecker } from "./Utils/APBSAttachmentChecker";
|
||||
import { SeasonalEventService } from "@spt/services/SeasonalEventService";
|
||||
import { APBSBotLootCacheService } from "./ClassExtensions/APBSBotLootCacheService";
|
||||
import { APBSPlayerScavGenerator } from "./ClassExtensions/APBSPlayerScavGenerator";
|
||||
|
||||
export class InstanceManager
|
||||
{
|
||||
@@ -182,6 +184,10 @@ export class InstanceManager
|
||||
this.container.register("BotInventoryGenerator", { useToken: "APBSBotInventoryGenerator" });
|
||||
this.container.register<APBSBotEquipmentModGenerator>("APBSBotEquipmentModGenerator", APBSBotEquipmentModGenerator);
|
||||
this.container.register("BotEquipmentModGenerator", { useToken: "APBSBotEquipmentModGenerator" });
|
||||
this.container.register<APBSPlayerScavGenerator>("APBSPlayerScavGenerator", APBSPlayerScavGenerator);
|
||||
this.container.register("PlayerScavGenerator", { useToken: "APBSPlayerScavGenerator" });
|
||||
this.container.register<APBSBotLootCacheService>("APBSBotLootCacheService", APBSBotLootCacheService);
|
||||
this.container.register("BotLootCacheService", { useToken: "APBSBotLootCacheService" });
|
||||
this.container.register<APBSBotLootGenerator>("APBSBotLootGenerator", APBSBotLootGenerator);
|
||||
this.container.register("BotLootGenerator", { useToken: "APBSBotLootGenerator" });
|
||||
this.container.register<APBSBotWeaponGenerator>("APBSBotWeaponGenerator", APBSBotWeaponGenerator);
|
||||
|
||||
+21
@@ -178,6 +178,27 @@ export class APBSEquipmentGetter
|
||||
const tierJson = this.getTierModsJson(tierInfo)
|
||||
switch (botRole)
|
||||
{
|
||||
case "bossboar":
|
||||
case "bossboarsniper":
|
||||
case "bossbully":
|
||||
case "bossgluhar":
|
||||
case "bosskilla":
|
||||
case "bosskojaniy":
|
||||
case "bosskolontay":
|
||||
case "bosssanitar":
|
||||
case "bosstagilla":
|
||||
case "bosspartisan":
|
||||
case "bossknight":
|
||||
case "followerbigpipe":
|
||||
case "followerbirdeye":
|
||||
case "sectantpriest":
|
||||
case "sectantwarrior":
|
||||
case "exusec":
|
||||
case "arenafighterevent":
|
||||
case "arenafighter":
|
||||
case "pmcbot":
|
||||
if (tierInfo < 4) return this.tierInformation.tier4mods;
|
||||
else return tierJson;
|
||||
case "marksman":
|
||||
case "cursedassault":
|
||||
case "assault":
|
||||
|
||||
+801
-868
File diff suppressed because it is too large
Load Diff
+854
-870
File diff suppressed because it is too large
Load Diff
+1
@@ -558,6 +558,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
|
||||
+864
-872
File diff suppressed because it is too large
Load Diff
+1
@@ -614,6 +614,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
|
||||
+872
-894
File diff suppressed because it is too large
Load Diff
+866
-912
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -866,6 +866,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -877,7 +878,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+851
-911
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -798,6 +798,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -809,7 +810,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+852
-912
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -784,6 +784,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -795,7 +796,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
+851
-911
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -764,6 +764,7 @@
|
||||
"56e335e4d2720b6c058b456d": 20,
|
||||
"5ca20d5986f774331e7c9602": 10,
|
||||
"5e9dcf5986f7746c417435b3": 10,
|
||||
"59e763f286f7742ee57895da": 15,
|
||||
"6038d614d10cbf667352dd44": 1,
|
||||
"6034d103ca006d2dca39b3f0": 1,
|
||||
"656ddcf0f02d7bcea90bf395": 1,
|
||||
@@ -775,7 +776,6 @@
|
||||
"5c0e805e86f774683f3dd637": 1,
|
||||
"5ab8ebf186f7742d8b372e80": 1,
|
||||
"639346cc1c8f182ad90c8972": 1,
|
||||
"59e763f286f7742ee57895da": 1,
|
||||
"5b44c6ae86f7742d1627baea": 1,
|
||||
"5d5d940f86f7742797262046": 1,
|
||||
"5df8a4d786f77412672a1e3b": 1,
|
||||
|
||||
Reference in New Issue
Block a user