diff --git a/Valens-AIO/Valens-AIO ReadMe.pdf b/Valens-AIO/Valens-AIO ReadMe.pdf index 34f22e7..d1577fc 100644 Binary files a/Valens-AIO/Valens-AIO ReadMe.pdf and b/Valens-AIO/Valens-AIO ReadMe.pdf differ diff --git a/Valens-AIO/config/config.json b/Valens-AIO/config/config.json index 5bfc37d..df3cbee 100644 --- a/Valens-AIO/config/config.json +++ b/Valens-AIO/config/config.json @@ -5,11 +5,11 @@ { "ammoStacks": { - "grenadeCartridges": 2, - "marksmanCartridges": 2, - "pistolCartridges": 2, - "rifleCartridges": 2, - "shotgunCartridges": 2 + "grenadeCartridges": 1, + "marksmanCartridges": 40, + "pistolCartridges": 50, + "rifleCartridges": 60, + "shotgunCartridges": 20 } }, @@ -17,22 +17,34 @@ { "bossChance": { - "activated": true, - "chance": 2 + "activated": false, + "chance": 100 }, - "maxBotCap": 2, + "maxBotCap": 20, "pmc": { - "chanceSameSideIsHostilePercent": 2, + "chanceSameSideIsHostilePercent": 50, "containersOnPMCs": true, - "isUsec": 2, - "lootNValue": 2, - "maxBackpackLootTotalRub": 2, - "maxPocketLootTotalRub": 2, - "maxVestLootTotalRub": 2, - "pmcDifficulty": "Easy", + "isUsec": 50, + "lootNValue": 3, + "maxBackpackLootTotalRub": 150000, + "maxPocketLootTotalRub": 50000, + "maxVestLootTotalRub": 50000, + + "difficultyWeights": + { + "difficulty": "asonline", + "useWeights": false, + "weights": + { + "easy": 3, + "normal": 5, + "hard": 2, + "impossible": 1 + } + }, "convertIntoPmcChance": { @@ -43,36 +55,36 @@ "assault for 3.2.0": { - "min": 18, - "max": 45 + "min": 15, + "max": 40 }, "cursedassault for 3.2.0": { - "min": 18, - "max": 45 + "min": 15, + "max": 40 }, "pmcbot for 3.2.0": { - "min": 18, - "max": 35 + "min": 15, + "max": 30 }, "exusec for 3.2.0": { "min": 5, - "max": 25 + "max": 20 } } }, "scav": { - "lootNValue": 2 + "lootNValue": 4 } }, "flea": { - "minUserLevel": 2, + "minUserLevel": 15, "blacklist": { @@ -82,35 +94,35 @@ "condition": { - "conditionChance": 0.4, - "min": 0.8, - "max": 0.9 + "conditionChance": 0.2, + "min": 0.6, + "max": 1.0 }, "currencies": { - "roubles": 79, - "dollars": 21, - "euros": 1 + "roubles": 78, + "dollars": 20, + "euros": 2 }, "offerItemCount": { - "min": 9, - "max": 16 + "min": 8, + "max": 15 }, "reputation": { - "gain": 0.000002, - "loss": 0.000002 + "gain": 0.0000002, + "loss": 0.0000002 }, "time": { - "baseSellTime": 1, - "minSellTime": 1, - "maxSellTime": 1 + "baseSellTime": 15, + "minSellTime": 5, + "maxSellTime": 15 } }, @@ -119,47 +131,47 @@ "damagePerMeter": 3, "safeHeight": 9, - "maxLoyaltyTraders": true, - "timeBeforeDeployLocal": 1, + "maxLoyaltyTraders": false, + "timeBeforeDeployLocal": 10, "match_end": { - "survived_exp_requirement": 1, - "survived_seconds_requirement": 1, - "survived_exp_reward": 1, - "mia_exp_reward": 1, - "runner_exp_reward": 1, - "leftMult": 2, - "miaMult": 12, - "survivedMult": 2, - "runnerMult": 2, - "killedMult": 2, - "headShotMult": 12, - "expOnDamageAllHealth": 52 + "survived_exp_requirement": 200, + "survived_seconds_requirement": 420, + "survived_exp_reward": 300, + "mia_exp_reward": 200, + "runner_exp_reward": 200, + "leftMult": 0, + "miaMult": 1, + "survivedMult": 1.3, + "runnerMult": 0.5, + "killedMult": 1, + "headShotMult": 1.2, + "expOnDamageAllHealth": 50 } }, "hideout": { - "airFilterUnitFlowRate": 0.004722222222222, - "constructionTime": 2, - "generatorFuelFlowRate": 0.001319444444444, - "gpuBoostRate": 0.04125, - "productionTime": 2, - "scavCaseTime": 2 + "airFilterUnitFlowRate": 0.0047222222222222, + "constructionTime": 1, + "generatorFuelFlowRate": 0.0013194444444444, + "gpuBoostRate": 0.041225, + "productionTime": 1, + "scavCaseTime": 1 }, "insurance": { "insuranceMultiplier": { - "prapor": 0.1, - "therapist": 0.2 + "prapor": 0.16, + "therapist": 0.25 }, "returnChancePercent": { - "prapor": 8, - "therapist": 8 + "prapor": 80, + "therapist": 85 } }, @@ -168,72 +180,73 @@ { "standardStash": { - "vertical": 2, - "horizontal": 11 + "vertical": 28, + "horizontal": 10 }, "behindStash": { - "vertical": 3, - "horizontal": 11 + "vertical": 38, + "horizontal": 10 }, "escapeStash": { - "vertical": 4, - "horizontal": 11 + "vertical": 48, + "horizontal": 10 }, "eodStash": { - "vertical": 6, - "horizontal": 11 + "vertical": 68, + "horizontal": 10 }, - "examinedByDefault": true, + "examinedByDefault": false, "removeBackpackFilter": true, - "weightModifier": 2, - "roublesMaxStack": 2, - "dollarsMaxStack": 2, - "eurosMaxStack": 2 + "removeKeyUsageMax": false, + "weightModifier": 1, + "roublesMaxStack": 500000, + "dollarsMaxStack": 50000, + "eurosMaxStack": 50000 }, "locations": { - "allExtractsAvailable": true, - "exfilTime": 2, - "extractionsExtended": true, - "noExtractRestrictions": true + "allExtractsAvailable": false, + "exfilTime": 8, + "extractionsExtended": false, + "noExtractRestrictions": false }, "loot": { "containersInMarkedRoom": true, - "looseLootMultiplier": 2, - "staticLootMultiplier": 2 + "looseLootMultiplier": 1, + "staticLootMultiplier": 1 }, "raid": { - "carExtractBaseStandingGain": 0.2, + "carExtractBaseStandingGain": 0.25, "chompiesBossFix": true, "fixOpenZones": true, - "scavExtractGain": 0.02, - "timeLimit": 2, - "aiAmount": "High", - "aiDifficulty": "Medium", - "bossEnabled": false, - "scavWars": true, - "taggedAndCursed": true, - "enablePve": false + "scavExtractGain": 0.01, + "timeLimit": 60, + "aiAmount": "asonline", + "aiDifficulty": "asonline", + "bossEnabled": true, + "scavWars": false, + "taggedAndCursed": false, + "enablePve": true }, "prewipe_events": { - "allBossesOnReserve": true, - "allTradersSellCheapItems": true, - "glukharOnLabs": true, - "killaOnFactory": true, - "makeObdolbosPowerful": true + "allBossesOnReserve": false, + "allTradersSellCheapItems": false, + "glukharOnLabs": false, + "killaOnFactory": false, + "makeObdolbosPowerful": false } } diff --git a/Valens-AIO/config/config.ts b/Valens-AIO/config/config.ts index 9c6b645..901b179 100644 --- a/Valens-AIO/config/config.ts +++ b/Valens-AIO/config/config.ts @@ -1,4 +1,4 @@ -export interface Root +export interface Config { DebugMode: boolean ammo: Ammo @@ -51,10 +51,18 @@ export interface Pmc maxBackpackLootTotalRub: number maxPocketLootTotalRub: number maxVestLootTotalRub: number - pmcDifficulty: string + difficultyWeights: DifficultyWeights convertIntoPmcChance: ConvertIntoPmcChance } + +export interface DifficultyWeights +{ + useWeights: boolean + weights: Record + difficulty: string +} + export interface ConvertIntoPmcChance { @@ -208,6 +216,7 @@ export interface Items eodStash: Stash examinedByDefault: boolean removeBackpackFilter: boolean + removeKeyUsageMax: boolean weightModifier: number roublesMaxStack: number dollarsMaxStack: number diff --git a/Valens-AIO/package.json b/Valens-AIO/package.json index 30ef1ed..fdd5200 100644 --- a/Valens-AIO/package.json +++ b/Valens-AIO/package.json @@ -1,6 +1,6 @@ { "name": "Valens-AIO", - "version": "1.1.1", + "version": "1.1.2", "main": "src/mod.js", "license": "CC BY-NC-ND 4.0", "author": "Valens", diff --git a/Valens-AIO/src/bots.ts b/Valens-AIO/src/bots.ts index ddfac83..af8e343 100644 --- a/Valens-AIO/src/bots.ts +++ b/Valens-AIO/src/bots.ts @@ -3,9 +3,10 @@ import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Logger } from "./logger"; import type { BossLocationSpawn } from "@spt-aki/models/eft/common/ILocationBase"; -import { Traders } from "./traders"; import { Money } from "@spt-aki/models/enums/Money" import { Config } from "../config/config"; +import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper"; +import { ITrader } from "@spt-aki/models/eft/common/tables/ITrader"; export class Bots { @@ -13,14 +14,16 @@ export class Bots private logger: Logger; private botConfig: IBotConfig; private tables: IDatabaseTables; - private traders: Traders; + private traders: Record; + private weightedRandomHelper: WeightedRandomHelper; - constructor(logger: Logger, databaseServer: DatabaseServer, botConfig: IBotConfig) + constructor(logger: Logger, databaseServer: DatabaseServer, botConfig: IBotConfig, weightedRandomHelper: WeightedRandomHelper) { this.logger = logger; this.botConfig = botConfig; this.tables = databaseServer.getTables(); this.traders = databaseServer.getTables().traders; + this.weightedRandomHelper = weightedRandomHelper; } public updateBots(): void @@ -28,11 +31,21 @@ export class Bots const mod = this.modConfig.bots; - // Changes PMC difficulty to Easy, Normal, Hard, Impossible or AsOnline. Default AsOnline. - if (mod.pmc.pmcDifficulty.toLowerCase() != "asonline") + if (mod.pmc.difficultyWeights.difficulty != "asonline") { - this.botConfig.pmc.difficulty = mod.pmc.pmcDifficulty - this.logger.info(`PMC Bot Difficulty set to ${mod.pmc.pmcDifficulty}`); + // Uses PMC difficulty weighting if Enabled. + if (mod.pmc.difficultyWeights.useWeights) + { + const chosenDifficulty = this.chooseRandomWeightedDifficulty(); + this.logger.info("PMC Difficulty Chance Weights Patched"); + this.logger.info(`PMC Difficulty Chosen: ${chosenDifficulty}`); + } + // Uses PMC difficulty if weighting is Disabled. + else + { + this.botConfig.pmc.difficulty = mod.pmc.difficultyWeights.difficulty; + this.logger.info(`PMC Bot Difficulty set to ${mod.pmc.difficultyWeights.difficulty}`); + } } // Enables common and secure containers to spawn on PMCs while additionally whitelisting the parent IDs. Rarity adjusted via PMC lootNValue. Default true. @@ -45,8 +58,8 @@ export class Bots // Chance that PMC bot will be USEC or BEAR. Higher value means higher chance for the PMC to be USEC. Default is 50% if (mod.pmc.isUsec != 50) { - this.botConfig.pmc.isUsec = mod.isUsec; - this.logger.info(`PMC isUsec Chance is: ${mod.isUsec}`); + this.botConfig.pmc.isUsec = mod.pmc.isUsec; + this.logger.info(`PMC isUsec Chance is: ${mod.pmc.isUsec}`); } // Max Loot Value in Rubles for PMC bots in Backpack, Pockets, and Vest respectively. Default is 150,000/50,000/50,000 @@ -111,6 +124,8 @@ export class Bots this.logger.info("Chance to Convert Bots into PMC Patched"); }*/ + + // Make all bosses spawn chance configurable. const locations = this.tables.locations; @@ -190,7 +205,8 @@ export class Bots ], "BossEscortAmount": "2" } - ] + ], + RandomTimeSpawn: false } glugluWave.BossZone = locations.laboratory.base.OpenZones; @@ -375,6 +391,14 @@ export class Bots dynaLoot.push("5795f317245977243854e041"); } + private chooseRandomWeightedDifficulty(): string + { + const chosenDifficulty = this.weightedRandomHelper.getWeightedInventoryItem(this.modConfig.bots.pmc.difficultyWeights.weights); + this.botConfig.pmc.difficulty = chosenDifficulty; + + return chosenDifficulty; + } + private containers(): any[] { /* Container "id"s diff --git a/Valens-AIO/src/items.ts b/Valens-AIO/src/items.ts index 0befd29..53926ba 100644 --- a/Valens-AIO/src/items.ts +++ b/Valens-AIO/src/items.ts @@ -21,6 +21,12 @@ export class Items this.items = this.tables.getTables().templates.items; this.wtf = this.modConfig.items; + if (this.wtf.removeKeyUsageMax) + { + this.removeKeyUsageMax(); + this.logger.info("Key Usage Limit Removed"); + } + // Weight Modifier. Multiplier of Weight *= modConfig.weightModifier if (this.wtf.weightModifier != 1) { @@ -119,14 +125,11 @@ export class Items // Updates backpacks and removes any values in the ExcludedFilter under props > Grids > props > filters > ExcludedFilter in database/templates/items.json private updateBackpacks(): void { - const items = Object.values(this.tables.getTables().templates.items); + const items = Object.values(this.tables.getTables().templates.items).filter(x=>x._parent === "5448e53e4bdc2d60728b4567"); for (const item of items) { - if (items._parent === "5448e53e4bdc2d60728b4567") - { for (const grid of item._props.Grids) - grid._props.filters[0].ExcludedFilter = []; - } + grid._props.filters[0].ExcludedFilter = []; } } @@ -139,4 +142,13 @@ export class Items item._props.ExaminedByDefault = this.wtf.examinedByDefault; } } + + private removeKeyUsageMax(): void + { + const keys = Object.values(this.tables.getTables().templates.items).filter(x=>x._parent === "543be5e94bdc2df1348b4568"); + for (const key of keys) + { + key._props.MaximumNumberOfUsage = 0; + } + } } diff --git a/Valens-AIO/src/mod.ts b/Valens-AIO/src/mod.ts index 48de371..90c1275 100644 --- a/Valens-AIO/src/mod.ts +++ b/Valens-AIO/src/mod.ts @@ -3,6 +3,7 @@ import { IPostDBLoadMod } from "@spt-aki/models/external/IPostDBLoadMod"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { ConfigServer } from "@spt-aki/servers/ConfigServer"; +import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; //import { IAirdropConfig } from "@spt-aki/models/spt/config/IAirdropConfig"; import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig"; @@ -36,6 +37,7 @@ class ValensAIO implements IPostDBLoadMod private ragfairConfig: IRagfairConfig; //private airdropConfig: IAirdropConfig; private inRaidConfig: IInRaidConfig; + private weightedRandomHelper : WeightedRandomHelper; public postDBLoad(container: DependencyContainer): void { @@ -44,6 +46,7 @@ class ValensAIO implements IPostDBLoadMod const vLogger = new Logger(logger); this.databaseServer = container.resolve("DatabaseServer"); this.configServer = container.resolve("ConfigServer"); + this.weightedRandomHelper = container.resolve("WeightedRandomHelper"); this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); @@ -57,7 +60,7 @@ class ValensAIO implements IPostDBLoadMod const ammo = new Ammo(vLogger, this.databaseServer); ammo.updateAmmo(); - const bots = new Bots(vLogger, this.databaseServer, this.botConfig); + const bots = new Bots(vLogger, this.databaseServer, this.botConfig, this.weightedRandomHelper); bots.updateBots(); const flea = new Flea(vLogger, this.ragfairConfig, this.tables);