From 509b5f46aea07869a187e316bb12c241ade91b13 Mon Sep 17 00:00:00 2001 From: VforValens Date: Mon, 8 Aug 2022 20:03:48 -0400 Subject: [PATCH] Changes for v1.3.0 --- Valens-AIO/V-AIO Progression ReadMe.pdf | Bin 0 -> 21951 bytes Valens-AIO/Valens-AIO ReadMe.pdf | Bin 1721133 -> 1724382 bytes Valens-AIO/config/config.json | 89 ++- Valens-AIO/config/config.ts | 42 +- Valens-AIO/package.json | 4 +- Valens-AIO/src/airdrop.ts | 5 +- Valens-AIO/src/ammo.ts | 6 +- Valens-AIO/src/bots.ts | 709 ++++++++++-------- Valens-AIO/src/containers.ts | 4 +- Valens-AIO/src/flea.ts | 8 +- Valens-AIO/src/globals.ts | 12 +- Valens-AIO/src/hideout.ts | 12 +- Valens-AIO/src/items.ts | 5 +- Valens-AIO/src/locations.ts | 3 +- Valens-AIO/src/loot.ts | 3 +- Valens-AIO/src/mod.ts | 9 +- Valens-AIO/src/progression.ts | 291 +++++++ Valens-AIO/src/quests.ts | 8 +- Valens-AIO/src/raid.ts | 3 +- Valens-AIO/src/weapons.ts | 3 +- .../types/callbacks/NotifierCallbacks.d.ts | 2 +- .../types/controllers/BotController.d.ts | 2 +- .../types/controllers/HideoutController.d.ts | 21 +- .../types/controllers/InraidController.d.ts | 13 +- .../controllers/InsuranceController.d.ts | 1 - .../types/controllers/NoteController.d.ts | 3 +- .../types/controllers/RepairController.d.ts | 1 - Valens-AIO/types/generators/BotGenerator.d.ts | 6 +- .../types/generators/BotLootGenerator.d.ts | 18 +- .../types/generators/BotWeaponGenerator.d.ts | 59 +- .../types/helpers/BotGeneratorHelper.d.ts | 9 +- Valens-AIO/types/helpers/DialogueHelper.d.ts | 21 +- .../types/helpers/ExtendedProfileHelper.d.ts | 27 - Valens-AIO/types/helpers/GameEventHelper.d.ts | 2 +- Valens-AIO/types/helpers/HideoutHelper.d.ts | 12 +- Valens-AIO/types/helpers/InRaidHelper.d.ts | 67 +- Valens-AIO/types/helpers/QuestHelper.d.ts | 26 +- .../types/helpers/RagfairOfferHelper.d.ts | 2 +- .../types/helpers/RagfairServerHelper.d.ts | 2 +- Valens-AIO/types/helpers/RepairHelper.d.ts | 2 +- .../models/eft/common/tables/IBotBase.d.ts | 13 +- .../types/models/eft/profile/IAkiProfile.d.ts | 14 +- Valens-AIO/types/models/enums/AmmoTypes.d.ts | 208 +++++ .../types/models/enums/ContainerTypes.d.ts | 29 + .../types/models/enums/QuestStatus.d.ts | 3 +- Valens-AIO/types/models/enums/SkillTypes.d.ts | 52 ++ .../types/models/enums/WeaponSkillTypes.d.ts | 14 + .../models/spt/bots/GenerateWeaponResult.d.ts | 9 + .../types/models/spt/config/IBotConfig.d.ts | 15 +- .../models/spt/config/IHideoutConfig.d.ts | 1 + .../models/spt/config/IInsuranceConfig.d.ts | 2 + .../models/spt/config/IRepairConfig.d.ts | 2 + .../types/models/spt/mod/NewItemDetails.d.ts | 39 + .../services/BotEquipmentFilterService.d.ts | 50 ++ .../types/services/InsuranceService.d.ts | 17 +- .../types/services/ProfileFixerService.d.ts | 21 + .../types/services/mod/CustomItemService.d.ts | 80 ++ Valens-AIO/types/utils/TimeUtil.d.ts | 10 + 58 files changed, 1552 insertions(+), 539 deletions(-) create mode 100644 Valens-AIO/V-AIO Progression ReadMe.pdf create mode 100644 Valens-AIO/src/progression.ts delete mode 100644 Valens-AIO/types/helpers/ExtendedProfileHelper.d.ts create mode 100644 Valens-AIO/types/models/enums/AmmoTypes.d.ts create mode 100644 Valens-AIO/types/models/enums/ContainerTypes.d.ts create mode 100644 Valens-AIO/types/models/enums/SkillTypes.d.ts create mode 100644 Valens-AIO/types/models/enums/WeaponSkillTypes.d.ts create mode 100644 Valens-AIO/types/models/spt/bots/GenerateWeaponResult.d.ts create mode 100644 Valens-AIO/types/models/spt/mod/NewItemDetails.d.ts create mode 100644 Valens-AIO/types/services/BotEquipmentFilterService.d.ts create mode 100644 Valens-AIO/types/services/mod/CustomItemService.d.ts diff --git a/Valens-AIO/V-AIO Progression ReadMe.pdf b/Valens-AIO/V-AIO Progression ReadMe.pdf new file mode 100644 index 0000000000000000000000000000000000000000..39d58f0773172f992b5556892ed265ee68b56166 GIT binary patch literal 21951 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ʥ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≪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 diff --git a/Valens-AIO/config/config.json b/Valens-AIO/config/config.json index 7958ffd..ccc7306 100644 --- a/Valens-AIO/config/config.json +++ b/Valens-AIO/config/config.json @@ -1,5 +1,5 @@ { - "DebugMode": true, + "DebugMode": false, "ammo": { @@ -25,7 +25,7 @@ "pmc": { - "chanceSameSideIsHostilePercent": 50, + "chanceSameSideIsHostile": 50, "containersOnPMCs": true, "isUsec": 50, "lootNValue": 3, @@ -33,6 +33,30 @@ "maxPocketLootTotalRub": 50000, "maxVestLootTotalRub": 50000, + "convertIntoPmcChance": + { + "assault": + { + "min": 15, + "max": 40 + }, + "cursedAssault": + { + "min": 15, + "max": 40 + }, + "pmcBot": + { + "min": 15, + "max": 30 + }, + "exUsec": + { + "min": 5, + "max": 20 + } + }, + "difficultyWeights": { "difficulty": "asonline", @@ -46,36 +70,14 @@ } }, - "convertIntoPmcChance": + "looseWeaponInBackpackChance": 15, + "looseWeaponInBackpackLoot": { - "assault": 25, - "cursedAssault": 25, - "pmcBot": 25, - "exUsec": 10, - - "assault for 3.2.0": - { - "min": 15, - "max": 40 - }, - "cursedassault for 3.2.0": - { - "min": 15, - "max": 40 - }, - "pmcbot for 3.2.0": - { - "min": 15, - "max": 30 - }, - "exusec for 3.2.0": - { - "min": 5, - "max": 20 - } + "min": 1, + "max": 1 } }, - + "scav": { "lootNValue": 4 @@ -97,8 +99,8 @@ "DOCUMENTS_CASE": { - "width": 1, - "height": 2, + "width": 2, + "height": 1, "cellsH": 4, "cellsV": 4 }, @@ -195,8 +197,8 @@ { "width": 2, "height": 2, - "cellsH": 3, - "cellsV": 4 + "cellsH": 4, + "cellsV": 3 }, "SICC_ORGANIZATIONAL_POUCH": @@ -217,8 +219,8 @@ "THICC_ITEM_CASE": { - "width": 3, - "height": 5, + "width": 5, + "height": 3, "cellsH": 14, "cellsV": 14 }, @@ -286,7 +288,7 @@ "KAPPA": { "width": 3, - "height": 4, + "height": 3, "cellsH": 3, "cellsV": 4 } @@ -424,10 +426,10 @@ "locations": { - "allExtractsAvailable": true, + "allExtractsAvailable": false, "exfilTime": 8, - "extractionsExtended": true, - "noExtractRestrictions": true + "extractionsExtended": false, + "noExtractRestrictions": false }, "loot": @@ -437,6 +439,11 @@ "staticLootMultiplier": 1 }, + "progression": + { + "enabled": true + }, + "quests": { "onlyFoundInRaid": true @@ -461,7 +468,7 @@ { "allBossesOnReserve": false, "allTradersSellCheapItems": false, - "glukharOnLabs": false, + "gluharOnLabs": false, "killaOnFactory": false, "makeObdolbosPowerful": false }, @@ -474,4 +481,4 @@ "overheat": false, "slide": false } -} +} \ No newline at end of file diff --git a/Valens-AIO/config/config.ts b/Valens-AIO/config/config.ts index 884d3e0..d5142a9 100644 --- a/Valens-AIO/config/config.ts +++ b/Valens-AIO/config/config.ts @@ -11,6 +11,7 @@ export interface Config items: Items locations: Locations loot: Loot + progression: Progression raid: Raid quests: Quests prewipeEvents: PrewipeEvents @@ -47,7 +48,7 @@ export interface BossChance export interface Pmc { - chanceSameSideIsHostilePercent: number + chanceSameSideIsHostile: number containersOnPMCs: boolean isUsec: number lootNValue: number @@ -56,6 +57,8 @@ export interface Pmc maxVestLootTotalRub: number difficultyWeights: DifficultyWeights convertIntoPmcChance: ConvertIntoPmcChance + looseWeaponInBackpackChance: number + looseWeaponInBackpackLoot: LooseWeapon } export interface DifficultyWeights @@ -75,35 +78,19 @@ export interface Weights export interface ConvertIntoPmcChance { - assault: number - cursedAssault: number - pmcBot: number - exUsec: number - "assault for 3.2.0": AssaultFor320 - "cursedassault for 3.2.0": CursedassaultFor320 - "pmcbot for 3.2.0": PmcbotFor320 - "exusec for 3.2.0": ExusecFor320 + assault: PmcChance + cursedAssault: PmcChance + pmcBot : PmcChance + exUsec : PmcChance } -export interface AssaultFor320 +export interface PmcChance { min: number max: number } - -export interface CursedassaultFor320 -{ - min: number - max: number -} - -export interface PmcbotFor320 -{ - min: number - max: number -} - -export interface ExusecFor320 + +export interface LooseWeapon { min: number max: number @@ -302,6 +289,11 @@ export interface Loot staticLootMultiplier: number } +export interface Progression +{ + enabled: boolean +} + export interface Quests { onlyFoundInRaid: boolean @@ -326,7 +318,7 @@ export interface PrewipeEvents { allBossesOnReserve: boolean allTradersSellCheapItems: boolean - glukharOnLabs: boolean + gluharOnLabs: boolean killaOnFactory: boolean makeObdolbosPowerful: boolean } diff --git a/Valens-AIO/package.json b/Valens-AIO/package.json index d0a066d..e0be496 100644 --- a/Valens-AIO/package.json +++ b/Valens-AIO/package.json @@ -1,10 +1,10 @@ { "name": "Valens-AIO", - "version": "1.2.3", + "version": "1.3.0", "main": "src/mod.js", "license": "CC BY-NC-ND 4.0", "author": "Valens", - "akiVersion": "3.1.*", + "akiVersion": "3.2.*", "scripts": { "setup:environment": "npm i", "build:unzipped": "copyfiles -e \"./node_modules/**/*.*\" -e \"./dist/**/*.*\" -e \"./package-lock.json\" -e \"./tsconfig.json\" -e \"./README.txt\" -e \"./mod.code-workspace\" \"./**/*.*\" ./dist", diff --git a/Valens-AIO/src/airdrop.ts b/Valens-AIO/src/airdrop.ts index 33753bd..76adfab 100644 --- a/Valens-AIO/src/airdrop.ts +++ b/Valens-AIO/src/airdrop.ts @@ -1,5 +1,4 @@ -/*import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; -import { Config } from "../config/config"; +/*import { Config } from "../config/config"; import { Logger } from "./logger"; import { IAirdropConfig } from "@spt-aki/models/spt/config/IAirdropConfig"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; @@ -8,7 +7,7 @@ export class Airdrop { private modConfig: Config = require("../config/config.jsonc"); private logger: Logger; - private tables: IDatabaseTables; + private databaseServer: IDatabaseTables; private airdropConfig: IAirdropConfig; constructor(logger: Logger, databaseServer: DatabaseServer, airdropConfig: IAirdropConfig) diff --git a/Valens-AIO/src/ammo.ts b/Valens-AIO/src/ammo.ts index cacafad..d8901df 100644 --- a/Valens-AIO/src/ammo.ts +++ b/Valens-AIO/src/ammo.ts @@ -7,17 +7,17 @@ export class Ammo { private modConfig: Config = require("../config/config.json") private logger: Logger; - private databaseServer: DatabaseServer; + private tables: DatabaseServer; constructor(logger: Logger, databaseServer: DatabaseServer) { this.logger = logger; - this.databaseServer = databaseServer; + this.tables = databaseServer.getTables(); } public updateAmmo(): void { - const items = this.databaseServer.getTables().templates.items; + const items = this.tables.templates.items; const mod = this.modConfig.ammo; if (mod.ammoStacks.grenadeCartridges != 1) diff --git a/Valens-AIO/src/bots.ts b/Valens-AIO/src/bots.ts index 0901f47..c98e589 100644 --- a/Valens-AIO/src/bots.ts +++ b/Valens-AIO/src/bots.ts @@ -1,5 +1,4 @@ import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig"; -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"; @@ -13,7 +12,7 @@ export class Bots private modConfig: Config = require("../config/config.json"); private logger: Logger; private botConfig: IBotConfig; - private tables: IDatabaseTables; + private tables: DatabaseServer; private traders: Record; private weightedRandomHelper: WeightedRandomHelper; @@ -22,361 +21,166 @@ export class Bots this.logger = logger; this.botConfig = botConfig; this.tables = databaseServer.getTables(); - this.traders = databaseServer.getTables().traders; + this.traders = this.tables.traders; this.weightedRandomHelper = weightedRandomHelper; } public updateBots(): void { - + // modConfig variables const mod = this.modConfig.bots; + const modPMC = this.modConfig.bots.pmc; + const modScav = this.modConfig.bots.scav; + const preWipe = this.modConfig.prewipeEvents; + + // Server side variables + const pmc = this.botConfig.pmc; + const lootNValue = this.botConfig.lootNValue; + + // Start modifications - if (mod.pmc.difficultyWeights.difficulty != "asonline") + + // Checks if straight up difficulty selection is used or not to determine if it should use that or if it should then go to use weighted difficulties. + if (modPMC.difficultyWeights.difficulty != "asonline") { - // Uses PMC difficulty weighting if Enabled. - if (mod.pmc.difficultyWeights.useWeights) + // Uses PMC difficulty weighting if straight up difficulty selection is not used. + if (modPMC.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. + // 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}`); + pmc.difficulty = modPMC.difficultyWeights.difficulty; + this.logger.info(`PMC Bot Difficulty set to ${modPMC.difficultyWeights.difficulty}`); } } - // Enables common and secure containers to spawn on PMCs while additionally whitelisting the parent IDs. Rarity adjusted via PMC lootNValue. Default true. - if (mod.pmc.containersOnPMCs) + + // Enables common and secure containers to spawn on PMCs by whitelisting the parent IDs. Rarity adjusted via PMC lootNValue. Default true. + if (modPMC.containersOnPMCs) { this.containersOnPMCs(); - this.logger.info(`Containers On PMCs: ${mod.pmc.containersOnPMCs}`); + this.logger.info(`Containers On PMCs: ${modPMC.containersOnPMCs}`); } - // 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) + + // Chance that PMC bot will be USEC or BEAR. Default is 50% + if (modPMC.isUsec != 50) { - this.botConfig.pmc.isUsec = mod.pmc.isUsec; - this.logger.info(`PMC isUsec Chance is: ${mod.pmc.isUsec}`); + pmc.isUsec = modPMC.isUsec; + this.logger.info(`PMC isUsec Chance is: ${modPMC.isUsec}`); } + // Max Loot Value in Rubles for PMC bots in Backpack, Pockets, and Vest respectively. Default is 150,000/50,000/50,000 - if (mod.pmc.maxBackpackLootTotalRub != 150000 - || mod.pmc.maxPocketLootTotalRub !=50000 - || mod.pmc.maxVestLootTotalRub != 50000) + if (modPMC.maxBackpackLootTotalRub != 150000 + || modPMC.maxPocketLootTotalRub !=50000 + || modPMC.maxVestLootTotalRub != 50000) { - this.botConfig.pmc.maxBackpackLootTotalRub = mod.pmc.maxBackpackLootTotalRub; - this.botConfig.pmc.maxPocketLootTotalRub = mod.pmc.maxPocketLootTotalRub; - this.botConfig.pmc.maxVestLootTotalRub = mod.pmc.maxVestLootTotalRub; - this.logger.info("PMC Loot Value totals changed!"); - this.logger.info(`Max Backpack Total Value: ${mod.pmc.maxBackpackLootTotalRub}`); - this.logger.info(`Max Pocket Total Value: ${mod.pmc.maxPocketLootTotalRub}`); - this.logger.info(`Max Vest Total Value: ${mod.pmc.maxVestLootTotalRub}`); + this.changeMaxLootvalue(); + this.logger.info(`PMC Loot Value totals changed! \n Max Backpack Total Value: ${modPMC.maxBackpackLootTotalRub} \n Max Pocket Total Value: ${modPMC.maxPocketLootTotalRub} \n Max Vest Total Value: ${modPMC.maxVestLootTotalRub}`); } - // Chance that the PMC bot of your side (BEAR/USEC) will be hostile or not. Default is 50%. - if (mod.pmc.chanceSameSideIsHostilePercent != 50) + + // Chance that the PMC bot of your faction (BEAR/USEC) will be hostile or not. Default is 50%. + if (modPMC.chanceSameSideIsHostile != 50) { - this.botConfig.pmc.chanceSameSideIsHostilePercent = mod.pmc.chanceSameSideIsHostilePercent; - this.logger.info(`Chance Same Side Is Hostle is ${mod.pmc.chanceSameSideIsHostilePercent}`); + pmc.chanceSameSideIsHostilePercent = modPMC.chanceSameSideIsHostile; + this.logger.info(`Chance Same Side Is Hostle is ${modPMC.chanceSameSideIsHostile}`); } - // Max Bot Cap located in configs/bot.json/maxBotCap + + // Adjusts the Max Bot Cap located in configs/bot.json/maxBotCap if (mod.maxBotCap != 20) { this.botConfig.maxBotCap = mod.maxBotCap; this.logger.info(`Bot Cap is now ${mod.maxBotCap}`); } - if (mod.pmc.lootNValue != 3 || mod.scav.lootNValue != 4) + + // Modifies the lootNValue of PMC or Scav if configured outside of the defaults. + if (modPMC.lootNValue != 3 || modScav.lootNValue != 4) { - this.botConfig.lootNValue.scav = mod.scav.lootNValue; - this.botConfig.lootNValue.pmc = mod.pmc.lootNValue; - this.logger.info("Loot NValue for bots has been changed!"); - this.logger.info(`Scav lootNValue set to ${mod.scav.lootNValue}`); - this.logger.info(`PMC lootNValue set to ${mod.pmc.lootNValue}`); + lootNValue.scav = modScav.lootNValue; + lootNValue.pmc = modPMC.lootNValue; + this.logger.info(`lootNValue for bots has been changed! \n Scav lootNValue set to ${modScav.lootNValue} \n PMC lootNValue set to ${modPMC.lootNValue}`); } - if (mod.pmc.convertIntoPmcChance.assault != 25 || mod.pmc.convertIntoPmcChance.cursedAssault != 25 - || mod.pmc.convertIntoPmcChance.pmcBot != 25 || mod.pmc.convertIntoPmcChance.exUsec != 10) - { - this.botConfig.pmc.types.assault = mod.pmc.convertIntoPmcChance.assault; - this.botConfig.pmc.types.cursedAssault = mod.pmc.convertIntoPmcChance.cursedAssault; - this.botConfig.pmc.types.pmcBot = mod.pmc.convertIntoPmcChance.pmcBot; - this.botConfig.pmc.types.exUsec = mod.pmc.convertIntoPmcChance.exUsec; - } - /*if (mod.pmc.convertIntoPmcChance["assault for 3.2.0"].min != 15 || mod.pmc.convertIntoPmcChance["assault for 3.2.0"].max != 40 - || mod.pmc.convertIntoPmcChance["cursedassault for 3.2.0"].min != 15 || mod.pmc.convertIntoPmcChance["cursedassault for 3.2.0"].max != 40 - || mod.pmc.convertIntoPmcChance["pmcbot for 3.2.0"].min != 15 || mod.pmc.convertIntoPmcChance["pmcbot for 3.2.0"].max != 30 - || mod.pmc.convertIntoPmcChance["exusec for 3.2.0"].min != 15 || mod.pmc.convertIntoPmcChance["exusec for 3.2.0"].max != 20) + // Adjusts the chance for PMC to spawn instead of the default bot type if configured outside of the default values. + const pmcChance = modPMC.convertIntoPmcChance; + if (pmcChance.assault.min != 15 || pmcChance.assault.max != 40 + || pmcChance.cursedAssault.min != 15 || pmcChance.cursedAssault.max != 40 + || pmcChance.pmcBot.min != 15 || pmcChance.pmcBot.max != 30 + || pmcChance.exUsec.min != 5 || pmcChance.exUsec.max != 20) { - this.botConfig.pmc.convertIntoPmcChance.assault.min = mod.pmc.convertIntoPmcChance["assault for 3.2.0"].min; - this.botConfig.pmc.convertIntoPmcChance.assault.max = mod.pmc.convertIntoPmcChance["assault for 3.2.0"].max; - this.botConfig.pmc.convertIntoPmcChance.cursedassault.min = mod.pmc.convertIntoPmcChance["cursedassault for 3.2.0"].min; - this.botConfig.pmc.convertIntoPmcChance.cursedassault.max = mod.pmc.convertIntoPmcChance["cursedassault for 3.2.0"].max; - this.botConfig.pmc.convertIntoPmcChance.pmcbot.min = mod.pmc.convertIntoPmcChance["pmcbot for 3.2.0"].min; - this.botConfig.pmc.convertIntoPmcChance.pmcbot.max = mod.pmc.convertIntoPmcChance["pmcbot for 3.2.0"].max; - this.botConfig.pmc.convertIntoPmcChance.exusec.min = mod.pmc.convertIntoPmcChance["exusec for 3.2.0"].min; - this.botConfig.pmc.convertIntoPmcChance.exusec.max = mod.pmc.convertIntoPmcChance["exusec for 3.2.0"].max; + this.adjustPmcChance(); this.logger.info("Chance to Convert Bots into PMC Patched"); - }*/ + } - - // Make all bosses spawn chance configurable. - const locations = this.tables.locations; - + // Makes *all* bosses spawn chance configurable. if (mod.bossChance.activated) { - for (const i in locations) - { - if (i !== "base") - { - if (locations[i].base.BossLocationSpawn !== []) - { - for (const x in locations[i].base.BossLocationSpawn) - { - locations[i].base.BossLocationSpawn[x].BossChance = mod.bossChance.chance; - this.logger.info(`Boss Chance set to ${mod.bossChance.chance}`) - } - } - } - } + this.configureBossChance(); + this.logger.info(`Boss Chance set to ${mod.bossChance.chance}`) } + // Prewipe Events - if (this.modConfig.prewipeEvents.killaOnFactory) + + + // Spawn Killa On Factory + if (preWipe.killaOnFactory) { - const killaWave = this.createBossWave("bossKilla", 100, "followerBully", 0, locations.factory4_day.base.OpenZones); - this.tables.locations.factory4_day.base.BossLocationSpawn.push(killaWave); - locations.factory4_night.base.BossLocationSpawn.push(killaWave); - this.logger.info("Killa Prewipe Event Enabled"); + this.spawnKillaOnFactory(); + this.logger.info("Killa On Factry Enabled"); } - if (this.modConfig.prewipeEvents.allBossesOnReserve) + + // Spawns All Bosses On Reserve + if (preWipe.allBossesOnReserve) { - let bossWave = this.createBossWave("bossKilla", 100, "followerBully", 0, locations.rezervbase.base.OpenZones); - locations.rezervbase.base.BossLocationSpawn.push(bossWave); - bossWave = this.createBossWave("bossBully", 100, "followerBully", 4, locations.rezervbase.base.OpenZones); - locations.rezervbase.base.BossLocationSpawn.push(bossWave); - bossWave = this.createBossWave("bossKojaniy", 100, "followerKojaniy", 2, locations.rezervbase.base.OpenZones); - locations.rezervbase.base.BossLocationSpawn.push(bossWave); - bossWave = this.createBossWave("bossSanitar", 100, "followerSanitar", 2, locations.rezervbase.base.OpenZones); - locations.rezervbase.base.BossLocationSpawn.push(bossWave); + this.spawnAllBossesOnReserve(); this.logger.info("Bosses On Reserve Prewipe Event Enabled"); } - - if (this.modConfig.prewipeEvents.glukharOnLabs) - { - const glugluWave: BossLocationSpawn = { - "BossName": "bossGluhar", - "BossChance": 43, - "BossZone": "ZoneRailStrorage,ZoneRailStrorage,ZoneRailStrorage,ZonePTOR1,ZonePTOR2,ZoneBarrack,ZoneBarrack,ZoneBarrack,ZoneSubStorage", - "BossPlayer": false, - "BossDifficult": "normal", - "BossEscortType": "followerGluharAssault", - "BossEscortDifficult": "normal", - "BossEscortAmount": "0", - "Time": -1, - "TriggerId": "", - "TriggerName": "", - "Supports": [ - { - "BossEscortType": "followerGluharAssault", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortAmount": "2" - }, - { - "BossEscortType": "followerGluharSecurity", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortAmount": "2" - }, - { - "BossEscortType": "followerGluharScout", - "BossEscortDifficult": [ - "normal" - ], - "BossEscortAmount": "2" - } - ], - RandomTimeSpawn: false - } - glugluWave.BossZone = locations.laboratory.base.OpenZones; - locations.laboratory.base.BossLocationSpawn.push(glugluWave); - this.logger.info("Glukhar On Labs Prewipe Event Enabled"); + + // Spawns Gluhar On Labs + if (preWipe.gluharOnLabs) + { + this.spawnGluharOnLabs(); + this.logger.info("Gluhar On Labs Prewipe Event Enabled"); } + // All cheap items on traders - if (this.modConfig.prewipeEvents.allTradersSellCheapItems) + if (preWipe.allTradersSellCheapItems) { + this.allTradersSellCheapItems(); this.logger.info("Cheap Items On Traders Prewipe Event Enabled"); - for (const trader in this.traders) - { - for (const assort in this.traders[trader].assort.barter_scheme) - { - const itemScheme = this.traders[trader].assort.barter_scheme[assort]; - switch (itemScheme[0][0]._tpl) - { - case Money.ROUBLES: - itemScheme[0][0].count = itemScheme[0][0].count * 0.01; - break; - case Money.DOLLARS: - itemScheme[0][0].count = itemScheme[0][0].count * 0.1; - break; - case Money.EUROS: - itemScheme[0][0].count = itemScheme[0][0].count * 0.05; - break; - default: - break; - - } - } - } } - if (this.modConfig.prewipeEvents.makeObdolbosPowerful) + // Makes Obdolbos Super Powered + if (preWipe.makeObdolbosPowerful) { - const obdolbosBuff = [ - { - "BuffType": "StaminaRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": 0.5, - "AbsoluteValue": true, - "SkillName": "" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": 10, - "AbsoluteValue": true, - "SkillName": "Endurance" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": 10, - "AbsoluteValue": true, - "SkillName": "Strength" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": 20, - "AbsoluteValue": true, - "SkillName": "StressResistance" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": 20, - "AbsoluteValue": true, - "SkillName": "Charisma" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": -20, - "AbsoluteValue": true, - "SkillName": "Memory" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": -20, - "AbsoluteValue": true, - "SkillName": "Intellect" - }, - { - "BuffType": "SkillRate", - "Chance": 1, - "Delay": 1, - "Duration": 1800, - "Value": -20, - "AbsoluteValue": true, - "SkillName": "Attention" - }, - { - "BuffType": "Pain", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": 0, - "AbsoluteValue": false, - "SkillName": "" - }, - { - "BuffType": "StomachBloodloss", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": 0, - "AbsoluteValue": false, - "SkillName": "" - }, - { - "BuffType": "HydrationRate", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": -0.05, - "AbsoluteValue": true, - "SkillName": "" - }, - { - "BuffType": "EnergyRate", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": -0.05, - "AbsoluteValue": true, - "SkillName": "" - }, - { - "BuffType": "DamageModifier", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": 0.2, - "AbsoluteValue": false, - "SkillName": "" - }, - { - "BuffType": "QuantumTunnelling", - "Chance": 0.25, - "Delay": 1, - "Duration": 1800, - "Value": 0, - "AbsoluteValue": false, - "SkillName": "" - }] - - this.tables.globals.config.Health.Effects.Stimulator.Buffs.Buffs_Obdolbos = obdolbosBuff; + this.makeObdolbosPowerful(); this.logger.info("Make Obdolbos Powerful Prewipe Event Enabled"); } + + if (modPMC.looseWeaponInBackpackChance != 15 || modPMC.looseWeaponInBackpackLoot.max != 1 || modPMC.looseWeaponInBackpackLoot.min != 1) + { + this.changeLooseWeapon(); + this.logger.info("Loose Weapon In PMC Backpack Values Patched"); + } } - // 5c0a840b86f7742ffa4f2482 thicc items case + + // Functions start here. + + // Function to enable secured and common containers on PMCs. private containersOnPMCs(): void { const dynaLoot = this.botConfig.pmc.dynamicLoot.whitelist; @@ -393,43 +197,8 @@ export class Bots return chosenDifficulty; } - private containers(): any[] - { - /* Container "id"s - * - * S I C C pouch: 5d235bb686f77443f4331278 - * Magazine Case: 5c127c4486f7745625356c13 - * Weapon Case: 59fb023c86f7746d0d4b423c - * T H I C C Weapon Case: 5b6d9ce188a4501afc1b2b25 - * Item Case: 59fb042886f7746c5005a7b2 - * T H I C C Item Case: 5c0a840b86f7742ffa4f2482 - * Money case: 59fb016586f7746d0d4b423a - * Mr Holodilnick Thermal Bag: 5c093db286f7740a1b2617e3 - * Medicine case: 5aafbcd986f7745e590fff23 - * Lucky scav junkbox: 5b7c710788a4506dec015957 - * Grenade case: 5e2af55f86f7746d4159f07c - * Ammunition case: 5aafbde786f774389d0cbc0f - * Documents case: 590c60fc86f77412b13fddcf - * Key tool: 59fafd4b86f7745ca07e123 - * Injector case: 619cbf7d23893217ec30b689 - * Dogtag case: 5c093e3486f77430cb02e593 - * Keycard holder: 619cbf9e0a7c3a1a2731940a - * WZ Wallet: 60b0f6c058e0b0481a09ad11 - * Pistol case: 567143bf4bdc2d1a0f8b4567 - * Secure container: 5448bf274bdc2dfc2f8b456a - * Kappa container: 5c093ca986f7740a1867ab12 - * Gamma container: 60b0f6c058e0b0481a09ad11 - */ - - const lootItems = ["5d235bb686f77443f4331278","5c127c4486f7745625356c13","59fb023c86f7746d0d4b423c","5b6d9ce188a4501afc1b2b25","59fb042886f7746c5005a7b2","5c0a840b86f7742ffa4f2482", - "59fb016586f7746d0d4b423a","5c093db286f7740a1b2617e3","5aafbcd986f7745e590fff23","5b7c710788a4506dec015957","5e2af55f86f7746d4159f07c","5448bf274bdc2dfc2f8b456a","5c093ca986f7740a1867ab12", - "5aafbde786f774389d0cbc0f","590c60fc86f77412b13fddcf","59fafd4b86f7745ca07e1232","619cbf7d23893217ec30b689","619cbf9e0a7c3a1a2731940a","5c093e3486f77430cb02e593","60b0f6c058e0b0481a09ad11", - "567143bf4bdc2d1a0f8b4567","60b0f6c058e0b0481a09ad11","59db794186f77448bc595262","5857a8b324597729ab0a0e7d"] - - return lootItems; - } - private createBossWave(role: string, chance: number, followers: string, escortAmount: number, zones: string): any + public createBossWave(role: string, chance: number, followers: string, escortAmount: number, zones: string): any { return { "BossName": role, @@ -443,4 +212,296 @@ export class Bots "Time": -1 } } + + + private adjustPmcChance(): void + { + const pmcConfig = this.botConfig.pmc.convertIntoPmcChance; + const modConfig = this.modConfig.bots.pmc.convertIntoPmcChance; + + pmcConfig.assault.min = modConfig.assault.min; + pmcConfig.assault.max = modConfig.assault.max; + pmcConfig.cursedassault.min = modConfig.cursedAssault.min; + pmcConfig.cursedassault.max = modConfig.cursedAssault.max; + pmcConfig.pmcbot.min = modConfig.pmcBot.min; + pmcConfig.pmcbot.max = modConfig.pmcBot.max; + pmcConfig.exusec.min = modConfig.exUsec.min; + pmcConfig.exusec.max = modConfig.exUsec.max; + } + + + private changeMaxLootvalue(): void + { + const lootConfig = this.botConfig.pmc; + const modConfig = this.modConfig.bots.pmc; + + lootConfig.maxBackpackLootTotalRub = modConfig.maxBackpackLootTotalRub; + lootConfig.maxPocketLootTotalRub = modConfig.maxPocketLootTotalRub; + lootConfig.maxVestLootTotalRub = modConfig.maxVestLootTotalRub; + } + + + private configureBossChance(): void + { + const locations = this.tables.locations; + + for (const i in locations) + { + if (i !== "base") + { + if (locations[i].base.BossLocationSpawn !== []) + { + for (const x in locations[i].base.BossLocationSpawn) + { + locations[i].base.BossLocationSpawn[x].BossChance = this.modConfig.bots.bossChance.chance; + } + } + } + } + } + + + private spawnKillaOnFactory(): void + { + const locations = this.tables.locations; + const killaWave = this.createBossWave("bossKilla", 100, "followerBully", 0, locations.factory4_day.base.OpenZones); + this.tables.locations.factory4_day.base.BossLocationSpawn.push(killaWave); + locations.factory4_night.base.BossLocationSpawn.push(killaWave); + } + + + private spawnAllBossesOnReserve(): void + { + const locations = this.tables.locations; + let bossWave = this.createBossWave("bossKilla", 100, "followerBully", 0, locations.rezervbase.base.OpenZones); + locations.rezervbase.base.BossLocationSpawn.push(bossWave); + bossWave = this.createBossWave("bossBully", 100, "followerBully", 4, locations.rezervbase.base.OpenZones); + locations.rezervbase.base.BossLocationSpawn.push(bossWave); + bossWave = this.createBossWave("bossKojaniy", 100, "followerKojaniy", 2, locations.rezervbase.base.OpenZones); + locations.rezervbase.base.BossLocationSpawn.push(bossWave); + bossWave = this.createBossWave("bossSanitar", 100, "followerSanitar", 2, locations.rezervbase.base.OpenZones); + locations.rezervbase.base.BossLocationSpawn.push(bossWave); + } + + + private spawnGluharOnLabs(): void + { + const locations = this.tables.locations; + const glugluWave: BossLocationSpawn = + { + "BossName": "bossGluhar", + "BossChance": 43, + "BossZone": "ZoneRailStrorage,ZoneRailStrorage,ZoneRailStrorage,ZonePTOR1,ZonePTOR2,ZoneBarrack,ZoneBarrack,ZoneBarrack,ZoneSubStorage", + "BossPlayer": false, + "BossDifficult": "normal", + "BossEscortType": "followerGluharAssault", + "BossEscortDifficult": "normal", + "BossEscortAmount": "0", + "Time": -1, + "TriggerId": "", + "TriggerName": "", + "Supports": [ + { + "BossEscortType": "followerGluharAssault", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortAmount": "2" + }, + { + "BossEscortType": "followerGluharSecurity", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortAmount": "2" + }, + { + "BossEscortType": "followerGluharScout", + "BossEscortDifficult": [ + "normal" + ], + "BossEscortAmount": "2" + } + ], + RandomTimeSpawn: false + } + + glugluWave.BossZone = locations.laboratory.base.OpenZones; + locations.laboratory.base.BossLocationSpawn.push(glugluWave); + } + + + private allTradersSellCheapItems(): void + { + + for (const trader in this.traders) + { + for (const assort in this.traders[trader].assort.barter_scheme) + { + const itemScheme = this.traders[trader].assort.barter_scheme[assort]; + switch (itemScheme[0][0]._tpl) + { + case Money.ROUBLES: + itemScheme[0][0].count = itemScheme[0][0].count * 0.01; + break; + case Money.DOLLARS: + itemScheme[0][0].count = itemScheme[0][0].count * 0.1; + break; + case Money.EUROS: + itemScheme[0][0].count = itemScheme[0][0].count * 0.05; + break; + default: + break; + + } + } + } + } + + + private makeObdolbosPowerful(): void + { + + const obdolbosBuff = [ + { + "BuffType": "StaminaRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": 0.5, + "AbsoluteValue": true, + "SkillName": "" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": 10, + "AbsoluteValue": true, + "SkillName": "Endurance" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": 10, + "AbsoluteValue": true, + "SkillName": "Strength" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": 20, + "AbsoluteValue": true, + "SkillName": "StressResistance" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": 20, + "AbsoluteValue": true, + "SkillName": "Charisma" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": -20, + "AbsoluteValue": true, + "SkillName": "Memory" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": -20, + "AbsoluteValue": true, + "SkillName": "Intellect" + }, + { + "BuffType": "SkillRate", + "Chance": 1, + "Delay": 1, + "Duration": 1800, + "Value": -20, + "AbsoluteValue": true, + "SkillName": "Attention" + }, + { + "BuffType": "Pain", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": 0, + "AbsoluteValue": false, + "SkillName": "" + }, + { + "BuffType": "StomachBloodloss", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": 0, + "AbsoluteValue": false, + "SkillName": "" + }, + { + "BuffType": "HydrationRate", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": -0.05, + "AbsoluteValue": true, + "SkillName": "" + }, + { + "BuffType": "EnergyRate", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": -0.05, + "AbsoluteValue": true, + "SkillName": "" + }, + { + "BuffType": "DamageModifier", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": 0.2, + "AbsoluteValue": false, + "SkillName": "" + }, + { + "BuffType": "QuantumTunnelling", + "Chance": 0.25, + "Delay": 1, + "Duration": 1800, + "Value": 0, + "AbsoluteValue": false, + "SkillName": "" + }] + + this.tables.globals.config.Health.Effects.Stimulator.Buffs.Buffs_Obdolbos = obdolbosBuff; + } + + + private changeLooseWeapon():void + { + const pmcConfig = this.botConfig.pmc; + const modConfig = this.modConfig.bots.pmc; + + pmcConfig.looseWeaponInBackpackChancePercent = modConfig.looseWeaponInBackpackChance; + pmcConfig.looseWeaponInBackpackLootMinMax.min = modConfig.looseWeaponInBackpackLoot.min; + pmcConfig.looseWeaponInBackpackLootMinMax.max = modConfig.looseWeaponInBackpackLoot.max; + } + } diff --git a/Valens-AIO/src/containers.ts b/Valens-AIO/src/containers.ts index ff185b2..ce8664b 100644 --- a/Valens-AIO/src/containers.ts +++ b/Valens-AIO/src/containers.ts @@ -1,5 +1,3 @@ - -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Logger } from "./logger"; import { Config } from "../config/config"; @@ -9,7 +7,7 @@ export class Containers { private modConfig: Config = require("../config/config.json"); private logger: Logger; - private tables: IDatabaseTables; + private tables: DatabaseServer; constructor(logger: Logger, databaseServer: DatabaseServer) { diff --git a/Valens-AIO/src/flea.ts b/Valens-AIO/src/flea.ts index 0311589..0cc7e24 100644 --- a/Valens-AIO/src/flea.ts +++ b/Valens-AIO/src/flea.ts @@ -1,4 +1,4 @@ -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { IRagfairConfig } from "@spt-aki/models/spt/config/IRagfairConfig"; import { Logger } from "./logger"; import { Config } from "../config/config"; @@ -8,14 +8,14 @@ export class Flea private modConfig: Config = require("../config/config.json"); private logger: Logger; private ragfairConfig: IRagfairConfig; - private tables: IDatabaseTables; + private tables: DatabaseServer; - constructor (logger: Logger, ragfairConfig: IRagfairConfig, tables: IDatabaseTables) + constructor (logger: Logger, ragfairConfig: IRagfairConfig, databaseServer: DatabaseServer) { this.logger = logger; this.ragfairConfig = ragfairConfig; - this.tables = tables; + this.tables = databaseServer.getTables(); } diff --git a/Valens-AIO/src/globals.ts b/Valens-AIO/src/globals.ts index 63d1d4d..6ac9a39 100644 --- a/Valens-AIO/src/globals.ts +++ b/Valens-AIO/src/globals.ts @@ -6,18 +6,18 @@ export class Globals { private modConfig: Config = require("../config/config.json"); private logger: Logger; - private databaseServer: DatabaseServer; + private tables: DatabaseServer; constructor(logger: Logger, databaseServer: DatabaseServer) { this.logger = logger; - this.databaseServer = databaseServer; + this.tables = databaseServer.getTables(); } public updateGlobals(): void { const mod = this.modConfig.globals; - const global = this.databaseServer.getTables().globals; + const global = this.tables.globals; if (mod.damagePerMeter != 9 || mod.safeHeight != 3) { @@ -50,7 +50,7 @@ export class Globals private matchEndSettings(): void { - const global1 = this.databaseServer.getTables().globals.config.exp.match_end; + const global1 = this.tables.globals.config.exp.match_end; const mod = this.modConfig.globals.matchEnd; global1.survived_exp_requirement = mod.survivedExpRequirement; @@ -63,8 +63,8 @@ export class Globals global1.survivedMult = mod.survivedMult; global1.runnerMult = mod.runnerMult; global1.killedMult = mod.killedMult; - this.databaseServer.getTables().globals.config.exp.kill.headShotMult = mod.headShotMult; - this.databaseServer.getTables().globals.config.exp.kill.expOnDamageAllHealth = mod.expOnDamageAllHealth; + this.tables.globals.config.exp.kill.headShotMult = mod.headShotMult; + this.tables.globals.config.exp.kill.expOnDamageAllHealth = mod.expOnDamageAllHealth; this.logger.info("Match End Settings Patched"); } } diff --git a/Valens-AIO/src/hideout.ts b/Valens-AIO/src/hideout.ts index f5b930e..16d30f3 100644 --- a/Valens-AIO/src/hideout.ts +++ b/Valens-AIO/src/hideout.ts @@ -6,12 +6,12 @@ export class Hideout { private modConfig: Config = require("../config/config.json") private logger: Logger; - private databaseServer: DatabaseServer; + private tables: DatabaseServer; constructor(logger: Logger, databaseServer: DatabaseServer) { this.logger = logger; - this.databaseServer = databaseServer; + this.tables = databaseServer.getTables(); } public updateHideout(): void @@ -40,7 +40,7 @@ export class Hideout ||mod.generatorFuelFlowRate != 0.0013194444444444 ||mod.gpuBoostRate != 0.041225) { - const settings = this.databaseServer.getTables().hideout.settings; + const settings = this.tables.hideout.settings; settings.airFilterUnitFlowRate = mod.airFilterUnitFlowRate; settings.generatorFuelFlowRate = mod.generatorFuelFlowRate; settings.gpuBoostRate = mod.gpuBoostRate; @@ -53,7 +53,7 @@ export class Hideout private updateConstructionTime() { - for (const area of this.databaseServer.getTables().hideout.areas) + for (const area of this.tables.hideout.areas) { for (const stage in area.stages) { @@ -65,7 +65,7 @@ export class Hideout private updateProductionTime() { - for (const production of this.databaseServer.getTables().hideout.production) + for (const production of this.tables.hideout.production) { production.productionTime *= this.modConfig.hideout.productionTime; } @@ -73,7 +73,7 @@ export class Hideout private updateScavCase() { - for (const scavCase of this.databaseServer.getTables().hideout.scavcase) + for (const scavCase of this.tables.hideout.scavcase) { scavCase.ProductionTime *= this.modConfig.hideout.scavCaseTime; } diff --git a/Valens-AIO/src/items.ts b/Valens-AIO/src/items.ts index 0c35c1c..a43dfa8 100644 --- a/Valens-AIO/src/items.ts +++ b/Valens-AIO/src/items.ts @@ -1,7 +1,6 @@ import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Config } from "../config/config"; import { Logger } from "./logger"; -import { Money } from "@spt-aki/models/enums/Money" export class Items { @@ -14,13 +13,13 @@ export class Items constructor(logger: Logger, databaseServer: DatabaseServer) { this.logger = logger; - this.tables = databaseServer; + this.tables = databaseServer.getTables(); } public updateItems(): void { - this.items = this.tables.getTables().templates.items; + this.items = this.tables.templates.items; this.mod = this.modConfig.items; if (this.mod.removeKeyUsageMax) diff --git a/Valens-AIO/src/locations.ts b/Valens-AIO/src/locations.ts index c9931ca..34f6783 100644 --- a/Valens-AIO/src/locations.ts +++ b/Valens-AIO/src/locations.ts @@ -1,4 +1,3 @@ -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Config } from "../config/config"; import { Logger } from "./logger"; @@ -7,7 +6,7 @@ export class Locations { private modConfig: Config = require("../config/config.json"); private logger: Logger; - private tables: IDatabaseTables; + private tables: DatabaseServer; constructor (logger: Logger, databaseServer: DatabaseServer) { diff --git a/Valens-AIO/src/loot.ts b/Valens-AIO/src/loot.ts index 93bbf7b..55efede 100644 --- a/Valens-AIO/src/loot.ts +++ b/Valens-AIO/src/loot.ts @@ -1,5 +1,4 @@ import { ILocationConfig } from "@spt-aki/models/spt/config/ILocationConfig"; -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Config } from "../config/config"; import { Logger } from "./logger"; @@ -8,7 +7,7 @@ export class Loot { private modConfig: Config = require("../config/config.json"); private logger: Logger; - private tables: IDatabaseTables; + private tables: DatabaseServer; private locationConfig: ILocationConfig; constructor (logger: Logger, databaseServer: DatabaseServer, locationConfig: ILocationConfig) diff --git a/Valens-AIO/src/mod.ts b/Valens-AIO/src/mod.ts index 721be32..c550ed8 100644 --- a/Valens-AIO/src/mod.ts +++ b/Valens-AIO/src/mod.ts @@ -1,7 +1,6 @@ import { DependencyContainer } from "tsyringe"; 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"; @@ -27,13 +26,13 @@ import { Weapons } from "./weapons"; import { Containers } from "./containers"; import { Locations } from "./locations"; import { Quests } from "./quests"; +import { Progression } from "./progression"; //import { Airdrop } from "./airdrop"; class ValensAIO implements IPostDBLoadMod { private modConfig: Config = require("../config/config.json"); private logger: ILogger; - private tables: IDatabaseTables; private databaseServer: DatabaseServer; private configServer: ConfigServer; private botConfig: IBotConfig; @@ -55,7 +54,6 @@ class ValensAIO implements IPostDBLoadMod this.locationConfig = this.configServer.getConfig(ConfigTypes.LOCATION); this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); this.botConfig = this.configServer.getConfig(ConfigTypes.BOT); - this.tables = this.databaseServer.getTables(); this.inRaidConfig = this.configServer.getConfig(ConfigTypes.IN_RAID); this.insuranceConfig = this.configServer.getConfig(ConfigTypes.INSURANCE); @@ -71,7 +69,7 @@ class ValensAIO implements IPostDBLoadMod const containers = new Containers(vLogger, this.databaseServer); containers.updateContainers(); - const flea = new Flea(vLogger, this.ragfairConfig, this.tables); + const flea = new Flea(vLogger, this.ragfairConfig, this.databaseServer); flea.updateFlea(); const globals = new Globals(vLogger, this.databaseServer); @@ -91,6 +89,9 @@ class ValensAIO implements IPostDBLoadMod const loot = new Loot(vLogger, this.databaseServer, this.locationConfig); loot.updateLoot(); + + const progression = new Progression(vLogger, this.databaseServer, this.botConfig); + progression.updateProgression(); const quests = new Quests(vLogger, this.databaseServer); quests.updateQuests(); diff --git a/Valens-AIO/src/progression.ts b/Valens-AIO/src/progression.ts new file mode 100644 index 0000000..2f077c4 --- /dev/null +++ b/Valens-AIO/src/progression.ts @@ -0,0 +1,291 @@ +import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; +import { Logger } from "./logger"; +import { Config } from "../config/config"; + +export class Progression +{ + private modConfig: Config = require("../config/config.json"); + private logger: Logger; + private botConfig: IBotConfig; + private tables: DatabaseServer; + + constructor(logger: Logger, databaseServer: DatabaseServer, botConfig: IBotConfig) + { + this.logger = logger; + this.botConfig = botConfig; + this.tables = databaseServer.getTables(); + } + + public updateProgression(): void + { + + // modConfig variables + const mod = this.modConfig.progression; + + + // Server side variables + + + if (mod.enabled) + { + this.generateProgression(); + this.logger.info("Progressional Gear Changes Injected"); + } + } + + + // Functions start here + + + private generateProgression() + { + const primaryWeaponArrayLL1 = ["574d967124597745970e7c94", "57d14d2524597714373db789", "57f4c844245977379d5c14d1", "59984ab886f7743e98271174", "5ea03f7400685063ec28bfa8", "5ae08f0a5acfc408fb1398a1", "5bfd297f0db834001a669119", "59d6088586f774275f37482f", "583990e32459771419544dd2", "59e6152586f77473dc057aa1", "5c07c60e0db834002330051f", "5a38e6bac4a2826c6e06d79b", "56dee2bdd2720bc8328b4567", "5447a9cd4bdc2dbd208b4567", "5d2f0d8048f0356c925bc3b0", "5d2f0d8048f0356c925bc3b0", "5fc3e272f8b6a877a729eac5", "58948c8e86f77409493f7266", "5644bd2b4bdc2d3b4c8b4572", "59e6687d86f77411d949b251", "54491c4f4bdc2db1078b4568", "5ba26383d4351e00334c93d9", "587e02ff24597743df3deaeb", "5c501a4d2e221602b412b540", "60db29ce99594040e04c4a27", "5580223e4bdc2d1c128b457f", "61f7c9e189e6fb1a5e3ea78d", "5e870397991fd70db46995c8", "5de652c31b7e3716273428be"]; + const primaryWeaponArrayLL2 = primaryWeaponArrayLL1.concat(...["5839a40f24597726f856b511", "59ff346386f77477562ff5e2", "5ab8e9fcd8ce870019439434", "5bf3e03b0db834001d2c4a9c", "55801eed4bdc2d89578b4588", "5fbcc1d9016cce60e8341ab3", "628b5638ad252a16da6dd245", "5f2a9575926fd9352339381f", "5a7828548dc32e5a9c28b516", "60339954d62c9b14ed777c06", "6184055050224f204c1da540", "623063e994fc3f7b302a9696", "5e00903ae9dc277128008b87", "5ac66cb05acfc40198510a10", "5aafa857e5b5b00018480968", "5cc82d76e24e8d00134b4b83", "5bfea6e90db834001b7347f3", "576165642459773c7a400233", "606dae0ab0e443224b421bb7"]); + const primaryWeaponArrayLL3 = primaryWeaponArrayLL2.concat(...["5ac66d725acfc43b321d4b60", "5a0ec13bfcdbcb00165aa685", "5abcbc27d8ce8700182eceeb", "5ac4cd105acfc40016339859", "5ac66d2e5acfc43b321d4b53", "5ac66d9b5acfc4001633997a", "5beed0f50db834001c062b12", "57838ad32459774a17445cd2", "5c46fbd72e2216398b5a8c9c", "5e848cc2988a8701445df1e8", "5d43021ca4b9362eab4b5e25", "588892092459774ac91d4b11", "5c488a752e221602b412af63", "5b0bbe4e5acfc40dc528a72d", "618428466ef05c2ce828f218", "5a367e5dc4a282000e49738f", "5df8ce05b11454561e39243b", "6176aca650224f204c1da3fb", "628a60ae6b1d481ff772e9c8", "6183afd850224f204c1da514", "6165ac306ef05c2ce828ef74", "6259b864ebedf17603599e88"]); + + const holsterArrayLL1 = ["5448bd6b4bdc2dfc2f8b4569", "571a12c42459771f627b58a0", "576a581d2459771e7b1bc4f1", "5a17f98cfcdbcb0980087290", "5e81c3cbac2bb513793cdc75", "5cadc190ae921500103bb3b6", "56d59856d2720bd8418b456a", "5a7ae0c351dfba0017554310"]; + const holsterArrayLL2 = holsterArrayLL1.concat(...["61a4c8884f95bc3b2c5dc96f", "56e0598dd2720bb5668b45a6", "59f98b4986f7746f546d2cef", "602a9740da11d6478d5a06dc", "6193a720f8ee7e52e42109ed"]); + const holsterArrayLL3 = holsterArrayLL2.concat(...["5abccb7dd8ce87001773e277", "5d3eb3b0a4b93615055e84d2", "5b1fa9b25acfc40018633c01"]); + + + const backpackArrayLL1 = ["5ab8ee7786f7742d8f33f0b9", "544a5cde4bdc2d39388b456b", "5e9dcf5986f7746c417435b3", "5ab8f04f86f774585f4237d8", "5ca20d5986f774331e7c9602"]; + const backpackArrayLL2 = backpackArrayLL1.concat(...["545cdae64bdc2d39198b4568", "60a2828e8689911a226117f9", "618bb76513f5097c8d5aa2d5", "5f5e467b0bc58666c37e7821", "5ab8ebf186f7742d8b372e80"]); + const backpackArrayLL3 = backpackArrayLL2.concat(...["5f5e46b96bdad616ad46d613", "5d5d940f86f7742797262046", "60a272cc93ef783291411d8e", "6034d103ca006d2dca39b3f0", "619cf0335771dd3c390269ae", "628e1ffc83ec92260c0f437f"]); + + + const tacticalVestArrayLL1 = ["5929a2a086f7744f4b234d43", "5e4abc1f86f774069619fbaa", "6034d0230ca681766b6a0fb5", "6034cf5fffd42c541047f72e", "572b7adb24597762ae139821", "5c0e3eb886f7742015526062"]; + const tacticalVestArrayLL2 = tacticalVestArrayLL1.concat(...["5d5d8ca986f7742798716522", "544a5caa4bdc2d1a388b4568", "5c0e446786f7742013381639", "592c2d1a86f7746dbe2af32a", "5d5d85c586f774279a21cbdb", "59e7643b86f7742cbf2c109", "5b44c8ea86f7742d1627baf1", "5ca20abf86f77418567a43f2", "5d5d646386f7742797261fd9", "5fd4c60f875c30179f5d04c2", "60a6220e953894617404b00a", "61bc85697113f767765c7fe7", "603648ff5a45383c122086ac", "5e4abfed86f77406a2713cf7"]); + const tacticalVestArrayLL3 = tacticalVestArrayLL2.concat(...["60a3c70cde5f453f634816a3", "5648a69d4bdc2ded0b8b457b", "5ab8dced86f774646209ec87", "5ab8dab586f77441cd04f2a2", "60a621c49c197e4e8c4455e6", "5b44cad286f77402a54ae7e5", "5c0e6a1586f77404597b4965", "5c0e722886f7740458316a57", "5c0e746986f7741453628fe5", "5d5d87f786f77427997cfaef", "5df8a42886f77412640e2e75", "628d0618d1ba6e4fa07ce5a4", "61bcc89aef0f505f0c6cd0fc", "628dc750b910320f4c27a732", "628cd624459354321c4b7fa2"]); + + + const earpieceArrayLL1 = ["5b432b965acfc47a8774094e", "6033fa48ffd42c541047f728"]; + const earpieceArrayLL2 = earpieceArrayLL1.concat(...["5645bcc04bdc2d363b8b4572", "5aa2ba71e5b5b000137b758f"]); + const earpieceArrayLL3 = earpieceArrayLL2.concat(...["5a16b9fffcdbcb0176308b34"]); + + + const headwearArrayLL1 = ["5a7c4850e899ef00150be885", "5aa7d193e5b5b000171d063f", "5c06c6a80db834001b735491", "59e7711e86f7746cae05fbe1", "5ac4c50d5acfc40019262e87", "5645bc214bdc2d363b8b4571", "5aa2a7e8e5b5b00016327c16", "5b40e61f5acfc4001a599bec", "5aa2b87de5b5b00016327c25", "5b40e5e25acfc4001a599bea"]; + const headwearArrayLL2 = headwearArrayLL1.concat(...["5aa7d03ae5b5b00016327db5", "5d5e7d28a4b936645d161203", "5aa7e454e5b5b0214e506fa2", "5aa7e3abe5b5b000171d064d", "5b40e4035acfc47a87740943", "5b432d215acfc4771e1c6624", "5f60e784f2bcbb675b00dac7", "5aa2ba19e5b5b00014028f4e", "5b43271c5acfc432ff4dce65", "60b52e5bc7d8103275739d67", "5a16b672fcdbcb001912fa83"]); + const headwearArrayLL3 = headwearArrayLL2.concat(...["5ac8d6885acfc400180ae7b0", "5a154d5cfcdbcb001a3b00da", "5e00c1ad86f774747333222c", "5b40e3f35acfc40016388218", "5b4329f05acfc47a86086aa1", "5d6d3716a4b9361bc8618872", "5aa2b9ede5b5b000137b758b", "5c091a4e0db834001d5addc8", "5f60e7788adaa7100c3adb49", "5f60e6403b85f6263c14558c", "5aa7e373e5b5b000137b76f0"]); + + + const armorVestArrayLL1 = ["5df8a2ca86f7740bfe6df777", "5ab8e4ed86f7742d8e50c7fa", "5648a7494bdc2d9d488b4583", "5c0e5bab86f77461f55ed1f3", "5c0e5edb86f77461f55ed1f7", "62a09d79de7ac81993580530"]; + const armorVestArrayLL2 = armorVestArrayLL1.concat(...["5b44d22286f774172b0c9de8", "5c0e51be86f774598e797894"]) + const armorVestArrayLL3 = armorVestArrayLL2.concat(...["5f5f41476bdad616ad46d631", "545cdb794bdc2d3a198b456a", "5ab8e79e86f7742d8b372e78", "5b44d0de86f774503d30cba8", "5c0e53c886f7747fa54205c7", "5c0e57ba86f7747fa141986d", "5ca2151486f774244a3b8d30", "609e8540d5c319764c2bc2e9"]); + + const eyewearArrayLL1 = ["5aa2b986e5b5b00014028f4c", "557ff21e4bdc2d89578b4586", "5b432be65acfc433000ed01f"]; + const eyewearArrayLL2 = eyewearArrayLL1.concat(...["5d5fca1ea4b93635fd598c07"]); + const eyewearArrayLL3 = eyewearArrayLL2.concat(...["603409c80ca681766b6a0fb2", "5c0d32fcd174af02a1659c75", "5d6d2e22a4b9361bd5780d05"]); + + const armBandArrayLL1 = ["5b3f16c486f7747c327f55f7", "5b3f3ade86f7746b6b790d8e", "5b3f3af486f774679e752c1f", "5b3f3b0186f774021a2afef7", "5b3f3b0e86f7746752107cda"]; + const armBandArrayLL2 = armBandArrayLL1; + const armBandArrayLL3 = armBandArrayLL2.concat(...["619bdf9cc9546643a67df6f8", "619bc61e86e01e16f839a999", "619bdfd4c9546643a67df6fa", "619bdd8886e01e16f839a99c", "60b0f988c4449e4cb624c1da", "5f9949d869e2777a0e779ba5"]); + + const faceCoverArrayLL1 = ["572b7f1624597762ae139822"]; + const faceCoverArrayLL2 = faceCoverArrayLL1.concat(...["5ab8f39486f7745cd93a1cca", "5b4325355acfc40019478126"]); + const faceCoverArrayLL3 = faceCoverArrayLL2.concat(...["5ab8f85d86f7745cd93a1cf5", "5b432f3d5acfc4704b4a1dfb"]); + + const ammo127x55ArrayLL3 = ["5cadf6e5ae921500113bb973", "5cadf6eeae921500134b2799"]; + + const ammo762x54ArrayLL1 = ["5887431f2459777e1612938f"]; + const ammo762x54ArrayLL2 = ammo762x54ArrayLL1.concat(...["5e023cf8186a883be655e54f"]); + const ammo762x54ArrayLL3 = ammo762x54ArrayLL2.concat(...["59e77a2386f7742ee578960a", "560d61e84bdc2da74d8b4571"]); + + const ammo762x51ArrayLL1 = ["5e023e6e34d52a55c3304f71"]; + const ammo762x51ArrayLL2 = ammo762x51ArrayLL1.concat(...["5e023e53d4353e3302577c4c"]); + const ammo762x51ArrayLL3 = ammo762x51ArrayLL2.concat(...["58dd3ad986f77403051cba8f", "5a608bf24f39f98ffc77720e", "5a6086ea4f39f99cd479502f"]); + + const ammo762x39ArrayLL1 = ["5656d7c34bdc2d9d198b4587", "59e4d3d286f774176a36250a"]; + const ammo762x39ArrayLL2 = ammo762x39ArrayLL1.concat(...["59e4cf5286f7741778269d8a"]); + const ammo762x39ArrayLL3 = ammo762x39ArrayLL2.concat(...["59e4d24686f7741776641ac7", "59e0d99486f7744a32234762"]); + + const ammo762x35ArrayLL2 = ["5fbe3ffdf8b6a877a729ea82"]; + const ammo762x35ArrayLL3 = ammo762x35ArrayLL2.concat(...["6196365d58ef8c428c287da1", "619636be6db0f2477964e710"]); + + const ammo762x25TTArrayLL1 = ["5735fdcd2459776445391d61", "5735ff5c245977640e39ba7e", "573601b42459776410737435", "573602322459776445391df1"]; + const ammo762x25TTArrayLL2 = ammo762x25TTArrayLL1.concat(...["5736026a245977644601dc61", "573603c924597764442bd9cb"]); + const ammo762x25TTArrayLL3 = ammo762x25TTArrayLL2.concat(...["573603562459776430731618"]); + + const ammo366TKMArrayLL1 = ["59e6542b86f77411dc52a77a", "59e655cb86f77411dc52a77b"]; + const ammo366TKMArrayLL2 = ammo366TKMArrayLL1.concat(...["59e6658b86f77411d949b250"]); + const ammo366TKMArrayLL3 = ammo366TKMArrayLL2.concat(...["5f0596629e22f464da6bbdd9"]); + + const ammo556x45ArrayLL1 = ["59e6920f86f77411d82aa167", "54527a984bdc2d4e668b4567", "59e68f6f86f7746c9f75e846", "59e6927d86f77411da468256"]; + const ammo556x45ArrayLL2 = ammo556x45ArrayLL1.concat(...["59e6918f86f7746c9f75e849", "59e6906286f7746c9f75e847"]); + const ammo556x45ArrayLL3 = ammo556x45ArrayLL2.concat(...["60194943740c5d77f6705eea", "59e690b686f7746c9f75e848", "5c0d5ae286f7741e46554302"]); + + const ammo545x39ArrayLL1 = ["56dff338d2720bbd668b4569", "56dff4a2d2720bbd668b456a", "56dff3afd2720bba668b4567"]; + const ammo545x39ArrayLL2 = ammo545x39ArrayLL1.concat(...["56dff2ced2720bb4668b4567", "56dff4ecd2720b5f5a8b4568", "56dff421d2720b5f5a8b4567"]); + const ammo545x39ArrayLL3 = ammo545x39ArrayLL2.concat(...["56dfef82d2720bbd668b4567", "56dff061d2720bb5668b4567", "56dff026d2720bb8668b4567", "5c0d5e4486f77478390952fe"]); + + const ammo57x28ArrayLL2 = ["5cc80f8fe4a949033b0224a2"]; + const ammo57x28ArrayLL3 = ammo57x28ArrayLL2.concat(...["5cc80f38e4a949001152b560", "5cc80f53e4a949000e1ea4f8", "5cc80f67e4a949035e43bbba", "5cc80f79e4a949033c7343b2", "5cc86840d7f00c002412c56c"]); + + const ammo46x30ArrayLL1 = ["5ba26812d4351e003201fef1"]; + const ammo46x30ArrayLL2 = ammo46x30ArrayLL1; + const ammo46x30ArrayLL3 = ammo46x30ArrayLL2.concat(...["5ba2678ad4351e44f824b344", "5ba26844d4351e00334c9475"]); + + const ammo9x18ArrayLL1 = ["573719762459775a626ccbc1", "57371e4124597760ff7b25f1", "57371eb62459776125652ac1", "57371f2b24597761224311f1", "5737201124597760fc4431f1", "5737207f24597760ff7b25f2"]; + const ammo9x18ArrayLL2 = ammo9x18ArrayLL1.concat(...["57371b192459775a9f58a5e0"]); + const ammo9x18ArrayLL3 = ammo9x18ArrayLL2.concat(...["573718ba2459775a75491131", "573719df2459775a626ccbc2", "57371aab2459775a77142f22", "573720e02459776143012541", "57372140245977611f70ee91", "5737218f245977612125ba51"]); + + const ammo9x19ArrayLL1 = ["58864a4f2459770fcc257101", "5c3df7d588a4501f290594e5"]; + const ammo9x19ArrayLL2 = ammo9x19ArrayLL1.concat(...["56d59d3ad2720bdb418b4577"]); + const ammo9x19ArrayLL3 = ammo9x19ArrayLL2.concat(...["5c925fa22e221601da359b7b", "5efb0e16aeb21837e749c7ff", "5efb0da7a29a85116f6ea05f"]); + + const ammo9x21ArrayLL2 = ["5a26abfac4a28232980eabff"]; + const ammo9x21ArrayLL3 = ammo9x21ArrayLL2.concat(...["5a269f97c4a282000b151807", "5a26ac06c4a282000c5a90a8"]); + + const ammo9x39ArrayLL2 = ["57a0dfb82459774d3078b56c"]; + const ammo9x39ArrayLL3 = ammo9x39ArrayLL2.concat(...["57a0e5022459774d1673f889", "5c0d688c86f77413ae3407b2", "5c0d668f86f7747ccb7f13b2"]); + + const ammo9x33RArrayLL2 = ["62330b3ed4dc74626d570b95", "62330bfadc5883093563729b", "62330c40bdd19b369e1e53d1"]; + const ammo9x33RArrayLL3 = ammo9x33RArrayLL2.concat(...["62330c18744e5e31df12f516"]); + + const ammo1143x23ACPArrayLL1 = ["5e81f423763d9f754677bf2e"]; + const ammo1143x23ACPArrayLL2 = ammo1143x23ACPArrayLL1.concat(...["5efb0d4f4bc50b58e81710f3"]); + const ammo1143x23ACPArrayLL3 = ammo1143x23ACPArrayLL2.concat(...["5efb0cabfb3e451d70735af5", "5efb0fc6aeb21837e749c801"]); + + const ammo12x70ArrayLL1 = ["560d5e524bdc2d25448b4571", "5d6e6772a4b936088465b17c", "5d6e67fba4b9361bc73bc779", "58820d1224597753c90aeb13", "5d6e6869a4b9361c140bcfde", "5d6e6891a4b9361bd473feea", ]; + const ammo12x70ArrayLL2 = ammo12x70ArrayLL1.concat(...["5d6e6806a4b936088465b17e", "5d6e689ca4b9361bc8618956", "5d6e68e6a4b9361c140bcfe0"]); + const ammo12x70ArrayLL3 = ammo12x70ArrayLL2.concat(...["5d6e68b3a4b9361bca7e50b5", "5d6e68dea4b9361bcc29e659", "5d6e68a8a4b9360b6c0d54e2", "5d6e6911a4b9361bd5780d52", "5d6e68c4a4b9361b93413f79", "5c0d591486f7744c505b416f"]); + + const ammo20x70ArrayLL1 = ["5a38ebd9c4a282000d722a5b", "5d6e695fa4b936359b35d852", "5d6e6a42a4b9364f07165f52", "5d6e6a53a4b9361bd473feec"]; + const ammo20x70ArrayLL2 = ammo20x70ArrayLL1.concat(...["5d6e69b9a4b9361bc8618958", "5d6e69c7a4b9360b6c0d54e4"]); + const ammo20x70ArrayLL3 = ammo20x70ArrayLL2.concat(...["5d6e6a05a4b93618084f58d0", "5d6e6a5fa4b93614ec501745"]); + + const ammo23x75ArrayLL3 = ["5e85a9a6eacf8c039e4e2ac1", "5f647f31b6238e5dd066e196"]; + + + const progressionWhitelistLL1: IBotConfig.Equipment.whitelist.EquipmentFilterDetails = + { + "levelRange": + { + "min": 1, + "max": 15 + }, + "equipment": + { + "FirstPrimaryWeapon": [...primaryWeaponArrayLL1], + "Holster": [...holsterArrayLL1], + "Backpack": [...backpackArrayLL1], + "TacticalVest": [...tacticalVestArrayLL1], + "Earpiece": [...earpieceArrayLL1], + "Headwear": [...headwearArrayLL1], + "ArmorVest": [...armorVestArrayLL1], + "Eyewear": [...eyewearArrayLL1], + "ArmBand": [...armBandArrayLL1], + "FaceCover": [...faceCoverArrayLL1] + }, + "cartridge": + { + "Caliber762x54R": [...ammo762x54ArrayLL1], + "Caliber762x51": [...ammo762x51ArrayLL1], + "Caliber762x39": [...ammo762x39ArrayLL1], + "Caliber762x25TT": [...ammo762x25TTArrayLL1], + "Caliber366TKM": [...ammo366TKMArrayLL1], + "Caliber556x45NATO": [...ammo556x45ArrayLL1], + "Caliber545x39": [...ammo545x39ArrayLL1], + "Caliber46x30": [...ammo46x30ArrayLL1], + "Caliber1143x23ACP": [...ammo1143x23ACPArrayLL1], + "Caliber9x19PARA": [...ammo9x19ArrayLL1], + "Caliber9x18PM": [...ammo9x18ArrayLL1], + "Caliber12g": [...ammo12x70ArrayLL1], + "Caliber20g": [...ammo20x70ArrayLL1] + } + } + + const progressionWhitelistLL2: IBotConfig.Equipment.whitelist.EquipmentFilterDetails = + { + "levelRange": + { + "min": 16, + "max": 25 + }, + "equipment": + { + "FirstPrimaryWeapon": [...primaryWeaponArrayLL2], + "Holster": [...holsterArrayLL2], + "Backpack": [...backpackArrayLL2], + "TacticalVest": [...tacticalVestArrayLL2], + "Earpiece": [...earpieceArrayLL2], + "Headwear": [...headwearArrayLL2], + "ArmorVest": [...armorVestArrayLL2], + "Eyewear": [...eyewearArrayLL2], + "ArmBand": [...armBandArrayLL2], + "FaceCover": [...faceCoverArrayLL2] + }, + "cartridge": + { + "Caliber762x54R": [...ammo762x54ArrayLL2], + "Caliber762x51": [...ammo762x51ArrayLL2], + "Caliber762x39": [...ammo762x39ArrayLL2], + "Caliber762x35": [...ammo762x35ArrayLL2], + "Caliber762x25TT": [...ammo762x25TTArrayLL2], + "Caliber366TKM": [...ammo366TKMArrayLL2], + "Caliber556x45NATO": [...ammo556x45ArrayLL2], + "Caliber545x39": [...ammo545x39ArrayLL2], + "Caliber57x28": [...ammo57x28ArrayLL2], + "Caliber46x30": [...ammo46x30ArrayLL2], + "Caliber1143x23ACP": [...ammo1143x23ACPArrayLL2], + "Caliber9x39": [...ammo9x39ArrayLL2], + "Caliber9x33R": [...ammo9x33RArrayLL2], + "Caliber9x21": [...ammo9x21ArrayLL2], + "Caliber9x19PARA": [...ammo9x19ArrayLL2], + "Caliber9x18PM": [...ammo9x18ArrayLL2], + "Caliber12g": [...ammo12x70ArrayLL2], + "Caliber20g": [...ammo20x70ArrayLL2] + } + } + + + const progressionWhitelistLL3: IBotConfig.Equipment.whitelist.EquipmentFilterDetails = + { + "levelRange": + { + "min": 26, + "max": 36 + }, + "equipment": + { + "FirstPrimaryWeapon": [...primaryWeaponArrayLL3], + "Holster": [...holsterArrayLL3], + "Backpack": [...backpackArrayLL3], + "TacticalVest": [...tacticalVestArrayLL3], + "Earpiece": [...earpieceArrayLL3], + "Headwear": [...headwearArrayLL3], + "ArmorVest": [...armorVestArrayLL3], + "Eyewear": [...eyewearArrayLL3], + "ArmBand": [...armBandArrayLL3], + "FaceCover": [...faceCoverArrayLL3] + }, + "cartridge": + { + "Caliber127x55": [...ammo127x55ArrayLL3], + "Caliber762x54R": [...ammo762x54ArrayLL3], + "Caliber762x51": [...ammo762x51ArrayLL3], + "Caliber762x39": [...ammo762x39ArrayLL3], + "Caliber762x35": [...ammo762x35ArrayLL3], + "Caliber762x25TT": [...ammo762x25TTArrayLL3], + "Caliber366TKM": [...ammo366TKMArrayLL3], + "Caliber556x45NATO": [...ammo556x45ArrayLL3], + "Caliber545x39": [...ammo545x39ArrayLL3], + "Caliber57x28": [...ammo57x28ArrayLL3], + "Caliber46x30": [...ammo46x30ArrayLL3], + "Caliber1143x23ACP": [...ammo1143x23ACPArrayLL3], + "Caliber9x39": [...ammo9x39ArrayLL3], + "Caliber9x33R": [...ammo9x33RArrayLL3], + "Caliber9x21": [...ammo9x21ArrayLL3], + "Caliber9x19PARA": [...ammo9x19ArrayLL3], + "Caliber9x18PM": [...ammo9x18ArrayLL3], + "Caliber12g": [...ammo12x70ArrayLL3], + "Caliber20g": [...ammo20x70ArrayLL3], + "Caliber23x75": [...ammo23x75ArrayLL3] + } + } + + this.botConfig.equipment.pmc.whitelist.push(progressionWhitelistLL1); + this.botConfig.equipment.pmc.whitelist.push(progressionWhitelistLL2); + this.botConfig.equipment.pmc.whitelist.push(progressionWhitelistLL3); + } +} \ No newline at end of file diff --git a/Valens-AIO/src/quests.ts b/Valens-AIO/src/quests.ts index e437f4c..057ee6b 100644 --- a/Valens-AIO/src/quests.ts +++ b/Valens-AIO/src/quests.ts @@ -1,4 +1,4 @@ -import { Logger } from "winston"; +import { Logger } from "./logger"; import { Config } from "../config/config"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; @@ -6,12 +6,12 @@ export class Quests { private modConfig: Config = require("../config/config.json"); private logger: Logger; - private databaseServer: DatabaseServer; + private tables: DatabaseServer; constructor(logger: Logger, databaseServer: DatabaseServer) { this.logger = logger; - this.databaseServer = databaseServer.getTables(); + this.tables = databaseServer.getTables(); } public updateQuests(): void @@ -26,7 +26,7 @@ export class Quests // Updates the weight modifier (as a multiplier) for all items in database/templates/items.json private onlyFoundInRaid(): void { - const quests = this.databaseServer.templates.quests; + const quests = this.tables.templates.quests; for (const questid in quests) { diff --git a/Valens-AIO/src/raid.ts b/Valens-AIO/src/raid.ts index a359f46..368e05d 100644 --- a/Valens-AIO/src/raid.ts +++ b/Valens-AIO/src/raid.ts @@ -1,4 +1,3 @@ -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { IInRaidConfig } from "@spt-aki/models/spt/config/IInRaidConfig"; import { Logger } from "./logger"; @@ -8,7 +7,7 @@ export class Raid { private modConfig: Config = require("../config/config.json") private logger: Logger; - private tables: IDatabaseTables; + private tables: DatabaseServer; private inRaidConfig: IInRaidConfig; constructor(logger:Logger, databaseServer: DatabaseServer, inRaidConfig: IInRaidConfig) diff --git a/Valens-AIO/src/weapons.ts b/Valens-AIO/src/weapons.ts index eaba34a..90532d4 100644 --- a/Valens-AIO/src/weapons.ts +++ b/Valens-AIO/src/weapons.ts @@ -1,4 +1,3 @@ -import { IDatabaseTables } from "@spt-aki/models/spt/server/IDatabaseTables"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { Config } from "../config/config"; import { Logger } from "./logger"; @@ -7,7 +6,7 @@ export class Weapons { private modConfig: Config = require("../config/config.json") private logger: Logger; - private tables: IDatabaseTables; + private tables: DatabaseServer; private mod: any; private weapons: any; diff --git a/Valens-AIO/types/callbacks/NotifierCallbacks.d.ts b/Valens-AIO/types/callbacks/NotifierCallbacks.d.ts index cd1e736..c42058f 100644 --- a/Valens-AIO/types/callbacks/NotifierCallbacks.d.ts +++ b/Valens-AIO/types/callbacks/NotifierCallbacks.d.ts @@ -16,7 +16,7 @@ export declare class NotifierCallbacks { * until we actually have something to send because otherwise we'd spam the client * and the client would abort the connection due to spam. */ - sendNotification(_sessionID: string, req: any, resp: any, _data: any): void; + sendNotification(sessionID: string, req: any, resp: any, data: any): void; getNotifier(url: string, info: any, sessionID: string): IGetBodyResponseData; createNotifierChannel(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData; selectProfile(url: string, info: ISelectProfileRequestData, sessionID: string): IGetBodyResponseData; diff --git a/Valens-AIO/types/controllers/BotController.d.ts b/Valens-AIO/types/controllers/BotController.d.ts index 8782d71..5e6f05d 100644 --- a/Valens-AIO/types/controllers/BotController.d.ts +++ b/Valens-AIO/types/controllers/BotController.d.ts @@ -30,6 +30,6 @@ export declare class BotController { */ getBotDifficulty(type: string, difficulty: string): Difficulty; protected getPmcDifficultySettings(pmcType: "bear" | "usec", difficulty: string): Difficulty; - generate(info: IGenerateBotsRequestData): IBotBase[]; + generate(sessionId: string, info: IGenerateBotsRequestData): IBotBase[]; getBotCap(): number; } diff --git a/Valens-AIO/types/controllers/HideoutController.d.ts b/Valens-AIO/types/controllers/HideoutController.d.ts index b8c1f7c..3eefe1a 100644 --- a/Valens-AIO/types/controllers/HideoutController.d.ts +++ b/Valens-AIO/types/controllers/HideoutController.d.ts @@ -45,13 +45,30 @@ export declare class HideoutController { protected hideoutHelper: HideoutHelper; protected scavCaseRewardGenerator: ScavCaseRewardGenerator; protected configServer: ConfigServer; + protected static nameBackendCountersCrafting: string; protected hideoutConfig: IHideoutConfig; constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, databaseServer: DatabaseServer, randomUtil: RandomUtil, inventoryHelper: InventoryHelper, saveServer: SaveServer, playerService: PlayerService, presetHelper: PresetHelper, paymentHelper: PaymentHelper, itemEventRouter: ItemEventRouter, httpResponse: HttpResponseUtil, profileHelper: ProfileHelper, hideoutHelper: HideoutHelper, scavCaseRewardGenerator: ScavCaseRewardGenerator, configServer: ConfigServer); upgrade(pmcData: IPmcData, body: IHideoutUpgradeRequestData, sessionID: string): IItemEventRouterResponse; upgradeComplete(pmcData: IPmcData, body: HideoutUpgradeCompleteRequestData, sessionID: string): IItemEventRouterResponse; - putItemsInAreaSlots(pmcData: IPmcData, body: IHideoutPutItemInRequestData, sessionID: string): IItemEventRouterResponse; + /** + * Create item in hideout slot item array, remove item from player inventory + * @param pmcData Profile data + * @param addItemToHideoutRequest reqeust from client to place item in area slot + * @param sessionID Session id + * @returns IItemEventRouterResponse object + */ + putItemsInAreaSlots(pmcData: IPmcData, addItemToHideoutRequest: IHideoutPutItemInRequestData, sessionID: string): IItemEventRouterResponse; takeItemsFromAreaSlots(pmcData: IPmcData, body: IHideoutTakeItemOutRequestData, sessionID: string): IItemEventRouterResponse; - protected removeItemFromGenerator(sessionID: string, pmcData: IPmcData, body: IHideoutTakeItemOutRequestData, output: IItemEventRouterResponse, hideoutArea: HideoutArea): IItemEventRouterResponse; + /** + * Find resource item in hideout area, add copy to player inventory, remove Item from hideout slot + * @param sessionID Session id + * @param pmcData Profile to update + * @param removeResourceRequest client request + * @param output response to send to client + * @param hideoutArea Area fuel is being removed from + * @returns IItemEventRouterResponse response + */ + protected removeResourceFromArea(sessionID: string, pmcData: IPmcData, removeResourceRequest: IHideoutTakeItemOutRequestData, output: IItemEventRouterResponse, hideoutArea: HideoutArea): IItemEventRouterResponse; toggleArea(pmcData: IPmcData, body: IHideoutToggleAreaRequestData, sessionID: string): IItemEventRouterResponse; singleProductionStart(pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData, sessionID: string): IItemEventRouterResponse; /** diff --git a/Valens-AIO/types/controllers/InraidController.d.ts b/Valens-AIO/types/controllers/InraidController.d.ts index 8940c97..b899e7d 100644 --- a/Valens-AIO/types/controllers/InraidController.d.ts +++ b/Valens-AIO/types/controllers/InraidController.d.ts @@ -13,9 +13,11 @@ import { DatabaseServer } from "../servers/DatabaseServer"; import { SaveServer } from "../servers/SaveServer"; import { InsuranceService } from "../services/InsuranceService"; import { JsonUtil } from "../utils/JsonUtil"; +import { TimeUtil } from "../utils/TimeUtil"; export declare class InraidController { protected saveServer: SaveServer; protected jsonUtil: JsonUtil; + protected timeUtil: TimeUtil; protected databaseServer: DatabaseServer; protected questHelper: QuestHelper; protected itemHelper: ItemHelper; @@ -27,7 +29,16 @@ export declare class InraidController { protected inRaidHelper: InRaidHelper; protected configServer: ConfigServer; protected inraidConfig: IInRaidConfig; - constructor(saveServer: SaveServer, jsonUtil: JsonUtil, databaseServer: DatabaseServer, questHelper: QuestHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, playerScavGenerator: PlayerScavGenerator, healthHelper: HealthHelper, traderHelper: TraderHelper, insuranceService: InsuranceService, inRaidHelper: InRaidHelper, configServer: ConfigServer); + constructor(saveServer: SaveServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, databaseServer: DatabaseServer, questHelper: QuestHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, playerScavGenerator: PlayerScavGenerator, healthHelper: HealthHelper, traderHelper: TraderHelper, insuranceService: InsuranceService, inRaidHelper: InRaidHelper, configServer: ConfigServer); addPlayer(sessionID: string, info: IRegisterPlayerRequestData): void; saveProgress(offraidData: ISaveProgressRequestData, sessionID: string): void; + /** + * Mark inventory items as FiR if player survived raid, otherwise remove FiR from them + * @param offraidData Save Progress Request + * @param pmcData player profile + * @param isPlayerScav Was the player a pScav + */ + private markOrRemoveFoundInRaidItems; + private handlePostRaidPlayerScavProcess; + private handlePostRaidPlayerScavKarmaChanges; } diff --git a/Valens-AIO/types/controllers/InsuranceController.d.ts b/Valens-AIO/types/controllers/InsuranceController.d.ts index af45442..6895383 100644 --- a/Valens-AIO/types/controllers/InsuranceController.d.ts +++ b/Valens-AIO/types/controllers/InsuranceController.d.ts @@ -41,5 +41,4 @@ export declare class InsuranceController { * @returns response object to send to client */ cost(info: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData; - doAbsolutelyNothing(): void; } diff --git a/Valens-AIO/types/controllers/NoteController.d.ts b/Valens-AIO/types/controllers/NoteController.d.ts index cc78383..ee70541 100644 --- a/Valens-AIO/types/controllers/NoteController.d.ts +++ b/Valens-AIO/types/controllers/NoteController.d.ts @@ -2,11 +2,10 @@ import { IPmcData } from "../models/eft/common/IPmcData"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { INoteActionData } from "../models/eft/notes/INoteActionData"; import { ItemEventRouter } from "../routers/ItemEventRouter"; -declare class NoteController { +export declare class NoteController { protected itemEventRouter: ItemEventRouter; constructor(itemEventRouter: ItemEventRouter); addNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; editNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; deleteNote(pmcData: IPmcData, body: INoteActionData, sessionID: string): IItemEventRouterResponse; } -export { NoteController }; diff --git a/Valens-AIO/types/controllers/RepairController.d.ts b/Valens-AIO/types/controllers/RepairController.d.ts index 330684d..0e78ef6 100644 --- a/Valens-AIO/types/controllers/RepairController.d.ts +++ b/Valens-AIO/types/controllers/RepairController.d.ts @@ -21,7 +21,6 @@ export declare class RepairController { protected repairHelper: RepairHelper; protected configServer: ConfigServer; protected repairConfig: IRepairConfig; - protected readonly WEAPON_SKILL_REPAIR_GAIN: number; constructor(logger: ILogger, itemEventRouter: ItemEventRouter, databaseServer: DatabaseServer, questHelper: QuestHelper, traderHelper: TraderHelper, paymentService: PaymentService, repairHelper: RepairHelper, configServer: ConfigServer); /** * Repair with trader diff --git a/Valens-AIO/types/generators/BotGenerator.d.ts b/Valens-AIO/types/generators/BotGenerator.d.ts index 6e837fa..a5fc0ad 100644 --- a/Valens-AIO/types/generators/BotGenerator.d.ts +++ b/Valens-AIO/types/generators/BotGenerator.d.ts @@ -8,6 +8,7 @@ import { IBotConfig } from "../models/spt/config/IBotConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; import { DatabaseServer } from "../servers/DatabaseServer"; +import { BotEquipmentFilterService } from "../services/BotEquipmentFilterService"; import { HashUtil } from "../utils/HashUtil"; import { JsonUtil } from "../utils/JsonUtil"; import { RandomUtil } from "../utils/RandomUtil"; @@ -26,11 +27,12 @@ export declare class BotGenerator { protected profileHelper: ProfileHelper; protected databaseServer: DatabaseServer; protected botInventoryGenerator: BotInventoryGenerator; + protected botEquipmentFilterService: BotEquipmentFilterService; protected botHelper: BotHelper; protected gameEventHelper: GameEventHelper; protected configServer: ConfigServer; protected botConfig: IBotConfig; - constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, databaseServer: DatabaseServer, botInventoryGenerator: BotInventoryGenerator, botHelper: BotHelper, gameEventHelper: GameEventHelper, configServer: ConfigServer); + constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, databaseServer: DatabaseServer, botInventoryGenerator: BotInventoryGenerator, botEquipmentFilterService: BotEquipmentFilterService, botHelper: BotHelper, gameEventHelper: GameEventHelper, configServer: ConfigServer); /** * Generate a player scav bot object * @param role e.g. assault / pmcbot @@ -39,7 +41,7 @@ export declare class BotGenerator { * @returns */ generatePlayerScav(role: string, difficulty: string, botTemplate: IBotType): IBotBase; - generate(info: IGenerateBotsRequestData): IBotBase[]; + generate(sessionId: string, info: IGenerateBotsRequestData): IBotBase[]; /** * Choose if a bot should become a PMC by checking if bot type is allowed to become a Pmc in botConfig.convertFromChances and doing a random int check * @param botRole the bot role to check if should be a pmc diff --git a/Valens-AIO/types/generators/BotLootGenerator.d.ts b/Valens-AIO/types/generators/BotLootGenerator.d.ts index 9e45529..c6a3f29 100644 --- a/Valens-AIO/types/generators/BotLootGenerator.d.ts +++ b/Valens-AIO/types/generators/BotLootGenerator.d.ts @@ -1,7 +1,7 @@ import { BotGeneratorHelper } from "../helpers/BotGeneratorHelper"; import { HandbookHelper } from "../helpers/HandbookHelper"; import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase"; -import { ItemMinMax, Items } from "../models/eft/common/tables/IBotType"; +import { Chances, Inventory, ItemMinMax, ModsChances } from "../models/eft/common/tables/IBotType"; import { Item } from "../models/eft/common/tables/IItem"; import { ITemplateItem, Props } from "../models/eft/common/tables/ITemplateItem"; import { IBotConfig } from "../models/spt/config/IBotConfig"; @@ -11,6 +11,7 @@ import { DatabaseServer } from "../servers/DatabaseServer"; import { BotLootCacheService } from "../services/BotLootCacheService"; import { HashUtil } from "../utils/HashUtil"; import { RandomUtil } from "../utils/RandomUtil"; +import { BotWeaponGenerator } from "./BotWeaponGenerator"; export declare class BotLootGenerator { protected logger: ILogger; protected hashUtil: HashUtil; @@ -18,11 +19,12 @@ export declare class BotLootGenerator { protected databaseServer: DatabaseServer; protected handbookHelper: HandbookHelper; protected botGeneratorHelper: BotGeneratorHelper; + protected botWeaponGenerator: BotWeaponGenerator; protected botLootCacheService: BotLootCacheService; protected configServer: ConfigServer; protected botConfig: IBotConfig; - constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, handbookHelper: HandbookHelper, botGeneratorHelper: BotGeneratorHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer); - generateLoot(lootPool: Items, itemCounts: ItemMinMax, isPmc: boolean, botRole: string, inventory: PmcInventory): void; + constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, handbookHelper: HandbookHelper, botGeneratorHelper: BotGeneratorHelper, botWeaponGenerator: BotWeaponGenerator, botLootCacheService: BotLootCacheService, configServer: ConfigServer); + generateLoot(templateInventory: Inventory, itemCounts: ItemMinMax, isPmc: boolean, botRole: string, botInventory: PmcInventory, equipmentChances: Chances): void; protected getRandomisedCount(min: number, max: number, nValue: number): number; /** * Take random items from a pool and add to an inventory until totalItemCount or totalValueLimit is reached @@ -36,6 +38,16 @@ export declare class BotLootGenerator { * @param isPmc is the bot being generated for a pmc */ protected addLootFromPool(pool: ITemplateItem[], equipmentSlots: string[], totalItemCount: number, inventoryToAddItemsTo: PmcInventory, botRole: string, useLimits?: boolean, totalValueLimitRub?: number, isPmc?: boolean): void; + /** + * Add generated weapons to inventory as loot + * @param botInventory inventory to add preset to + * @param equipmentSlot slot to place the preset in (backpack) + * @param templateInventory bots template, assault.json + * @param modChances chances for mods to spawn on weapon + * @param botRole bots role, .e.g. pmcBot + * @param isPmc are we generating for a pmc + */ + protected addLooseWeaponsToInventorySlot(botInventory: PmcInventory, equipmentSlot: string, templateInventory: Inventory, modChances: ModsChances, botRole: string, isPmc: boolean): void; /** * Get a random item from the pool parameter using the biasedRandomNumber system * @param pool pool of items to pick an item from diff --git a/Valens-AIO/types/generators/BotWeaponGenerator.d.ts b/Valens-AIO/types/generators/BotWeaponGenerator.d.ts index e9e298b..9215214 100644 --- a/Valens-AIO/types/generators/BotWeaponGenerator.d.ts +++ b/Valens-AIO/types/generators/BotWeaponGenerator.d.ts @@ -6,6 +6,7 @@ import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase" import { Inventory, ModsChances } from "../models/eft/common/tables/IBotType"; import { Item } from "../models/eft/common/tables/IItem"; import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem"; +import { GenerateWeaponResult } from "../models/spt/bots/GenerateWeaponResult"; import { IBotConfig } from "../models/spt/config/IBotConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ConfigServer } from "../servers/ConfigServer"; @@ -26,12 +27,60 @@ export declare class BotWeaponGenerator { protected readonly modMagazineSlotId = "mod_magazine"; protected botConfig: IBotConfig; constructor(jsonUtil: JsonUtil, logger: ILogger, hashUtil: HashUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, weightedRandomHelper: WeightedRandomHelper, botGeneratorHelper: BotGeneratorHelper, randomUtil: RandomUtil, configServer: ConfigServer); - generateWeapon(equipmentSlot: string, templateInventory: Inventory, modChances: ModsChances, magCounts: MinMax, botRole: string, isPmc: boolean, inventory: PmcInventory): void; + /** + * Get a random weapon from a bots pool of weapons (weighted) + * @param equipmentSlot Primary/secondary/holster + * @param botTemplateInventory e.g. assault.json + * @returns weapon tpl + */ + pickWeightedWeaponTplFromPool(equipmentSlot: string, botTemplateInventory: Inventory): string; + /** + * Generated a weapon based on the supplied weapon tpl + * @param weaponTpl weapon tpl to generate (use pickWeightedWeaponTplFromPool()) + * @param equipmentSlot slot to fit into, primary/secondary/holster + * @param botTemplateInventory e.g. assault.json + * @param weaponParentId + * @param modChances + * @param botRole + * @param isPmc + * @returns GenerateWeaponResult object + */ + generateWeaponByTpl(weaponTpl: string, equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean): GenerateWeaponResult; + /** + * Generate an entirely random weapon + * @param equipmentSlot Primary/secondary/holster + * @param botTemplateInventory e.g. assault.json + * @param weaponParentId + * @param modChances + * @param botRole + * @param isPmc + * @returns GenerateWeaponResult object + */ + generateRandomWeapon(equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean): GenerateWeaponResult; + /** + * Create array with weapon base as only element + * Add additional properties as required + * @param weaponTpl + * @param weaponParentId + * @param equipmentSlot + * @param weaponItemTemplate + * @param botRole for durability values + * @returns + */ + constructWeaponBaseArray(weaponTpl: string, weaponParentId: string, equipmentSlot: string, weaponItemTemplate: ITemplateItem, botRole: string): Item[]; + /** + * Add compatible magazines to an inventory based on a generated weapon + * @param weaponDetails + * @param magCounts + * @param inventory + * @param botRole the bot type we're getting generating extra mags for + */ + addExtraMagazinesToInventory(weaponDetails: GenerateWeaponResult, magCounts: MinMax, inventory: PmcInventory, botRole: string): void; /** * Get the mods necessary to kit out a weapon to its preset level * @param weaponTpl weapon to find preset for * @param equipmentSlot the slot the weapon will be placed in - * @param weaponParentId + * @param weaponParentId Value used for the parentid * @returns array of weapon mods */ protected getPresetWeaponMods(weaponTpl: string, equipmentSlot: string, weaponParentId: string, itemTemplate: ITemplateItem, botRole: string): Item[]; @@ -45,9 +94,10 @@ export declare class BotWeaponGenerator { * @param magCounts * @param ammoTpl * @param inventory + * @param botRole the bot type we're getting generating extra mags for * @returns */ - protected generateExtraMagazines(weaponMods: Item[], weaponTemplate: ITemplateItem, magCounts: MinMax, ammoTpl: string, inventory: PmcInventory): void; + protected generateExtraMagazines(weaponMods: Item[], weaponTemplate: ITemplateItem, magCounts: MinMax, ammoTpl: string, inventory: PmcInventory, botRole: string): void; /** * Get a randomised number of bullets for a specific magazine * @param magCounts min and max count of magazines @@ -73,9 +123,10 @@ export declare class BotWeaponGenerator { * Get a weapons magazine tpl from a weapon template * @param weaponMods mods from a weapon template * @param weaponTemplate Weapon to get magazine tpl for + * @param botRole the bot type we are getting the magazine for * @returns magazine tpl string */ - protected getMagazineTplFromWeaponTemplate(weaponMods: Item[], weaponTemplate: ITemplateItem): string; + protected getMagazineTplFromWeaponTemplate(weaponMods: Item[], weaponTemplate: ITemplateItem, botRole: string): string; /** * Get a weapons default magazine template id * @param weaponTemplate weapon to get default magazine for diff --git a/Valens-AIO/types/helpers/BotGeneratorHelper.d.ts b/Valens-AIO/types/helpers/BotGeneratorHelper.d.ts index 413fc10..3cd7256 100644 --- a/Valens-AIO/types/helpers/BotGeneratorHelper.d.ts +++ b/Valens-AIO/types/helpers/BotGeneratorHelper.d.ts @@ -28,20 +28,13 @@ export declare class BotGeneratorHelper { protected configServer: ConfigServer; protected botConfig: IBotConfig; constructor(logger: ILogger, jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, probabilityHelper: ProbabilityHelper, databaseServer: DatabaseServer, durabilityLimitsHelper: DurabilityLimitsHelper, itemHelper: ItemHelper, inventoryHelper: InventoryHelper, containerHelper: ContainerHelper, configServer: ConfigServer); - generateModsForItem(items: Item[], modPool: Mods, parentId: string, parentTemplate: ITemplateItem, modSpawnChances: ModsChances, isPmc?: boolean): Item[]; + generateModsForItem(items: Item[], modPool: Mods, parentId: string, parentTemplate: ITemplateItem, modSpawnChances: ModsChances): Item[]; /** * Is this magazine cylinder related (revolvers and grenade launchers) * @param magazineParentName the name of the magazines parent * @returns true if it is cylinder related */ magazineIsCylinderRelated(magazineParentName: string): boolean; - /** - * Get a list of non black-listed cartridges from the PMC bot config - * @param cartridgesToFilter catridges to filter - * @param itemModPool - * @returns string array of cartridges PMCs can use - */ - getNonBlacklistedPmcCartridges(cartridgesToFilter: string[]): string[]; /** * randomly choose if a mod should be spawned, 100% for required mods OR mod is ammo slot * never return true for an item that has 0% spawn chance diff --git a/Valens-AIO/types/helpers/DialogueHelper.d.ts b/Valens-AIO/types/helpers/DialogueHelper.d.ts index 9776c6a..e3e2bda 100644 --- a/Valens-AIO/types/helpers/DialogueHelper.d.ts +++ b/Valens-AIO/types/helpers/DialogueHelper.d.ts @@ -1,3 +1,4 @@ +import { Item } from "../models/eft/common/tables/IItem"; import { Dialogue, MessageContent, MessagePreview } from "../models/eft/profile/IAkiProfile"; import { MessageType } from "../models/enums/MessageType"; import { DatabaseServer } from "../servers/DatabaseServer"; @@ -15,7 +16,25 @@ export declare class DialogueHelper { protected itemHelper: ItemHelper; constructor(hashUtil: HashUtil, saveServer: SaveServer, databaseServer: DatabaseServer, notifierHelper: NotifierHelper, notificationSendHelper: NotificationSendHelper, itemHelper: ItemHelper); createMessageContext(templateId: string, messageType: MessageType, maxStoreTime: number): MessageContent; + /** + * Add a templated message to the dialogue. + * @param dialogueID + * @param messageContent + * @param sessionID + * @param rewards + */ addDialogueMessage(dialogueID: string, messageContent: MessageContent, sessionID: string, rewards?: any[]): void; + /** + * Get the preview contents of the last message in a dialogue. + * @param dialogue + * @returns + */ getMessagePreview(dialogue: Dialogue): MessagePreview; - getMessageItemContents(messageID: string, sessionID: string): any[]; + /** + * Get the item contents for a particular message. + * @param messageID + * @param sessionID + * @returns + */ + getMessageItemContents(messageID: string, sessionID: string): Item[]; } diff --git a/Valens-AIO/types/helpers/ExtendedProfileHelper.d.ts b/Valens-AIO/types/helpers/ExtendedProfileHelper.d.ts deleted file mode 100644 index c05d88e..0000000 --- a/Valens-AIO/types/helpers/ExtendedProfileHelper.d.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { BotGenerator } from "../generators/BotGenerator"; -import { IPmcData, Skills, Stats } from "../models/eft/common/IPmcData"; -import { DatabaseServer } from "../servers/DatabaseServer"; -import { SaveServer } from "../servers/SaveServer"; -import { BotLootCacheService } from "../services/BotLootCacheService"; -import { FenceService } from "../services/FenceService"; -import { JsonUtil } from "../utils/JsonUtil"; -import { TimeUtil } from "../utils/TimeUtil"; -import { Watermark } from "../utils/Watermark"; -import { ItemHelper } from "./ItemHelper"; -import { ProfileHelper } from "./ProfileHelper"; -/** - * This class needs to exist outside of ProfileHelper to ensure cyclic deps don't cause the server to fail on load - */ -export declare class ExtendedProfileHelper extends ProfileHelper { - protected botLootCacheService: BotLootCacheService; - protected botGenerator: BotGenerator; - constructor(jsonUtil: JsonUtil, watermark: Watermark, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, botLootCacheService: BotLootCacheService, fenceService: FenceService, botGenerator: BotGenerator); - generatePlayerScav(sessionID: string): IPmcData; - protected getScavSkills(sessionID: string): Skills; - protected removeSecureContainer(profile: IPmcData): IPmcData; - protected getDefaultScavSkills(): Skills; - protected getScavStats(sessionID: string): Stats; - protected getScavLevel(sessionID: string): number; - protected getScavExperience(sessionID: string): number; - protected setScavCooldownTimer(profile: IPmcData, pmcData: IPmcData): IPmcData; -} diff --git a/Valens-AIO/types/helpers/GameEventHelper.d.ts b/Valens-AIO/types/helpers/GameEventHelper.d.ts index b2d6377..7613053 100644 --- a/Valens-AIO/types/helpers/GameEventHelper.d.ts +++ b/Valens-AIO/types/helpers/GameEventHelper.d.ts @@ -2,7 +2,7 @@ import { DatabaseServer } from "../servers/DatabaseServer"; export declare class GameEventHelper { protected databaseServer: DatabaseServer; constructor(databaseServer: DatabaseServer); - get EVENT(): Record; + get events(): Record; get christmasEventItems(): string[]; itemIsChristmasRelated(itemId: string): boolean; christmasEventEnabled(): boolean; diff --git a/Valens-AIO/types/helpers/HideoutHelper.d.ts b/Valens-AIO/types/helpers/HideoutHelper.d.ts index 6ac0945..36e4009 100644 --- a/Valens-AIO/types/helpers/HideoutHelper.d.ts +++ b/Valens-AIO/types/helpers/HideoutHelper.d.ts @@ -30,14 +30,10 @@ export declare class HideoutHelper { protected inventoryHelper: InventoryHelper; protected playerService: PlayerService; protected configServer: ConfigServer; - static BITCOIN_FARM: string; - protected WATER_COLLECTOR: string; - protected BITCOIN: string; - protected EXPEDITIONARY_FUEL_TANK: string; - static NAME_BACKENDCOUNTERS_CRAFTING: string; - static SKILL_NAME_HIDEOUT: string; - static HOUR_FOR_SKILL_CRAFTING: number; - static SKILL_NAME_CRAFITING: string; + static bitcoinFarm: string; + static waterCollector: string; + static bitcoin: string; + static expeditionaryFuelTank: string; protected hideoutConfig: IHideoutConfig; constructor(logger: ILogger, hashUtil: HashUtil, timeUtil: TimeUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, itemEventRouter: ItemEventRouter, httpResponse: HttpResponseUtil, profileHelper: ProfileHelper, inventoryHelper: InventoryHelper, playerService: PlayerService, configServer: ConfigServer); registerProduction(pmcData: IPmcData, body: IHideoutSingleProductionStartRequestData | IHideoutContinousProductionStartRequestData, sessionID: string): IItemEventRouterResponse; diff --git a/Valens-AIO/types/helpers/InRaidHelper.d.ts b/Valens-AIO/types/helpers/InRaidHelper.d.ts index b818a48..c3cbfbb 100644 --- a/Valens-AIO/types/helpers/InRaidHelper.d.ts +++ b/Valens-AIO/types/helpers/InRaidHelper.d.ts @@ -16,21 +16,72 @@ export declare class InRaidHelper { protected inventoryHelper: InventoryHelper; protected paymentHelper: PaymentHelper; constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, paymentHelper: PaymentHelper); + /** + * Reset the SPT inraid property stored in a profile to 'none' + * @param sessionID Session id + */ protected removePlayer(sessionID: string): void; + /** + * Some maps have one-time-use keys (e.g. Labs + * Remove the relevant key from an inventory based on the post-raid request data passed in + * @param offraidData post-raid data + * @param sessionID Session id + */ protected removeMapAccessKey(offraidData: ISaveProgressRequestData, sessionID: string): void; + /** + * Check an array of items and add an upd object to money items with a stack count of 1 + * Single stack money items have no upd object and thus no StackObjectsCount, causing issues + * @param items Items array to check + */ addUpdToMoneyFromRaid(items: Item[]): void; /** - * Add positive karma for PMC kills - * @param {*} existingFenceStanding - * @param {*} victims + * Add karma changes up and return the new value + * @param existingFenceStanding Current fence standing level + * @param victims Array of kills player performed + * @returns adjusted karma level after kills are taken into account */ - calculateFenceStandingChangeFromKills(existingFenceStanding: number, victims: Victim[]): void; - setBaseStats(profileData: IPmcData, offraidData: ISaveProgressRequestData, sessionID: string): IPmcData; - markFoundItems(pmcData: IPmcData, profile: IPmcData, isPlayerScav: boolean): IPmcData; - removeFoundInRaidStatusFromItems(profile: IPmcData): IPmcData; - setInventory(sessionID: string, pmcData: IPmcData, profile: IPmcData): IPmcData; + calculateFenceStandingChangeFromKills(existingFenceStanding: number, victims: Victim[]): number; + /** + * Reset a profile to a baseline, used post-raid + * Reset points earned during session property + * Increment exp + * Remove Labs keycard + * @param profileData Profile to update + * @param saveProgressRequest post raid save data request data + * @param sessionID Sessino id + * @returns Reset profile object + */ + updateProfileBaseStats(profileData: IPmcData, saveProgressRequest: ISaveProgressRequestData, sessionID: string): IPmcData; + /** + * Adds SpawnedInSession property to items found in a raid + * Removes SpawnedInSession for non-scav players if item was taken into raid with SpawnedInSession = true + * @param preRaidProfile profile to update + * @param postRaidProfile profile to upate inventory contents of + * @param isPlayerScav Was this a p scav raid + * @returns + */ + addSpawnedInSessionPropertyToItems(preRaidProfile: IPmcData, postRaidProfile: IPmcData, isPlayerScav: boolean): IPmcData; + /** + * Iterate over inventory items and remove the property that defines an item as Found in Raid + * Only removes property if item had FiR when entering raid + * @param postRaidProfile profile to update items for + * @returns Updated profile with SpawnedInSession removed + */ + removeSpawnedInSessionPropertyFromItems(postRaidProfile: IPmcData): IPmcData; + /** + * Update a players inventory post-raid + * Remove equipped items from pre-raid + * Add new items found in raid to profile + * Store insurance items in profile + * @param sessionID + * @param pmcData Profile to update + * @param postRaidProfile Profile returned by client after a raid + * @returns Updated profile + */ + setInventory(sessionID: string, pmcData: IPmcData, postRaidProfile: IPmcData): IPmcData; /** * Clear pmc inventory of all items except those that are exempt + * Used post-raid to remove items after death * @param pmcData Player profile * @param sessionID Session id * @returns Player profile with pmc inventory cleared diff --git a/Valens-AIO/types/helpers/QuestHelper.d.ts b/Valens-AIO/types/helpers/QuestHelper.d.ts index 650929a..0f68cd5 100644 --- a/Valens-AIO/types/helpers/QuestHelper.d.ts +++ b/Valens-AIO/types/helpers/QuestHelper.d.ts @@ -1,9 +1,9 @@ import { IPmcData } from "../models/eft/common/IPmcData"; -import { Quest } from "../models/eft/common/tables/IBotBase"; import { AvailableForConditions, AvailableForProps, IQuest, Reward } from "../models/eft/common/tables/IQuest"; import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse"; import { IAcceptQuestRequestData } from "../models/eft/quests/IAcceptQuestRequestData"; import { ICompleteQuestRequestData } from "../models/eft/quests/ICompleteQuestRequestData"; +import { QuestStatus } from "../models/enums/QuestStatus"; import { IQuestConfig } from "../models/spt/config/IQuestConfig"; import { ILogger } from "../models/spt/utils/ILogger"; import { ItemEventRouter } from "../routers/ItemEventRouter"; @@ -36,8 +36,7 @@ export declare class QuestHelper { protected configServer: ConfigServer; protected questConfig: IQuestConfig; constructor(logger: ILogger, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, itemHelper: ItemHelper, itemEventRouter: ItemEventRouter, databaseServer: DatabaseServer, localeService: LocaleService, ragfairServerHelper: RagfairServerHelper, dialogueHelper: DialogueHelper, profileHelper: ProfileHelper, paymentHelper: PaymentHelper, traderHelper: TraderHelper, configServer: ConfigServer); - static get STATUS(): Record; - questStatus(pmcData: IPmcData, questID: string): string; + questStatus(pmcData: IPmcData, questID: string): QuestStatus; /** * returns true is the condition is satisfied */ @@ -49,11 +48,17 @@ export declare class QuestHelper { * Debug Routine for showing some information on the * quest list in question. */ - dumpQuests(quests: any, label?: any): void; + dumpQuests(quests: any): void; loyaltyRequirementCheck(loyaltyRequirementProperties: AvailableForProps, profile: IPmcData): boolean; protected processReward(reward: Reward): any[]; - getQuestRewardItems(quest: IQuest, state: string): Reward[]; - addQuestToPMCData(pmcData: IPmcData, quest: Quest, newState: string, acceptedQuest: IAcceptQuestRequestData): void; + getQuestRewardItems(quest: IQuest, state: QuestStatus): Reward[]; + /** + * Add quest with new state value to pmc profile + * @param pmcData profile to add quest to + * @param newState state the new quest should be in when added + * @param acceptedQuest Details of quest being added + */ + addQuestToPMCData(pmcData: IPmcData, newState: QuestStatus, acceptedQuest: IAcceptQuestRequestData): void; acceptedUnlocked(acceptedQuestId: string, sessionID: string): IQuest[]; failedUnlocked(failedQuestId: string, sessionID: string): IQuest[]; applyMoneyBoost(quest: IQuest, moneyBoost: number): IQuest; @@ -84,6 +89,13 @@ export declare class QuestHelper { */ getQuestFromDb(questId: string, pmcData: IPmcData): IQuest; getQuestLocaleIdFromDb(messageId: string): string; + /** + * Alter a quests state + Add a record to tis status timers object + * @param pmcData Profile to update + * @param newQuestState new state the qeust should be in + * @param questId id of the quest to alter the status of + */ + updateQuestState(pmcData: IPmcData, newQuestState: QuestStatus, questId: string): void; /** * Give player quest rewards - Skills/exp/trader standing/items/assort unlocks * @param pmcData Player profile @@ -92,7 +104,7 @@ export declare class QuestHelper { * @param sessionID Seession id * @returns array of reward objects */ - applyQuestReward(pmcData: IPmcData, body: ICompleteQuestRequestData, state: string, sessionID: string): Reward[]; + applyQuestReward(pmcData: IPmcData, body: ICompleteQuestRequestData, state: QuestStatus, sessionID: string): Reward[]; /** * Get the intel center bonus a player has * @param pmcData player profile diff --git a/Valens-AIO/types/helpers/RagfairOfferHelper.d.ts b/Valens-AIO/types/helpers/RagfairOfferHelper.d.ts index 5a77e13..8d03bee 100644 --- a/Valens-AIO/types/helpers/RagfairOfferHelper.d.ts +++ b/Valens-AIO/types/helpers/RagfairOfferHelper.d.ts @@ -40,7 +40,7 @@ export declare class RagfairOfferHelper { protected ragfairOfferService: RagfairOfferService; protected localeService: LocaleService; protected configServer: ConfigServer; - protected static TPL_GOODS_SOLD: string; + protected static goodSoldTemplate: string; protected ragfairConfig: IRagfairConfig; protected questConfig: IQuestConfig; constructor(logger: ILogger, timeUtil: TimeUtil, hashUtil: HashUtil, itemEventRouter: ItemEventRouter, databaseServer: DatabaseServer, saveServer: SaveServer, dialogueHelper: DialogueHelper, itemHelper: ItemHelper, paymentHelper: PaymentHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, ragfairServerHelper: RagfairServerHelper, ragfairSortHelper: RagfairSortHelper, ragfairHelper: RagfairHelper, ragfairOfferService: RagfairOfferService, localeService: LocaleService, configServer: ConfigServer); diff --git a/Valens-AIO/types/helpers/RagfairServerHelper.d.ts b/Valens-AIO/types/helpers/RagfairServerHelper.d.ts index a52306b..e4939d1 100644 --- a/Valens-AIO/types/helpers/RagfairServerHelper.d.ts +++ b/Valens-AIO/types/helpers/RagfairServerHelper.d.ts @@ -26,7 +26,7 @@ export declare class RagfairServerHelper { protected configServer: ConfigServer; protected ragfairConfig: IRagfairConfig; protected questConfig: IQuestConfig; - protected static TPL_GOODS_RETURNED: string; + protected static goodsReturnedTemplate: string; constructor(randomUtil: RandomUtil, hashUtil: HashUtil, saveServer: SaveServer, databaseServer: DatabaseServer, profileHelper: ProfileHelper, itemHelper: ItemHelper, localeService: LocaleService, dialogueHelper: DialogueHelper, jsonUtil: JsonUtil, configServer: ConfigServer); /** * Is item valid / on blacklist / quest item diff --git a/Valens-AIO/types/helpers/RepairHelper.d.ts b/Valens-AIO/types/helpers/RepairHelper.d.ts index 545108e..9a3ab29 100644 --- a/Valens-AIO/types/helpers/RepairHelper.d.ts +++ b/Valens-AIO/types/helpers/RepairHelper.d.ts @@ -14,7 +14,7 @@ export declare class RepairHelper { protected configServer: ConfigServer; protected repairConfig: IRepairConfig; constructor(logger: ILogger, jsonUtil: JsonUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, configServer: ConfigServer); - updateItemDurability(itemToRepair: Item, itemToRepairDetails: ITemplateItem, isArmor: boolean, amountToRepair: number, useRepairKit?: boolean): Item; + updateItemDurability(itemToRepair: Item, itemToRepairDetails: ITemplateItem, isArmor: boolean, amountToRepair: number, useRepairKit?: boolean, applyRandomDegradation?: boolean): Item; protected getRandomisedArmorRepairDegredationValue(armorMaterial: string, isRepairKit: boolean, armorMax: number): number; protected getRandomisedWeaponRepairDegredationValue(itemProps: Props, isRepairKit: boolean, armorMax: number): number; isWeaponTemplate(tpl: string): boolean; diff --git a/Valens-AIO/types/models/eft/common/tables/IBotBase.d.ts b/Valens-AIO/types/models/eft/common/tables/IBotBase.d.ts index 3acd540..0ee468e 100644 --- a/Valens-AIO/types/models/eft/common/tables/IBotBase.d.ts +++ b/Valens-AIO/types/models/eft/common/tables/IBotBase.d.ts @@ -1,5 +1,6 @@ import { HideoutAreas } from "../../../enums/HideoutAreas"; import { MemberCategory } from "../../../enums/MemberCategory"; +import { QuestStatus } from "../../../enums/QuestStatus"; import { IRagfairOffer } from "../../ragfair/IRagfairOffer"; import { Item, Upd } from "./IItem"; import { IPmcDataRepeatableQuest } from "./IRepeatableQuests"; @@ -293,7 +294,9 @@ export interface HideoutArea { lastRecipe: string; } export interface HideoutSlot { - item: HideoutItem[]; + /** SPT specific value to keep track of what index this slot is (0,1,2,3 etc) */ + locationIndex: number; + item?: HideoutItem[]; } export interface HideoutItem { _id: string; @@ -318,13 +321,11 @@ export declare enum SurvivorClass { export interface Quest { qid: string; startTime: number; - status: string; - statusTimers?: StatusTimer; + status: QuestStatus; + statusTimers?: Record; + /** SPT specific property */ completedConditions?: string[]; } -export interface StatusTimer { - AvailableForStart?: number; -} export interface TraderInfo { loyaltyLevel: number; salesSum: number; diff --git a/Valens-AIO/types/models/eft/profile/IAkiProfile.d.ts b/Valens-AIO/types/models/eft/profile/IAkiProfile.d.ts index 3e0b319..eaa66c1 100644 --- a/Valens-AIO/types/models/eft/profile/IAkiProfile.d.ts +++ b/Valens-AIO/types/models/eft/profile/IAkiProfile.d.ts @@ -49,16 +49,16 @@ export interface Message { uid: string; type: MessageType; dt: number; - localDateTime: number; UtcDateTime?: number; Member?: IUpdatableChatMember; templateId: string; text?: string; hasRewards: boolean; rewardCollected: boolean; - items: Items; + items: MessageItems; maxStorageTime?: number; systemData?: ISystemData; + profileChangeEvents?: any[]; } export interface MessagePreview { uid: string; @@ -67,7 +67,7 @@ export interface MessagePreview { templateId: string; text?: string; } -export interface Items { +export interface MessageItems { stash?: string; data?: Item[]; } @@ -153,15 +153,11 @@ export interface MessageContent { templateId: string; type: MessageType; maxStorageTime?: number; - systemData?: MessageContentData; + profileChangeEvents?: any[]; + systemData?: ISystemData; } export interface MessageContentRagfair { offerId: string; count: number; handbookId: string; } -export interface MessageContentData { - date: string; - time: string; - location: string; -} diff --git a/Valens-AIO/types/models/enums/AmmoTypes.d.ts b/Valens-AIO/types/models/enums/AmmoTypes.d.ts new file mode 100644 index 0000000..b52ddcf --- /dev/null +++ b/Valens-AIO/types/models/enums/AmmoTypes.d.ts @@ -0,0 +1,208 @@ +export declare enum Grenade { + M386_HE_GRENADE = "5ede475b549eed7c6d5c18fb", + M576_MP_APERS_GRENADE = "5ede475339ee016e8c534742", + M433_HEDP_GRENADE = "5f0c892565703e5c461894e9", + M406_HE_GRENADE = "5ede4739e0350d05467f73e8", + M381_HE_GRENADE = "5ede474b0c226a66f5402622", + M441_HE_GRENADE = "5ede47405b097655935d7d16" +} +export declare enum Ammo762x51 { + M62_TRACER = "5a608bf24f39f98ffc77720e", + M80 = "58dd3ad986f77403051cba8f", + M61 = "5a6086ea4f39f99cd479502f", + BCP_FMJ = "5e023e53d4353e3302577c4c", + ULTRA_NOSLER = "5e023e88277cce2b522ff2b1", + TCW_SP = "5e023e6e34d52a55c3304f71", + M993 = "5efb0c1bd79ff02a1f5e68d9" +} +export declare enum Ammo762x54 { + SNB_GZH = "560d61e84bdc2da74d8b4571", + LPS_GZH = "5887431f2459777e1612938f", + PS_GZH = "59e77a2386f7742ee578960a", + T46M_GZH = "5e023cf8186a883be655e54f", + BT_GZH = "5e023d34e8a400319a28ed44", + BS_GZH = "5e023d48186a883be655e551" +} +export declare enum Ammo338Lapua { + TAC_X = "5fc382b6d6fa9c00c571bbc3", + UCW = "5fc382c1016cce60e8341b20", + AP = "5fc382a9d724d907e2077dab", + FMJ = "5fc275cf85fd526b824a571a" +} +export declare enum Ammo46x30 { + AP_SX = "5ba26835d4351e0035628ff5", + ACTION_SX = "5ba26812d4351e003201fef1", + FMJ_SX = "5ba2678ad4351e44f824b344", + SUBSONIC_SX = "5ba26844d4351e00334c9475" +} +export declare enum Ammo57x28 { + SS198LF = "5cc80f79e4a949033c7343b2", + R37_F = "5cc86832d7f00c000d3a6e6c", + SS190 = "5cc80f38e4a949001152b560", + R37_X = "5cc86840d7f00c002412c56c", + L191 = "5cc80f53e4a949000e1ea4f8", + SS197SR = "5cc80f8fe4a949033b0224a2", + SB193 = "5cc80f67e4a949035e43bbba" +} +export declare enum Ammo762x25 { + FMJ43 = "5735ff5c245977640e39ba7e", + LRN = "573601b42459776410737435", + P_GL = "5736026a245977644601dc61", + PST_GZH = "573603562459776430731618", + LRNPC = "573602322459776445391df1", + AKBS = "5735fdcd2459776445391d61", + PT_GZH = "573603c924597764442bd9cb" +} +export declare enum Ammo9x18 { + PM_SP8_GZH = "5737218f245977612125ba51", + P_GZH = "573719762459775a626ccbc1", + PSTM_GZH = "57371aab2459775a77142f22", + RG028_GZH = "573720e02459776143012541", + BZHT_GZH = "573718ba2459775a75491131", + PM_PSV = "5737207f24597760ff7b25f2", + SP7_GZH = "57372140245977611f70ee91", + PBM_GZH = "573719df2459775a626ccbc2", + PSO_GZH = "57371f8d24597761006c6a81", + PST_GZH = "5737201124597760fc4431f1", + PS_GS_PPO = "57371f2b24597761224311f1", + PRS_GS = "57371eb62459776125652ac1", + PPT_GZH = "57371e4124597760ff7b25f1", + PPE_GZH = "57371b192459775a9f58a5e0" +} +export declare enum Ammo9x19 { + PSO_GZH = "58864a4f2459770fcc257101", + PST_GZH = "56d59d3ad2720bdb418b4577", + GREEN_TRACER = "5c3df7d588a4501f290594e5", + RIP = "5c0d56a986f774449d5de529", + AP_63 = "5c925fa22e221601da359b7b", + LUGER_CCI = "5a3c16fe86f77452b62de32a", + PBP_GZH = "5efb0da7a29a85116f6ea05f", + QUAKEMAKER = "5efb0e16aeb21837e749c7ff" +} +export declare enum Ammo9x21 { + P_GZH = "5a26abfac4a28232980eabff", + PS_GZH = "5a269f97c4a282000b151807", + PE_GZH = "5a26ac06c4a282000c5a90a8", + BT_GZH = "5a26ac0ec4a28200741e1e18" +} +export declare enum Ammo357Mag { + FMJ = "62330b3ed4dc74626d570b95", + HOLLOW_POINT = "62330bfadc5883093563729b", + SOFT_POINT = "62330c40bdd19b369e1e53d1", + JACKET_HP = "62330c18744e5e31df12f516" +} +export declare enum Ammo45ACP { + MATCH_FMJ = "5e81f423763d9f754677bf2e", + HYDRA_SHOK = "5efb0fc6aeb21837e749c801", + LASERMATCH_FMJ = "5efb0d4f4bc50b58e81710f3", + AP = "5efb0cabfb3e451d70735af5", + RIP = "5ea2a8e200685063ec28c05a" +} +export declare enum Ammo545x39 { + PS_GS = "56dff3afd2720bba668b4567", + SP = "56dff421d2720b5f5a8b4567", + PPBS_GS_IGOLNIK = "5c0d5e4486f77478390952fe", + BS_7N40 = "61962b617c6c7b169525f168", + PRS_GS = "56dff338d2720bbd668b4569", + BT_GS = "56dff061d2720bb5668b4567", + US_GS = "56dff4ecd2720b5f5a8b4568", + BP_GS = "56dfef82d2720bbd668b4567", + HP = "56dff216d2720bbd668b4568", + BS_GS = "56dff026d2720bb8668b4567", + T_GS = "56dff4a2d2720bbd668b456a", + PP_GS = "56dff2ced2720bb4668b4567", + FMJ = "56dff0bed2720bb0668b4567" +} +export declare enum Ammo556x45 { + M856 = "59e68f6f86f7746c9f75e846", + MK255_MOD_0_RRLP = "59e6918f86f7746c9f75e849", + M995 = "59e690b686f7746c9f75e848", + M855A1 = "54527ac44bdc2d36668b4567", + M856A1 = "59e6906286f7746c9f75e847", + M855 = "54527a984bdc2d4e668b4567", + HP = "59e6927d86f77411da468256", + FMJ = "59e6920f86f77411d82aa167", + WARMAGEDDON = "5c0d5ae286f7741e46554302", + MK_318_MOD_0_SOST = "60194943740c5d77f6705eea", + SSA_AP = "601949593ae8f707c4608daa" +} +export declare enum Ammo300Blackout { + M62_TRACER = "619636be6db0f2477964e710", + BCP_FMJ = "5fbe3ffdf8b6a877a729ea82", + AP = "5fd20ff893a8961fc660a954", + V_MAX = "6196364158ef8c428c287d9f", + WHISPER = "6196365d58ef8c428c287da1" +} +export declare enum Ammo762x39 { + PS_GZH = "5656d7c34bdc2d9d198b4587", + HP = "59e4d3d286f774176a36250a", + US_GZH = "59e4d24686f7741776641ac7", + T45M1_GZH = "59e4cf5286f7741778269d8a", + BP_GZH = "59e0d99486f7744a32234762", + MAI_AP = "601aa3d2b2bcb34913271e6d" +} +export declare enum Ammo9x39 { + SP5_GS = "57a0dfb82459774d3078b56c", + BP_GS = "5c0d688c86f77413ae3407b2", + SP6_GS = "57a0e5022459774d1673f889", + SPP_GS = "5c0d668f86f7747ccb7f13b2", + PAB9_GS = "61962d879bb3d20b0946d385" +} +export declare enum Ammo366TKM { + FMJ = "59e6542b86f77411dc52a77a", + GEKSA = "59e6658b86f77411d949b250", + EKO = "59e655cb86f77411dc52a77b", + APM = "5f0596629e22f464da6bbdd9" +} +export declare enum Ammo127x55 { + PS12 = "5cadf6ddae9215051e1c23b2", + PS12B = "5cadf6eeae921500134b2799", + PS12A = "5cadf6e5ae921500113bb973" +} +export declare enum Ammo12Gauge { + BUCKSHOT_7MM = "560d5e524bdc2d25448b4571", + MAGNUM_85MM = "5d6e6806a4b936088465b17e", + RIP = "5c0d591486f7744c505b416f", + BMG_SLUG_50CAL = "5d6e68c4a4b9361b93413f79", + BUCKSHOT_525MM = "5d6e6772a4b936088465b17c", + EXPRESS_65MM = "5d6e67fba4b9361bc73bc779", + FLECHETTE = "5d6e6911a4b9361bd5780d52", + FTX_CUSTOM_LITE_SLUG = "5d6e68e6a4b9361c140bcfe0", + AP20_ARMOR_PIERCING_SLUG = "5d6e68a8a4b9360b6c0d54e2", + DUAL_SABOT_SLUG = "5d6e68dea4b9361bcc29e659", + POLEVA_6U_SLUG = "5d6e689ca4b9361bc8618956", + POLEVA_3_SLUG = "5d6e6891a4b9361bd473feea", + GRIZZLY_40_SLUG = "5d6e6869a4b9361c140bcfde", + SUPERFORMANCE_HP_SLUG = "5d6e68d1a4b93622fe60e845", + COPPER_SABOT_PREMIER_HP_SLUG = "5d6e68b3a4b9361bca7e50b5", + LEAD_SLUG = "58820d1224597753c90aeb13" +} +export declare enum Ammo20Gauge { + BUCKSHOT_75MM = "5a38ebd9c4a282000d722a5b", + STAR_SLUG = "5d6e6a05a4b93618084f58d0", + BUCKSHOT_73MM = "5d6e69c7a4b9360b6c0d54e4", + DEVASTATOR_SLUG = "5d6e6a5fa4b93614ec501745", + BUCKSHOT_56MM = "5d6e695fa4b936359b35d852", + POLEVA_6U_SLUG = "5d6e6a42a4b9364f07165f52", + POLEVA_3_SLUG = "5d6e6a53a4b9361bd473feec", + BUCKSHOT_62MM = "5d6e69b9a4b9361bc8618958" +} +export declare enum Ammo23x75 { + SHRAPNEL10_BUCKSHOT = "5e85a9a6eacf8c039e4e2ac1", + SHRAPNEL25_BUCKSHOT = "5f647f31b6238e5dd066e196", + ZVEZDA_FLASHBANG = "5e85a9f4add9fe03027d9bf1", + BARRIKADA_SLUG = "5e85aa1a988a8701445df1f5" +} +export declare enum Ammo30x29 { + VOG_30 = "5d70e500a4b9364de70d38ce" +} +export declare enum Ammo127x108 { + B32 = "5cde8864d7f00c0010373be1", + BZT_44M = "5d2f2ab648f03550091993ca" +} +export declare enum Ammo26x75 { + GREEN_FLARE = "62389aaba63f32501b1b444f", + RED_FLARE = "62389ba9a63f32501b1b4451", + WHITE_FLARE = "62389bc9423ed1685422dc57", + YELLOW_FLARE = "62389be94d5d474bf712e709" +} diff --git a/Valens-AIO/types/models/enums/ContainerTypes.d.ts b/Valens-AIO/types/models/enums/ContainerTypes.d.ts new file mode 100644 index 0000000..e6b330a --- /dev/null +++ b/Valens-AIO/types/models/enums/ContainerTypes.d.ts @@ -0,0 +1,29 @@ +export declare enum CommonContainers { + AMMO_CASE = "5aafbde786f774389d0cbc0f", + DOCUMENTS_CASE = "590c60fc86f77412b13fddcf", + DOGTAG_CASE = "5c093e3486f77430cb02e593", + GRENADE_CASE = "5e2af55f86f7746d4159f07c", + INJECTOR_CASE = "619cbf7d23893217ec30b689", + ITEM_CASE = "59fb042886f7746c5005a7b2", + KEY_TOOL = "59fafd4b86f7745ca07e1232", + KEYCARD_HOLDER = "619cbf9e0a7c3a1a2731940a", + SCAV_JUNKBOX = "5b7c710788a4506dec015957", + MAGAZINE_CASE = "5c127c4486f7745625356c13", + MEDICINE_CASE = "5aafbcd986f7745e590fff23", + MONEY_CASE = "59fb016586f7746d0d4b423a", + HOLODILNICK_THERMAL_BAG = "5c093db286f7740a1b2617e3", + PISTOL_CASE = "567143bf4bdc2d1a0f8b4567", + SICC_ORGANIZATIONAL_POUCH = "5d235bb686f77443f4331278", + SIMPLE_WALLET = "5783c43d2459774bbe137486", + THICC_ITEM_CASE = "5c0a840b86f7742ffa4f2482", + THICC_WEAPON_CASE = "5b6d9ce188a4501afc1b2b25", + WEAPON_CASE = "59fb023c86f7746d0d4b423c", + WZ_WALLET = "60b0f6c058e0b0481a09ad11" +} +export declare enum SecuredContainers { + ALPHA = "544a11ac4bdc2d470e8b456a", + BETA = "5857a8b324597729ab0a0e7d", + EPSILON = "59db794186f77448bc595262", + GAMMA = "5857a8bc2459772bad15db29", + KAPPA = "5c093ca986f7740a1867ab12" +} diff --git a/Valens-AIO/types/models/enums/QuestStatus.d.ts b/Valens-AIO/types/models/enums/QuestStatus.d.ts index 6335c73..ba65933 100644 --- a/Valens-AIO/types/models/enums/QuestStatus.d.ts +++ b/Valens-AIO/types/models/enums/QuestStatus.d.ts @@ -6,5 +6,6 @@ export declare enum QuestStatus { Success = 4, Fail = 5, FailRestartable = 6, - MarkedAsFailed = 7 + MarkedAsFailed = 7, + Expired = 8 } diff --git a/Valens-AIO/types/models/enums/SkillTypes.d.ts b/Valens-AIO/types/models/enums/SkillTypes.d.ts new file mode 100644 index 0000000..4eb90af --- /dev/null +++ b/Valens-AIO/types/models/enums/SkillTypes.d.ts @@ -0,0 +1,52 @@ +export declare enum SkillTypes { + HIDEOUT_MANAGEMENT = "HideoutManagement", + CRAFTING = "Crafting", + METABOLISM = "Metabolism", + IMMUNITY = "Immunity", + ENDURANCE = "Endurance", + STRENGTH = "Strength", + VITALITY = "Vitality", + HEALTH = "Health", + STRESS_RESISTANCE = "StressResistance", + THROWING = "Throwing", + RECOIL_CONTROL = "RecoilControl", + COVERT_MOVEMENT = "CovertMovement", + FIELD_MEDICINE = "FieldMedicine", + SEARCH = "Search", + SNIPING = "Sniping", + PERCEPTION = "Perception", + INTELLECT = "Intellect", + ATTENTION = "Attention", + CHARISMA = "Charisma", + MEMORY = "Memory", + SURGERY = "Surgery", + AIM_DRILLS = "AimDrills", + TROUBLESHOOTING = "TroubleShooting", + PRONE_MOVEMENT = "ProneMovement", + FIRST_AID = "FirstAid", + LIGHT_VESTS = "LightVests", + HEAVY_VESTS = "HeavyVests", + WEAPON_MODDING = "WeaponModding", + ADVANCED_MODDING = "AdvancedModding", + NIGHT_OPS = "NightOps", + SILENT_OPS = "SilentOps", + LOCKPICKING = "Lockpicking", + WEAPON_TREATMENT = "WeaponTreatment", + MAG_DRILLS = "MagDrills", + FREE_TRADING = "Freetrading", + AUCTIONS = "Auctions", + CLEAN_OPS = "Cleanoperations", + BARTER = "Barter", + SHADOW_CONNECTIONS = "Shadowconnections", + TASK_PERFORMANCE = "Taskperformance", + BEAR_ASSAULT_OPS = "BearAssaultoperations", + BEAR_AUTHORITY = "BearAuthority", + BEAR_AK_SYSTEMS = "BearAksystems", + BEAR_HEAVY_CAL = "BearHeavycaliber", + BEAR_RAW_POWER = "BearRawpower", + USEC_AR_SYSTEMS = "UsecArsystems", + USEC_DEEP_WEAPON_MOD = "UsecDeepweaponmodding_Settings", + USEC_LONG_RANGE_OPTICS = "UsecLongrangeoptics_Settings", + USEC_NEGOTIATIONS = "UsecNegotiations", + USEC_TACTICS = "UsecTactics" +} diff --git a/Valens-AIO/types/models/enums/WeaponSkillTypes.d.ts b/Valens-AIO/types/models/enums/WeaponSkillTypes.d.ts new file mode 100644 index 0000000..1e20a2d --- /dev/null +++ b/Valens-AIO/types/models/enums/WeaponSkillTypes.d.ts @@ -0,0 +1,14 @@ +export declare enum WeaponSkillTypes { + PISTOL = "Pistol", + REVOLVER = "Revolver", + SMG = "SMG", + ASSAULT = "Assault", + SHOTGUN = "Shotgun", + SNIPER = "Sniper", + LMG = "LMG", + HMG = "HMG", + DMR = "DMR", + LAUNCHER = "Launcher", + ATTACHED_LAUNCHER = "AttachedLauncher", + MELEE = "Melee" +} diff --git a/Valens-AIO/types/models/spt/bots/GenerateWeaponResult.d.ts b/Valens-AIO/types/models/spt/bots/GenerateWeaponResult.d.ts new file mode 100644 index 0000000..f099752 --- /dev/null +++ b/Valens-AIO/types/models/spt/bots/GenerateWeaponResult.d.ts @@ -0,0 +1,9 @@ +import { Mods } from "../../eft/common/tables/IBotType"; +import { Item } from "../../eft/common/tables/IItem"; +import { ITemplateItem } from "../../eft/common/tables/ITemplateItem"; +export declare class GenerateWeaponResult { + weapon: Item[]; + chosenAmmo: string; + weaponMods: Mods; + weaponTemplate: ITemplateItem; +} diff --git a/Valens-AIO/types/models/spt/config/IBotConfig.d.ts b/Valens-AIO/types/models/spt/config/IBotConfig.d.ts index 82f77b4..e171087 100644 --- a/Valens-AIO/types/models/spt/config/IBotConfig.d.ts +++ b/Valens-AIO/types/models/spt/config/IBotConfig.d.ts @@ -9,6 +9,7 @@ export interface IBotConfig extends IBaseConfig { revenge: Record; pmc: PmcConfig; itemSpawnLimits: Record>; + equipment: Record; showTypeInNickname: boolean; maxBotCap: number; secureContainerAmmoStackCount: number; @@ -94,8 +95,9 @@ export interface LootNvalue { } export interface PmcConfig { dynamicLoot: PmcDynamicLoot; - cartridgeBlacklist: string[]; difficulty: string; + looseWeaponInBackpackChancePercent: number; + looseWeaponInBackpackLootMinMax: MinMax; isUsec: number; chanceSameSideIsHostilePercent: number; usecType: string; @@ -103,7 +105,7 @@ export interface PmcConfig { maxBackpackLootTotalRub: number; maxPocketLootTotalRub: number; maxVestLootTotalRub: number; - convertFromChances: Record; + convertIntoPmcChance: Record; enemyTypes: string[]; } export interface PmcDynamicLoot { @@ -111,3 +113,12 @@ export interface PmcDynamicLoot { blacklist: string[]; moneyStackLimits: Record; } +export interface Equipment { + blacklist: EquipmentFilterDetails[]; + whitelist: EquipmentFilterDetails[]; +} +export interface EquipmentFilterDetails { + levelRange: MinMax; + equipment: Record; + cartridge: Record; +} diff --git a/Valens-AIO/types/models/spt/config/IHideoutConfig.d.ts b/Valens-AIO/types/models/spt/config/IHideoutConfig.d.ts index cf17871..36d6246 100644 --- a/Valens-AIO/types/models/spt/config/IHideoutConfig.d.ts +++ b/Valens-AIO/types/models/spt/config/IHideoutConfig.d.ts @@ -3,4 +3,5 @@ export interface IHideoutConfig extends IBaseConfig { kind: "aki-hideout"; runIntervalSeconds: number; fuelDrainRateMultipler: number; + hoursForSkillCrafting: number; } diff --git a/Valens-AIO/types/models/spt/config/IInsuranceConfig.d.ts b/Valens-AIO/types/models/spt/config/IInsuranceConfig.d.ts index 6e9c744..b27e753 100644 --- a/Valens-AIO/types/models/spt/config/IInsuranceConfig.d.ts +++ b/Valens-AIO/types/models/spt/config/IInsuranceConfig.d.ts @@ -3,5 +3,7 @@ export interface IInsuranceConfig extends IBaseConfig { kind: "aki-insurance"; insuranceMultiplier: Record; returnChancePercent: Record; + blacklistedEquipment: string[]; + slotIdsWithChanceOfNotReturning: string[]; runIntervalSeconds: number; } diff --git a/Valens-AIO/types/models/spt/config/IRepairConfig.d.ts b/Valens-AIO/types/models/spt/config/IRepairConfig.d.ts index 4966eb5..23e6838 100644 --- a/Valens-AIO/types/models/spt/config/IRepairConfig.d.ts +++ b/Valens-AIO/types/models/spt/config/IRepairConfig.d.ts @@ -2,4 +2,6 @@ import { IBaseConfig } from "./IBaseConfig"; export interface IRepairConfig extends IBaseConfig { kind: "aki-repair"; priceMultiplier: number; + applyRandomizeDurabilityLoss: boolean; + weaponSkillRepairGain: number; } diff --git a/Valens-AIO/types/models/spt/mod/NewItemDetails.d.ts b/Valens-AIO/types/models/spt/mod/NewItemDetails.d.ts new file mode 100644 index 0000000..fc69a06 --- /dev/null +++ b/Valens-AIO/types/models/spt/mod/NewItemDetails.d.ts @@ -0,0 +1,39 @@ +import { ITemplateItem, Props } from "../../eft/common/tables/ITemplateItem"; +export declare abstract class NewItemDetailsBase { + /** Price of the item on flea market */ + fleaPriceRoubles: number; + /** Price of the item in the handbook */ + handbookPriceRoubles: number; + /** + * A dictionary for locale settings, key = langauge (e.g. en,cn,es-mx,jp,fr) + * If a language is not included, the first item in the array will be used in its place + */ + locales: Record; +} +export declare class NewItemFromCloneDetails extends NewItemDetailsBase { + /** Id of the item to copy and use as a base */ + itemTplToClone: string; + /** Item properties that should be applied over the top of the cloned base */ + overrideProperties: Props; + /** ParentId for the new item (item type) */ + parentId: string; + /** + * the id the new item should have, leave blank to have one generated for you + * This is often known as the TplId, or TemplateId + */ + newId: string; +} +export declare class NewItemDetails extends NewItemDetailsBase { + newItem: ITemplateItem; +} +export declare class LocaleDetails { + name: string; + shortName: string; + description: string; +} +export declare class CreateItemResult { + constructor(); + success: boolean; + itemId: string; + errors: string[]; +} diff --git a/Valens-AIO/types/services/BotEquipmentFilterService.d.ts b/Valens-AIO/types/services/BotEquipmentFilterService.d.ts new file mode 100644 index 0000000..e49645b --- /dev/null +++ b/Valens-AIO/types/services/BotEquipmentFilterService.d.ts @@ -0,0 +1,50 @@ +import { IBotType } from "../models/eft/common/tables/IBotType"; +import { Equipment, EquipmentFilterDetails, IBotConfig } from "../models/spt/config/IBotConfig"; +import { ILogger } from "../models/spt/utils/ILogger"; +import { ConfigServer } from "../servers/ConfigServer"; +export declare class BotEquipmentFilterService { + protected logger: ILogger; + protected configServer: ConfigServer; + protected botConfig: IBotConfig; + protected botEquipmentFilterlists: Record; + constructor(logger: ILogger, configServer: ConfigServer); + /** + * Filter a bots data to exclude equipment and cartridges defines in the botConfig + * @param baseBotNode bots json data to filter + * @param playerLevel Level of the currently playing player + * @param isPmc Is the bot we're filtering a PMC + * @param role Role of the bot we're filtering + */ + filterBotEquipment(baseBotNode: IBotType, playerLevel: number, isPmc: boolean, role: string): void; + /** + * Get an object that contains equipment and cartridge blacklists for a specified bot type + * @param botRole Role of the bot we want the blacklist for + * @param playerLevel Level of the player + * @returns EquipmentBlacklistDetails object + */ + protected getBotEquipmentBlacklist(botRole: string, playerLevel: number): EquipmentFilterDetails; + /** + * Get the whitelist for a specific bot type that's within the players level + * @param botRole Bot type + * @param playerLevel Players level + * @returns EquipmentFilterDetails object + */ + protected getBotEquipmentWhitelist(botRole: string, playerLevel: number): EquipmentFilterDetails; + /** + * Filter bot equipment based on blacklist and whitelist from config/bot.json + * Prioritises whitelist first, if one is found blacklist is ignored + * @param baseBotNode bot .json file to update + * @param blacklist equipment blacklist + * @returns Filtered bot file + */ + protected filterEquipment(baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails): void; + /** + * Filter bot cartridges based on blacklist and whitelist from config/bot.json + * Prioritises whitelist first, if one is found blacklist is ignored + * @param baseBotNode bot .json file to update + * @param blacklist equipment on this list should be excluded from the bot + * @param whitelist equipment on this list should be used exclusivly + * @returns Filtered bot file + */ + protected filterCartridges(baseBotNode: IBotType, blacklist: EquipmentFilterDetails, whitelist: EquipmentFilterDetails): void; +} diff --git a/Valens-AIO/types/services/InsuranceService.d.ts b/Valens-AIO/types/services/InsuranceService.d.ts index 0219816..171bf10 100644 --- a/Valens-AIO/types/services/InsuranceService.d.ts +++ b/Valens-AIO/types/services/InsuranceService.d.ts @@ -22,7 +22,6 @@ export declare class InsuranceService { protected dialogueHelper: DialogueHelper; protected configServer: ConfigServer; protected insured: Record>; - protected templatesById: {}; protected insuranceConfig: IInsuranceConfig; constructor(logger: ILogger, databaseServer: DatabaseServer, secureContainerHelper: SecureContainerHelper, randomUtil: RandomUtil, timeUtil: TimeUtil, saveServer: SaveServer, traderHelper: TraderHelper, dialogueHelper: DialogueHelper, configServer: ConfigServer); insuranceExists(sessionId: string): boolean; @@ -32,9 +31,19 @@ export declare class InsuranceService { resetInsurance(sessionId: string): void; resetInsuranceTraderArray(sessionId: string, traderId: string): void; addInsuranceItemToArray(sessionId: string, traderId: string, itemToAdd: any): void; - getItemPrice(_tpl: string): number; - generateTemplatesById(): void; - sendInsuredItems(pmcData: IPmcData, sessionID: string): void; + /** + * Get the rouble price for an item by templateId + * @param itemTpl item tpl to get handbook price for + * @returns handbook price in roubles, Return 0 if not found + */ + getItemPrice(itemTpl: string): number; + /** + * Sends stored insured items as message to player + * @param pmcData profile to modify + * @param sessionID SessionId of current player + * @param mapId Id of the map player died/exited that caused the insurance to be issued on + */ + sendInsuredItems(pmcData: IPmcData, sessionID: string, mapId: string): void; storeLostGear(pmcData: IPmcData, offraidData: ISaveProgressRequestData, preRaidGear: Item[], sessionID: string): void; storeInsuredItemsForReturn(pmcData: IPmcData, offraidData: ISaveProgressRequestData, preRaidGear: Item[], sessionID: string): void; protected addGearToSend(pmcData: IPmcData, insuredItem: any, actualItem: any, sessionID: string): any; diff --git a/Valens-AIO/types/services/ProfileFixerService.d.ts b/Valens-AIO/types/services/ProfileFixerService.d.ts index 313a907..ed1dec7 100644 --- a/Valens-AIO/types/services/ProfileFixerService.d.ts +++ b/Valens-AIO/types/services/ProfileFixerService.d.ts @@ -1,6 +1,8 @@ import { IPmcData } from "../models/eft/common/IPmcData"; +import { HideoutSlot } from "../models/eft/common/tables/IBotBase"; import { IPmcDataRepeatableQuest, IRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests"; import { IAkiProfile } from "../models/eft/profile/IAkiProfile"; +import { HideoutAreas } from "../models/enums/HideoutAreas"; import { ILogger } from "../models/spt/utils/ILogger"; import { DatabaseServer } from "../servers/DatabaseServer"; import { Watermark } from "../utils/Watermark"; @@ -29,8 +31,27 @@ export declare class ProfileFixerService { protected getActiveRepeatableQuests(repeatableQuests: IPmcDataRepeatableQuest[]): IRepeatableQuest[]; protected fixNullTraderSalesSums(pmcProfile: IPmcData): void; protected addMissingBonusesProperty(pmcProfile: IPmcData): void; + /** + * Adjust profile quest status and statusTimers object values + * quest.status is numeric e.g. 2 + * quest.statusTimers keys are numeric as strings e.g. "2" + * @param pmcProfile profile to update + */ + protected updateProfileQuestDataValues(pmcProfile: IPmcData): void; protected addMissingRepeatableQuestsProperty(pmcProfile: IPmcData): void; protected addMissingWorkbenchWeaponSkills(pmcProfile: IPmcData): void; + /** + * A new property was added to slot items "locationIndex", if this is missing, the hideout slot item must be removed + * @param pmcProfile Profile to find and remove slots from + */ + protected removeResourcesFromSlotsInHideoutWithoutLocationIndexValue(pmcProfile: IPmcData): void; + /** + * add in objects equal to the number of slots + * @param areaType area to check + * @param pmcProfile profile to update + */ + protected addEmptyObjectsToHideoutAreaSlots(areaType: HideoutAreas, emptyItemCount: number, pmcProfile: IPmcData): void; + protected addObjectsToArray(count: number, slots: HideoutSlot[]): HideoutSlot[]; /** * In 18876 bsg changed the pockets tplid to be one that has 3 additional special slots * @param pmcProfile diff --git a/Valens-AIO/types/services/mod/CustomItemService.d.ts b/Valens-AIO/types/services/mod/CustomItemService.d.ts new file mode 100644 index 0000000..87bda40 --- /dev/null +++ b/Valens-AIO/types/services/mod/CustomItemService.d.ts @@ -0,0 +1,80 @@ +import { ITemplateItem, Props } from "../../models/eft/common/tables/ITemplateItem"; +import { CreateItemResult, LocaleDetails, NewItemDetails, NewItemFromCloneDetails } from "../../models/spt/mod/NewItemDetails"; +import { IDatabaseTables } from "../../models/spt/server/IDatabaseTables"; +import { ILogger } from "../../models/spt/utils/ILogger"; +import { DatabaseServer } from "../../servers/DatabaseServer"; +import { HashUtil } from "../../utils/HashUtil"; +import { JsonUtil } from "../../utils/JsonUtil"; +export declare class CustomItemService { + protected logger: ILogger; + protected hashUtil: HashUtil; + protected jsonUtil: JsonUtil; + protected databaseServer: DatabaseServer; + protected tables: IDatabaseTables; + constructor(logger: ILogger, hashUtil: HashUtil, jsonUtil: JsonUtil, databaseServer: DatabaseServer); + /** + * Create a new item from a cloned item base + * WARNING - If no item id is supplied, an id will be generated, this id will be random every time you add an item and will not be the same on each subsequent server start + * Add to the items db + * Add to the flea market + * Add to the handbook + * Add to the locales + * @param newItemDetails Item details for the new item to be created + * @returns tplId of the new item created + */ + createItemFromClone(newItemDetails: NewItemFromCloneDetails): CreateItemResult; + /** + * Create a new item without using an existing item as a template + * Add to the items db + * Add to the flea market + * Add to the handbook + * Add to the locales + * @param newItemDetails Details on what the item to be created + * @returns CreateItemResult containing the completed items Id + */ + createItem(newItemDetails: NewItemDetails): CreateItemResult; + /** + * If the id provided is an empty string, return a randomly generated guid, otherwise return the newId parameter + * @param newId id supplied to code + * @returns item id + */ + protected getOrGenerateIdForItem(newId: string): string; + /** + * Iterates through supplied properties and updates the cloned items properties with them + * Complex objects cannot have overrides, they must be fully hydrated with values if they are to be used + * @param overrideProperties new properties to apply + * @param itemClone item to update + */ + protected updateBaseItemPropertiesWithOverrides(overrideProperties: Props, itemClone: ITemplateItem): void; + /** + * Addd a new item object to the in-memory representation of items.json + * @param newItemId id of the item to add to items.json + * @param itemToAdd Item to add against the new id + */ + protected addToItemsDb(newItemId: string, itemToAdd: ITemplateItem): void; + /** + * Add a handbook price for an item + * @param newItemId id of the item being added + * @param parentId parent id of the item being added + * @param priceRoubles price of the item being added + */ + protected addToHandbookDb(newItemId: string, parentId: string, priceRoubles: number): void; + /** + * Iterate through the passed in locale data and add to each locale in turn + * If data is not provided for each langauge eft uses, the first object will be used in its place + * e.g. + * en[0] + * fr[1] + * + * No jp provided, so english will be used as a substitute + * @param localeDetails key is language, value are the new locale details + * @param newItemId id of the item being created + */ + protected addToLocaleDbs(localeDetails: Record, newItemId: string): void; + /** + * Add a price to the in-memory representation of prices.json, used to inform the flea of an items price on the market + * @param newItemId id of the new item + * @param fleaPriceRoubles Price of the new item + */ + protected addToFleaPriceDb(newItemId: string, fleaPriceRoubles: number): void; +} diff --git a/Valens-AIO/types/utils/TimeUtil.d.ts b/Valens-AIO/types/utils/TimeUtil.d.ts index 9733be9..eed4e6d 100644 --- a/Valens-AIO/types/utils/TimeUtil.d.ts +++ b/Valens-AIO/types/utils/TimeUtil.d.ts @@ -5,4 +5,14 @@ export declare class TimeUtil { getDate(): string; getTime(): string; getTimestamp(): number; + /** + * mail in eft requires time be in a specific format + * @returns current time in format: 00:00 (hh:mm) + */ + getTimeMailFormat(): string; + /** + * Mail in eft requires date be in a specific format + * @returns current date in format: 00.00.0000 (dd.mm.yyyy) + */ + getDateMailFormat(): string; }