Co-authored-by: Dev <dev@dev.sp-tarkov.com>
Co-authored-by: Refringe <refringe@noreply.dev.sp-tarkov.com>
Reviewed-on: #15
This commit is contained in:
chomp 2023-10-08 21:07:25 +00:00
parent 226107e25c
commit 7907d533ae
3712 changed files with 80700 additions and 12583 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
**/package-lock.json
**/node_modules/
**/dist/
updateTypes.ps1
NewTypes/

View File

@ -1,10 +1,11 @@
# Mod examples for 3.6.0
# Mod examples for v3.7.0
A collection of example mods that perform typical actions in SPT
# Setup
Download and put each folder in user/mods
# Mod upgrade guide
Dive into a specific mod folder and follow the instructions in the `README.md` file.
# Mod Upgrade Guide
Read [Here](https://hub.sp-tarkov.com/doc/entry/51-modding-in-2-4-0/)

View File

@ -0,0 +1,20 @@
/.buildignore
/.DS_Store
/.editorconfig
/.eslintignore
/.eslintrc.json
/.git
/.github
/.gitignore
/.gitlab
/.nvmrc
/.prettierrc
/.vscode
/build.mjs
/dist
/images
/mod.code-workspace
/node_modules
/package-lock.json
/tsconfig.json
/types

View File

@ -25,26 +25,38 @@
"warn",
{
"selector": "default",
"format": ["camelCase"],
"format": [
"camelCase"
],
"leadingUnderscore": "allow"
},
{
"selector": "typeLike",
"format": ["PascalCase"]
"format": [
"PascalCase"
]
},
{
"selector": "objectLiteralProperty",
"format": ["PascalCase", "camelCase"],
"format": [
"PascalCase",
"camelCase"
],
"leadingUnderscore": "allow"
},
{
"selector": "typeProperty",
"format": ["PascalCase", "camelCase"],
"format": [
"PascalCase",
"camelCase"
],
"leadingUnderscore": "allow"
},
{
"selector": "enumMember",
"format": ["UPPER_CASE"]
"format": [
"UPPER_CASE"
]
}
],
"@typescript-eslint/indent": [
@ -71,5 +83,16 @@
"allowArgumentsExplicitlyTypedAsAny": true
}
]
},
"overrides": [
{
"files": [
"*.mjs",
"*.ts"
],
"env": {
"node": true
}
}
]
}

View File

@ -1,64 +1,66 @@
# Welcome to the SPT-AKI Modding Project
This project was created to automate most parts of building and setting up an environment.
This project is designed to streamline the initial setup process for building and creating mods in the SPT-AKI environment. Follow this guide to set up your environment efficiently.
## **NodeJS:**
## **Table of Contents**
- [NodeJS Setup](#nodejs-setup)
- [IDE Setup](#ide-setup)
- [Workspace Configuration](#workspace-configuration)
- [Environment Setup](#environment-setup)
- [Essential Concepts](#essential-concepts)
- [Coding Guidelines](#coding-guidelines)
- [Distribution Guidelines](#distribution-guidelines)
The first step would be to install nodejs on your pc, the version you NEED is **16.17.1**
## **NodeJS Setup**
That version is the one that has been used to test the mod templates and build scripts.
Before you begin, ensure to install NodeJS version `v16.17.1`, which has been tested thoroughly with our mod templates and build scripts. Download it from the [official NodeJS website](https://nodejs.org/).
It can be downloaded from here: https://nodejs.org/dist/v16.17.1/node-v16.17.1-x64.msi
After installation, it's advised to reboot your system.
A system reboot may be needed after install.
## **IDE Setup**
## **IDE:**
For this project, you can work with either [VSCodium](https://vscodium.com/) or [VSCode](https://code.visualstudio.com/). However, we strongly recommend using VSCode, as all development and testing have been carried out using this IDE, ensuring a smoother experience and compatibility with the project setups. Either way, we have a prepared a workspace file to assist you in setting up your environment.
The second step is having an IDE ready. We've setup a VSCodium workspace file to help with this.
## **Workspace Configuration**
You CAN use Visual Studio Code if you so desire, just keep in mind that our devs tests on the mod files was done using VSCode.
With NodeJS and your chosen IDE ready, initiate the `mod.code-workspace` file using your IDE:
You can get VSCode here: https://code.visualstudio.com/
> File -> Open Workspace from File...
## **Workspace:**
Upon project loading, consider installing recommended plugins like the ESLint plugin.
Once you have NodeJS and VSCode/VSCodium ready, open the mod.code-workspace file with VSCode (File->Open Workspace from File...).
## **Environment Setup**
Once the project loads you may be recommended to install the ESLint plugin. This is HIGHLY recommended.
An automated task is available to configure your environment for Typescript utilization:
## **Environment Setup:**
> Terminal -> Run Task... -> Show All Tasks... -> npm: install
There is a task that will automatically setup your environment to use typescript.
Note: Preserve the `node_modules` folder as it contains necessary dependencies for Typescript and other functionalities.
To run it, you just need to go to:
## **Essential Concepts**
> Terminal->Run Task...->Show All Tasks...->npm: install
Prioritize understanding Dependency Injection and Inversion of Control, the architectural principles SPT-AKI adopts. Comprehensive guidelines will be available on the hub upon release.
After running this task, your environment will be ready to start coding.
Some resources to get you started:
- [A quick intro to Dependency Injection](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/)
- [Understanding Inversion of Control (IoC) Principle](https://medium.com/@amitkma/understanding-inversion-of-control-ioc-principle-163b1dc97454)
DO NOT remove the node_modules folder, this is an auto generated directory that has the required dependencies to be able to use typescript and more.
## **Coding Guidelines**
## **IMPORTANT:**
Focus your mod development around the `mod.ts` file. In the `package.json` file, only alter these properties: `"name"`, `"version"`, `"license"`, `"author"`, and `"akiVersion"`.
Before starting to work on your mod, we suggest you read about Dependency Injection and Inversion of Control as this is the adopted architecture SPT-AKI has adopted.
New to Typescript? Find comprehensive documentation on the [official website](https://www.typescriptlang.org/docs/).
It will be difficult to understand some of the problems you may be having if you dont understand the basics of it.
## **Distribution Guidelines**
A guide explaining all the essentials will be available on the hub on release for you to read about.
Automated tasks are set up to bundle all necessary files for your mod to function in SPT-AKI:
## **Coding:**
> Terminal -> Run Task... -> Show All Tasks... -> npm: build
All your work should be centered around the mod.ts file as an entry point.
You can ONLY change the following properties from the package.json file: `"name"`, `"version"`, `"license"`: `"MIT"`, `"author"`, `"akiVersion"`.
The ZIP output, located in the `dist` directory, contains all required files. Ensure all files are included and modify the `.buildignore` file as needed. This ZIP file is your uploadable asset for the hub.
If you have never used typescript before, you can read about it here: https://www.typescriptlang.org/docs/
## **Conclusion**
## **Distributing your mod:**
With this setup, you're ready to begin modding with SPT-AKI. If you run into any trouble be sure to check out the [modding documentation on the hub](https://hub.sp-tarkov.com/doc/lexicon/66-modding/). If you really get stuck feel free to join us in the [#mods-development](https://discord.com/channels/875684761291599922/875803116409323562) official Discord channel.
The project has been set up with an automatic task that will copy and zip ALL required files for your mod to work on SPT-AKI.
To run this task you just need to go to:
> Terminal->Run Task...->Show All Tasks...->npm: build:zip
The output will be a mod.zip file that will appear on the root of the project.
Always verify that all files were included into the zip file.
Build something awesome!

View File

@ -0,0 +1,383 @@
#!/usr/bin/env node
/**
* Build Script
*
* This script automates the build process for server-side SPT mod projects, facilitating the creation of distributable
* mod packages. It performs a series of operations as outlined below:
* - Loads the .buildignore file, which is used to list files that should be ignored during the build process.
* - Loads the package.json to get project details so a descriptive name can be created for the mod package.
* - Creates a distribution directory and a temporary working directory.
* - Copies files to the temporary directory while respecting the .buildignore rules.
* - Creates a zip archive of the project files.
* - Moves the zip file to the root of the distribution directory.
* - Cleans up the temporary directory.
*
* It's typical that this script be customized to suit the needs of each project. For example, the script can be updated
* to perform additional operations, such as moving the mod package to a specific location or uploading it to a server.
* This script is intended to be a starting point for developers to build upon.
*
* Usage:
* - Run this script using npm: `npm run build`
* - Use `npm run buildinfo` for detailed logging.
*
* Note:
* - Ensure that all necessary Node.js modules are installed before running the script: `npm install`
* - The script reads configurations from the `package.json` and `.buildignore` files; ensure they are correctly set up.
*
* @author Refringe
* @version v1.0.0
*/
import fs from "fs-extra";
import os from "os";
import path from "path";
import { fileURLToPath } from "url";
import { dirname } from "path";
import ignore from "ignore";
import archiver from "archiver";
import winston from "winston";
// Get the command line arguments to determine whether to use verbose logging.
const args = process.argv.slice(2);
const verbose = args.includes("--verbose") || args.includes("-v");
// Configure the Winston logger to use colours.
const logColors = {
error: "red",
warn: "yellow",
info: "grey",
success: "green",
};
winston.addColors(logColors);
// Create a logger instance to log build progress. Configure the logger levels to allow for different levels of logging
// based on the verbosity flag, and set the console transport to log messages of the appropriate level.
const logger = winston.createLogger({
levels: {
error: 0,
warn: 1,
success: 2,
info: 3,
},
format: winston.format.combine(
winston.format.colorize(),
winston.format.printf(info => {
return `${info.level}: ${info.message}`;
})
),
transports: [
new winston.transports.Console({
level: verbose ? "info" : "success",
}),
],
});
/**
* The main function orchestrates the build process for creating a distributable mod package. It leverages a series of
* helper functions to perform various tasks such as loading configuration files, setting up directories, copying files
* according to `.buildignore` rules, and creating a ZIP archive of the project files.
*
* Utilizes the Winston logger to provide information on the build status at different stages of the process.
*
* @returns {void}
*/
async function main() {
// Get the current directory where the script is being executed
const currentDir = getCurrentDirectory();
// Defining at this scope because we need to use it in the finally block.
let projectDir;
try {
// Load the .buildignore file to set up an ignore handler for the build process.
const buildIgnorePatterns = await loadBuildIgnoreFile(currentDir);
// Load the package.json file to get project details.
const packageJson = await loadPackageJson(currentDir);
// Create a descriptive name for the mod package.
const projectName = createProjectName(packageJson);
logger.log("success", `Project name created: ${projectName}`);
// Remove the old distribution directory and create a fresh one.
const distDir = await removeOldDistDirectory(currentDir);
logger.log("info", "Distribution directory successfully cleaned.");
// Create a temporary working directory to perform the build operations.
projectDir = await createTemporaryDirectoryWithProjectName(projectName);
logger.log("success", "Temporary working directory successfully created.");
logger.log("info", projectDir);
// Copy files to the temporary directory while respecting the .buildignore rules.
logger.log("info", "Beginning copy operation using .buildignore file...");
await copyFiles(currentDir, projectDir, buildIgnorePatterns);
logger.log("success", "Files successfully copied to temporary directory.");
// Create a zip archive of the project files.
logger.log("info", "Beginning folder compression...");
const zipFilePath = path.join(path.dirname(projectDir), `${projectName}.zip`);
await createZipFile(projectDir, zipFilePath, "user/mods/" + projectName);
logger.log("success", "Archive successfully created.");
logger.log("info", zipFilePath);
// Move the zip file inside of the project directory, within the temporary working directory.
const zipFileInProjectDir = path.join(projectDir, `${projectName}.zip`);
await fs.move(zipFilePath, zipFileInProjectDir);
logger.log("success", "Archive successfully moved.");
logger.log("info", zipFileInProjectDir);
// Move the temporary directory into the distribution directory.
await fs.move(projectDir, distDir);
logger.log("success", "Temporary directory successfully moved into project distribution directory.");
// Log the success message. Write out the path to the mod package.
logger.log("success", "------------------------------------");
logger.log("success", "Build script completed successfully!");
logger.log("success", "Your mod package has been created in the 'dist' directory:");
logger.log("success", `/${path.relative(process.cwd(), path.join(distDir, `${projectName}.zip`))}`);
logger.log("success", "------------------------------------");
if (!verbose) {
logger.log("success", "To see a detailed build log, use `npm run buildinfo`.");
logger.log("success", "------------------------------------");
}
} catch (err) {
// If any of the file operations fail, log the error.
logger.log("error", "An error occurred: " + err);
} finally {
// Clean up the temporary directory, even if the build fails.
if (projectDir) {
try {
await fs.promises.rm(projectDir, { force: true, recursive: true });
logger.log("info", "Cleaned temporary directory.");
} catch (err) {
logger.log("error", "Failed to clean temporary directory: " + err);
}
}
}
}
/**
* Retrieves the current working directory where the script is being executed. This directory is used as a reference
* point for various file operations throughout the build process, ensuring that paths are resolved correctly regardless
* of the location from which the script is invoked.
*
* @returns {string} The absolute path of the current working directory.
*/
function getCurrentDirectory() {
return dirname(fileURLToPath(import.meta.url));
}
/**
* Loads the `.buildignore` file and sets up an ignore handler using the `ignore` module. The `.buildignore` file
* contains a list of patterns describing files and directories that should be ignored during the build process. The
* ignore handler created by this method is used to filter files and directories when copying them to the temporary
* directory, ensuring that only necessary files are included in the final mod package.
*
* @param {string} currentDirectory - The absolute path of the current working directory.
* @returns {Promise<ignore>} A promise that resolves to an ignore handler.
*/
async function loadBuildIgnoreFile(currentDir) {
const buildIgnorePath = path.join(currentDir, ".buildignore");
try {
// Attempt to read the contents of the .buildignore file asynchronously.
const fileContent = await fs.promises.readFile(buildIgnorePath, "utf-8");
// Return a new ignore instance and add the rules from the .buildignore file (split by newlines).
return ignore().add(fileContent.split("\n"));
} catch (err) {
logger.log("warn", "Failed to read .buildignore file. No files or directories will be ignored.");
// Return an empty ignore instance, ensuring the build process can continue.
return ignore();
}
}
/**
* Loads the `package.json` file and returns its content as a JSON object. The `package.json` file contains important
* project details such as the name and version, which are used in later stages of the build process to create a
* descriptive name for the mod package. The method reads the file from the current working directory, ensuring that it
* accurately reflects the current state of the project.
*
* @param {string} currentDirectory - The absolute path of the current working directory.
* @returns {Promise<Object>} A promise that resolves to a JSON object containing the contents of the `package.json`.
*/
async function loadPackageJson(currentDir) {
const packageJsonPath = path.join(currentDir, "package.json");
// Read the contents of the package.json file asynchronously as a UTF-8 string.
const packageJsonContent = await fs.promises.readFile(packageJsonPath, "utf-8");
return JSON.parse(packageJsonContent);
}
/**
* Constructs a descriptive name for the mod package using details from the `package.json` file. The name is created by
* concatenating the project name, version, and a timestamp, resulting in a unique and descriptive file name for each
* build. This name is used as the base name for the temporary working directory and the final ZIP archive, helping to
* identify different versions of the mod package easily.
*
* @param {Object} packageJson - A JSON object containing the contents of the `package.json` file.
* @returns {string} A string representing the constructed project name.
*/
function createProjectName(packageJson) {
// Remove any non-alphanumeric characters from the author and name.
const author = packageJson.author.replace(/\W/g, "");
const name = packageJson.name.replace(/\W/g, "");
const version = packageJson.version;
// Ensure the name is lowercase, as per the package.json specification.
return `${author}-${name}-${version}`.toLowerCase();
}
/**
* Defines the location of the distribution directory where the final mod package will be stored and deletes any
* existing distribution directory to ensure a clean slate for the build process.
*
* @param {string} currentDirectory - The absolute path of the current working directory.
* @returns {Promise<string>} A promise that resolves to the absolute path to the distribution directory.
*/
async function removeOldDistDirectory(projectDir) {
const distPath = path.join(projectDir, "dist");
await fs.remove(distPath);
return distPath;
}
/**
* Creates a temporary working directory using the project name. This directory serves as a staging area where project
* files are gathered before being archived into the final mod package. The method constructs a unique directory path
* by appending the project name to a base temporary directory path, ensuring that each build has its own isolated
* working space. This approach facilitates clean and organized build processes, avoiding potential conflicts with other
* builds.
*
* @param {string} currentDirectory - The absolute path of the current working directory.
* @param {string} projectName - The constructed project name, used to create a unique path for the temporary directory.
* @returns {Promise<string>} A promise that resolves to the absolute path of the newly created temporary directory.
*/
async function createTemporaryDirectoryWithProjectName(projectName) {
// Create a new directory in the system's temporary folder to hold the project files.
const tempDir = await fs.promises.mkdtemp(path.join(os.tmpdir(), "spt-mod-build-"));
// Create a subdirectory within the temporary directory using the project name for this specific build.
const projectDir = path.join(tempDir, projectName);
await fs.ensureDir(projectDir);
return projectDir;
}
/**
* Copies the project files to the temporary directory while respecting the rules defined in the `.buildignore` file.
* The method is recursive, iterating over all files and directories in the source directory and using the ignore
* handler to filter out files and directories that match the patterns defined in the `.buildignore` file. This ensures
* that only the necessary files are included in the final mod package, adhering to the specifications defined by the
* developer in the `.buildignore` file.
*
* The copy operations are delayed and executed in parallel to improve efficiency and reduce the build time. This is
* achieved by creating an array of copy promises and awaiting them all at the end of the function.
*
* @param {string} sourceDirectory - The absolute path of the current working directory.
* @param {string} destinationDirectory - The absolute path of the temporary directory where the files will be copied.
* @param {Ignore} ignoreHandler - The ignore handler created from the `.buildignore` file.
* @returns {Promise<void>} A promise that resolves when all copy operations are completed successfully.
*/
async function copyFiles(srcDir, destDir, ignoreHandler) {
try {
// Read the contents of the source directory to get a list of entries (files and directories).
const entries = await fs.promises.readdir(srcDir, { withFileTypes: true });
// Initialize an array to hold the promises returned by recursive calls to copyFiles and copyFile operations.
const copyOperations = [];
for (const entry of entries) {
// Define the source and destination paths for each entry.
const srcPath = path.join(srcDir, entry.name);
const destPath = path.join(destDir, entry.name);
// Get the relative path of the source file to check against the ignore handler.
const relativePath = path.relative(process.cwd(), srcPath);
// If the ignore handler dictates that this file should be ignored, skip to the next iteration.
if (ignoreHandler.ignores(relativePath)) {
logger.log("info", `Ignored: /${path.relative(process.cwd(), srcPath)}`);
continue;
}
if (entry.isDirectory()) {
// If the entry is a directory, create the corresponding temporary directory and make a recursive call
// to copyFiles to handle copying the contents of the directory.
await fs.ensureDir(destPath);
copyOperations.push(copyFiles(srcPath, destPath, ignoreHandler));
} else {
// If the entry is a file, add a copyFile operation to the copyOperations array and log the event when
// the operation is successful.
copyOperations.push(
fs.copy(srcPath, destPath).then(() => {
logger.log("info", `Copied: /${path.relative(process.cwd(), srcPath)}`);
})
);
}
}
// Await all copy operations to ensure all files and directories are copied before exiting the function.
await Promise.all(copyOperations);
} catch (err) {
// Log an error message if any error occurs during the copy process.
logger.log("error", "Error copying files: " + err);
}
}
/**
* Creates a ZIP archive of the project files located in the temporary directory. The method uses the `archiver` module
* to create a ZIP file, which includes all the files that have been copied to the temporary directory during the build
* process. The ZIP file is named using the project name, helping to identify the contents of the archive easily.
*
* @param {string} directoryPath - The absolute path of the temporary directory containing the project files.
* @param {string} projectName - The constructed project name, used to name the ZIP file.
* @returns {Promise<string>} A promise that resolves to the absolute path of the created ZIP file.
*/
async function createZipFile(directoryToZip, zipFilePath, containerDirName) {
return new Promise((resolve, reject) => {
// Create a write stream to the specified ZIP file path.
const output = fs.createWriteStream(zipFilePath);
// Create a new archiver instance with ZIP format and maximum compression level.
const archive = archiver("zip", {
zlib: { level: 9 },
});
// Set up an event listener for the 'close' event to resolve the promise when the archiver has finalized.
output.on("close", function () {
logger.log("info", "Archiver has finalized. The output and the file descriptor have closed.");
resolve();
});
// Set up an event listener for the 'warning' event to handle warnings appropriately, logging them or rejecting
// the promise based on the error code.
archive.on("warning", function (err) {
if (err.code === "ENOENT") {
logger.log("warn", `Archiver issued a warning: ${err.code} - ${err.message}`);
} else {
reject(err);
}
});
// Set up an event listener for the 'error' event to reject the promise if any error occurs during archiving.
archive.on("error", function (err) {
reject(err);
});
// Pipe archive data to the file.
archive.pipe(output);
// Add the directory to the archive, under the provided directory name.
archive.directory(directoryToZip, containerDirName);
// Finalize the archive, indicating that no more files will be added and triggering the 'close' event once all
// data has been written.
archive.finalize();
});
}
// Engage!
main();

View File

@ -4,20 +4,23 @@
"main": "src/mod.js",
"license": "MIT",
"author": "Chomp",
"akiVersion": "~3.6",
"akiVersion": "~3.7",
"scripts": {
"setup": "npm i",
"build": "node ./packageBuild.ts"
"build": "node ./build.mjs",
"buildinfo": "node ./build.mjs --verbose"
},
"devDependencies": {
"@types/node": "20.4.5",
"@typescript-eslint/eslint-plugin": "6.2.0",
"@typescript-eslint/parser": "6.2.0",
"bestzip": "2.2.1",
"archiver": "^6.0",
"eslint": "8.46.0",
"fs-extra": "11.1.1",
"glob": "10.3.3",
"fs-extra": "^11.1",
"ignore": "^5.2",
"os": "^0.1",
"tsyringe": "4.8.0",
"typescript": "5.1.6"
"typescript": "5.1.6",
"winston": "^3.9"
}
}

View File

@ -1,75 +0,0 @@
#!/usr/bin/env node
// This is a simple script used to build a mod package. The script will copy necessary files to the build directory
// and compress the build directory into a zip file that can be easily shared.
const fs = require("fs-extra");
const glob = require("glob");
const zip = require('bestzip');
const path = require("path");
const minimatch = require('minimatch');
// Load the package.json file to get some information about the package so we can name things appropriately. This is
// atypical, and you would never do this in a production environment, but this script is only used for development so
// it's fine in this case. Some of these values are stored in environment variables, but those differ between node
// versions; the 'author' value is not available after node v14.
const { author, name:packageName, version } = require("./package.json");
// Generate the name of the package, stripping out all non-alphanumeric characters in the 'author' and 'name'.
const modName = `${author.replace(/[^a-z0-9]/gi, "")}-${packageName.replace(/[^a-z0-9]/gi, "")}-${version}`;
console.log(`Generated package name: ${modName}`);
// Delete the old build directory and compressed package file.
fs.rmSync(`${__dirname}/dist`, { force: true, recursive: true });
console.log("Previous build files deleted.");
// Generate a list of files that should not be copied over into the distribution directory. This is a blacklist to ensure
// we always copy over additional files and directories that authors may have added to their project. This may need to be
// expanded upon by the mod author to allow for node modules that are used within the mod; example commented out below.
const ignoreList = [
"node_modules/",
// "node_modules/!(weighted|glob)", // Instead of excluding the entire node_modules directory, allow two node modules.
"src/**/*.js",
"types/",
".git/",
".gitea/",
".eslintignore",
".eslintrc.json",
".gitignore",
".DS_Store",
"packageBuild.ts",
"mod.code-workspace",
"package-lock.json",
"tsconfig.json"
];
const exclude = glob.sync(`{${ignoreList.join(",")}}`, { realpath: true, dot: true });
fs.copySync(__dirname, path.normalize(`${__dirname}/../~${modName}`), {filter: (src) =>
{
const relativePath = path.relative(__dirname, src);
const shouldExclude = exclude.some((pattern) => minimatch(relativePath, pattern));
console.log(`${relativePath} - Excluded: ${shouldExclude}`);
return !shouldExclude;
},});
fs.moveSync(path.normalize(`${__dirname}/../~${modName}`), path.normalize(`${__dirname}/${modName}`), { overwrite: true });
fs.copySync(path.normalize(`${__dirname}/${modName}`), path.normalize(`${__dirname}/dist`));
console.log("Build files copied.");
// Compress the files for easy distribution. The compressed file is saved into the dist directory. When uncompressed we
// need to be sure that it includes a directory that the user can easily copy into their game mods directory.
zip({
source: modName,
destination: `dist/${modName}.zip`,
cwd: __dirname
}).catch(function(err)
{
console.error("A bestzip error has occurred: ", err.stack);
}).then(function()
{
console.log(`Compressed mod package to: /dist/${modName}.zip`);
// Now that we're done with the compression we can delete the temporary build directory.
fs.rmSync(`${__dirname}/${modName}`, { force: true, recursive: true });
console.log("Build successful! your zip file has been created and is ready to be uploaded to hub.sp-tarkov.com/files/");
});

View File

@ -1,4 +1,5 @@
import { GameController } from "../controllers/GameController";
import { OnLoad } from "../di/OnLoad";
import { IEmptyRequestData } from "../models/eft/common/IEmptyRequestData";
import { ICheckVersionResponse } from "../models/eft/game/ICheckVersionResponse";
import { ICurrentGroupResponse } from "../models/eft/game/ICurrentGroupResponse";
@ -15,12 +16,14 @@ import { INullResponseData } from "../models/eft/httpResponse/INullResponseData"
import { SaveServer } from "../servers/SaveServer";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { Watermark } from "../utils/Watermark";
declare class GameCallbacks {
declare class GameCallbacks implements OnLoad {
protected httpResponse: HttpResponseUtil;
protected watermark: Watermark;
protected saveServer: SaveServer;
protected gameController: GameController;
constructor(httpResponse: HttpResponseUtil, watermark: Watermark, saveServer: SaveServer, gameController: GameController);
onLoad(): Promise<void>;
getRoute(): string;
/**
* Handle client/game/version/validate
* @returns INullResponseData

View File

@ -21,8 +21,11 @@ import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRout
export declare class InventoryCallbacks {
protected inventoryController: InventoryController;
constructor(inventoryController: InventoryController);
/** Handle Move event */
moveItem(pmcData: IPmcData, body: IInventoryMoveRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle Remove event */
removeItem(pmcData: IPmcData, body: IInventoryRemoveRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle Split event */
splitItem(pmcData: IPmcData, body: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse;
mergeItem(pmcData: IPmcData, body: IInventoryMergeRequestData, sessionID: string): IItemEventRouterResponse;
transferItem(pmcData: IPmcData, body: IInventoryTransferRequestData, sessionID: string): IItemEventRouterResponse;

View File

@ -24,5 +24,7 @@ declare class LauncherCallbacks {
ping(url: string, info: IEmptyRequestData, sessionID: string): string;
removeProfile(url: string, info: IRemoveProfileData, sessionID: string): string;
getCompatibleTarkovVersion(): string;
getLoadedServerMods(): string;
getServerModsProfileUsed(url: string, info: IEmptyRequestData, sessionId: string): string;
}
export { LauncherCallbacks };

View File

@ -6,11 +6,13 @@ import { INotifierChannel } from "../models/eft/notifier/INotifier";
import { ISelectProfileRequestData } from "../models/eft/notifier/ISelectProfileRequestData";
import { ISelectProfileResponse } from "../models/eft/notifier/ISelectProfileResponse";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { JsonUtil } from "../utils/JsonUtil";
export declare class NotifierCallbacks {
protected httpServerHelper: HttpServerHelper;
protected httpResponse: HttpResponseUtil;
protected jsonUtil: JsonUtil;
protected notifierController: NotifierController;
constructor(httpServerHelper: HttpServerHelper, httpResponse: HttpResponseUtil, notifierController: NotifierController);
constructor(httpServerHelper: HttpServerHelper, httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, notifierController: NotifierController);
/**
* If we don't have anything to send, it's ok to not send anything back
* because notification requests can be long-polling. In fact, we SHOULD wait

View File

@ -4,16 +4,23 @@ import { IPmcData } from "../models/eft/common/IPmcData";
import { IGetBodyResponseData } from "../models/eft/httpResponse/IGetBodyResponseData";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IPresetBuildActionRequestData } from "../models/eft/presetBuild/IPresetBuildActionRequestData";
import { WeaponBuild } from "../models/eft/profile/IAkiProfile";
import { IRemoveBuildRequestData } from "../models/eft/presetBuild/IRemoveBuildRequestData";
import { IUserBuilds } from "../models/eft/profile/IAkiProfile";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
export declare class PresetBuildCallbacks {
protected httpResponse: HttpResponseUtil;
protected presetBuildController: PresetBuildController;
constructor(httpResponse: HttpResponseUtil, presetBuildController: PresetBuildController);
/** Handle client/handbook/builds/my/list */
getHandbookUserlist(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData<WeaponBuild[]>;
/** Handle SaveBuild event */
saveBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveBuild event*/
removeBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
getHandbookUserlist(url: string, info: IEmptyRequestData, sessionID: string): IGetBodyResponseData<IUserBuilds>;
/** Handle SaveWeaponBuild event */
saveWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle removeBuild event*/
removeBuild(pmcData: IPmcData, body: IRemoveBuildRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveWeaponBuild event*/
removeWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SaveEquipmentBuild event */
saveEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveEquipmentBuild event*/
removeEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
}

View File

@ -14,9 +14,11 @@ import { IGetOffersResult } from "../models/eft/ragfair/IGetOffersResult";
import { IRemoveOfferRequestData } from "../models/eft/ragfair/IRemoveOfferRequestData";
import { ISearchRequestData } from "../models/eft/ragfair/ISearchRequestData";
import { ISendRagfairReportRequestData } from "../models/eft/ragfair/ISendRagfairReportRequestData";
import { IStorePlayerOfferTaxAmountRequestData } from "../models/eft/ragfair/IStorePlayerOfferTaxAmountRequestData";
import { IRagfairConfig } from "../models/spt/config/IRagfairConfig";
import { ConfigServer } from "../servers/ConfigServer";
import { RagfairServer } from "../servers/RagfairServer";
import { RagfairTaxService } from "../services/RagfairTaxService";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { JsonUtil } from "../utils/JsonUtil";
/**
@ -27,9 +29,10 @@ export declare class RagfairCallbacks implements OnLoad, OnUpdate {
protected jsonUtil: JsonUtil;
protected ragfairServer: RagfairServer;
protected ragfairController: RagfairController;
protected ragfairTaxService: RagfairTaxService;
protected configServer: ConfigServer;
protected ragfairConfig: IRagfairConfig;
constructor(httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, ragfairServer: RagfairServer, ragfairController: RagfairController, configServer: ConfigServer);
constructor(httpResponse: HttpResponseUtil, jsonUtil: JsonUtil, ragfairServer: RagfairServer, ragfairController: RagfairController, ragfairTaxService: RagfairTaxService, configServer: ConfigServer);
onLoad(): Promise<void>;
getRoute(): string;
onUpdate(timeSinceLastRun: number): Promise<boolean>;
@ -53,4 +56,5 @@ export declare class RagfairCallbacks implements OnLoad, OnUpdate {
getFleaPrices(url: string, request: IEmptyRequestData, sessionID: string): IGetBodyResponseData<Record<string, number>>;
/** Handle client/reports/ragfair/send */
sendReport(url: string, info: ISendRagfairReportRequestData, sessionID: string): INullResponseData;
storePlayerOfferTaxAmount(url: string, request: IStorePlayerOfferTaxAmountRequestData, sessionId: string): INullResponseData;
}

View File

@ -3,6 +3,7 @@ import { IPmcData } from "../models/eft/common/IPmcData";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IProcessBaseTradeRequestData } from "../models/eft/trade/IProcessBaseTradeRequestData";
import { IProcessRagfairTradeRequestData } from "../models/eft/trade/IProcessRagfairTradeRequestData";
import { ISellScavItemsToFenceRequestData } from "../models/eft/trade/ISellScavItemsToFenceRequestData";
export declare class TradeCallbacks {
protected tradeController: TradeController;
constructor(tradeController: TradeController);
@ -12,4 +13,6 @@ export declare class TradeCallbacks {
processTrade(pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RagFairBuyOffer event */
processRagfairTrade(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SellAllFromSavage event */
sellAllFromSavage(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionID: string): IItemEventRouterResponse;
}

View File

@ -8,6 +8,7 @@ import { IBotBase } from "../models/eft/common/tables/IBotBase";
import { IBotCore } from "../models/eft/common/tables/IBotCore";
import { Difficulty } from "../models/eft/common/tables/IBotType";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -29,6 +30,7 @@ export declare class BotController {
protected applicationContext: ApplicationContext;
protected jsonUtil: JsonUtil;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
static readonly pmcTypeLabel = "PMC";
constructor(logger: ILogger, databaseServer: DatabaseServer, botGenerator: BotGenerator, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, botGenerationCacheService: BotGenerationCacheService, matchBotDetailsCacheService: MatchBotDetailsCacheService, localisationService: LocalisationService, profileHelper: ProfileHelper, configServer: ConfigServer, applicationContext: ApplicationContext, jsonUtil: JsonUtil);
/**
@ -70,5 +72,5 @@ export declare class BotController {
* @returns cap number
*/
getBotCap(): number;
getPmcBotTypes(): Record<string, Record<string, Record<string, number>>>;
getAiBotBrainTypes(): any;
}

View File

@ -7,7 +7,9 @@ import { IGetMailDialogViewResponseData } from "../models/eft/dialog/IGetMailDia
import { ISendMessageRequest } from "../models/eft/dialog/ISendMessageRequest";
import { Dialogue, DialogueInfo, IAkiProfile, IUserDialogInfo, Message } from "../models/eft/profile/IAkiProfile";
import { MessageType } from "../models/enums/MessageType";
import { ICoreConfig } from "../models/spt/config/ICoreConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { SaveServer } from "../servers/SaveServer";
import { GiftService } from "../services/GiftService";
import { MailSendService } from "../services/MailSendService";
@ -24,7 +26,9 @@ export declare class DialogueController {
protected mailSendService: MailSendService;
protected giftService: GiftService;
protected hashUtil: HashUtil;
constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, profileHelper: ProfileHelper, randomUtil: RandomUtil, mailSendService: MailSendService, giftService: GiftService, hashUtil: HashUtil);
protected configServer: ConfigServer;
protected coreConfig: ICoreConfig;
constructor(logger: ILogger, saveServer: SaveServer, timeUtil: TimeUtil, dialogueHelper: DialogueHelper, profileHelper: ProfileHelper, randomUtil: RandomUtil, mailSendService: MailSendService, giftService: GiftService, hashUtil: HashUtil, configServer: ConfigServer);
/** Handle onUpdate spt event */
update(): void;
/**

View File

@ -11,21 +11,23 @@ import { IGameConfigResponse } from "../models/eft/game/IGameConfigResponse";
import { IGameKeepAliveResponse } from "../models/eft/game/IGameKeepAliveResponse";
import { IServerDetails } from "../models/eft/game/IServerDetails";
import { IAkiProfile } from "../models/eft/profile/IAkiProfile";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { ICoreConfig } from "../models/spt/config/ICoreConfig";
import { IHttpConfig } from "../models/spt/config/IHttpConfig";
import { ILocationConfig } from "../models/spt/config/ILocationConfig";
import { ILootConfig } from "../models/spt/config/ILootConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { IRagfairConfig } from "../models/spt/config/IRagfairConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { CustomLocationWaveService } from "../services/CustomLocationWaveService";
import { GiftService } from "../services/GiftService";
import { ItemBaseClassService } from "../services/ItemBaseClassService";
import { LocalisationService } from "../services/LocalisationService";
import { OpenZoneService } from "../services/OpenZoneService";
import { ProfileFixerService } from "../services/ProfileFixerService";
import { SeasonalEventService } from "../services/SeasonalEventService";
import { EncodingUtil } from "../utils/EncodingUtil";
import { HashUtil } from "../utils/HashUtil";
import { JsonUtil } from "../utils/JsonUtil";
import { RandomUtil } from "../utils/RandomUtil";
import { TimeUtil } from "../utils/TimeUtil";
@ -34,10 +36,10 @@ export declare class GameController {
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected timeUtil: TimeUtil;
protected hashUtil: HashUtil;
protected preAkiModLoader: PreAkiModLoader;
protected httpServerHelper: HttpServerHelper;
protected randomUtil: RandomUtil;
protected encodingUtil: EncodingUtil;
protected hideoutHelper: HideoutHelper;
protected profileHelper: ProfileHelper;
protected profileFixerService: ProfileFixerService;
@ -45,6 +47,7 @@ export declare class GameController {
protected customLocationWaveService: CustomLocationWaveService;
protected openZoneService: OpenZoneService;
protected seasonalEventService: SeasonalEventService;
protected itemBaseClassService: ItemBaseClassService;
protected giftService: GiftService;
protected applicationContext: ApplicationContext;
protected configServer: ConfigServer;
@ -53,12 +56,23 @@ export declare class GameController {
protected coreConfig: ICoreConfig;
protected locationConfig: ILocationConfig;
protected ragfairConfig: IRagfairConfig;
protected botConfig: IBotConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, encodingUtil: EncodingUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer);
protected pmcConfig: IPmcConfig;
protected lootConfig: ILootConfig;
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, preAkiModLoader: PreAkiModLoader, httpServerHelper: HttpServerHelper, randomUtil: RandomUtil, hideoutHelper: HideoutHelper, profileHelper: ProfileHelper, profileFixerService: ProfileFixerService, localisationService: LocalisationService, customLocationWaveService: CustomLocationWaveService, openZoneService: OpenZoneService, seasonalEventService: SeasonalEventService, itemBaseClassService: ItemBaseClassService, giftService: GiftService, applicationContext: ApplicationContext, configServer: ConfigServer);
load(): void;
/**
* Handle client/game/start
*/
gameStart(_url: string, _info: IEmptyRequestData, sessionID: string, startTimeStampMS: number): void;
protected addCustomLooseLootPositions(): void;
protected adjustLooseLootSpawnProbabilities(): void;
protected setHideoutAreasAndCraftsTo40Secs(): void;
/**
* 3.7.0 moved AIDs to be numeric, old profiles need to be migrated
* We store the old AID value in new field `sessionId`
* @param fullProfile Profile to update
*/
protected fixIncorrectAidValue(fullProfile: IAkiProfile): void;
/** Apply custom limits on bot types as defined in configs/location.json/botTypeLimits */
protected adjustMapBotLimits(): void;
/**

View File

@ -29,34 +29,35 @@ export declare class HealthController {
* stores in-raid player health
* @param pmcData Player profile
* @param info Request data
* @param sessionID
* @param sessionID Player id
* @param addEffects Should effects found be added or removed from profile
* @param deleteExistingEffects Should all prior effects be removed before apply new ones
*/
saveVitality(pmcData: IPmcData, info: ISyncHealthRequestData, sessionID: string, addEffects?: boolean, deleteExistingEffects?: boolean): void;
/**
* When healing in menu
* @param pmcData
* @param body
* @param sessionID
* @returns
* @param pmcData Player profile
* @param request Healing request
* @param sessionID Player id
* @returns IItemEventRouterResponse
*/
offraidHeal(pmcData: IPmcData, body: IOffraidHealRequestData, sessionID: string): IItemEventRouterResponse;
offraidHeal(pmcData: IPmcData, request: IOffraidHealRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Handle Eat event
* Consume food/water outside of a raid
* @param pmcData Player profile
* @param body request Object
* @param request Eat request
* @param sessionID Session id
* @returns IItemEventRouterResponse
*/
offraidEat(pmcData: IPmcData, body: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse;
offraidEat(pmcData: IPmcData, request: IOffraidEatRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Handle RestoreHealth event
* Occurs on post-raid healing page
* @param pmcData player profile
* @param healthTreatmentRequest Request data from client
* @param sessionID Session id
* @returns
* @returns IItemEventRouterResponse
*/
healthTreatment(pmcData: IPmcData, healthTreatmentRequest: IHealthTreatmentRequestData, sessionID: string): IItemEventRouterResponse;
/**
@ -66,12 +67,4 @@ export declare class HealthController {
* @param sessionID
*/
applyWorkoutChanges(pmcData: IPmcData, info: IWorkoutData, sessionId: string): void;
/**
* Iterate over treatment request diff and find effects to remove from player limbs
* @param sessionId
* @param profile Profile to update
* @param treatmentRequest client request
* @param output response to send to client
*/
protected removeEffectsAfterPostRaidHeal(sessionId: string, profile: IPmcData, treatmentRequest: IHealthTreatmentRequestData, output: IItemEventRouterResponse): void;
}

View File

@ -8,6 +8,7 @@ import { IPmcData } from "../models/eft/common/IPmcData";
import { HideoutArea, Product } from "../models/eft/common/tables/IBotBase";
import { HideoutUpgradeCompleteRequestData } from "../models/eft/hideout/HideoutUpgradeCompleteRequestData";
import { IHandleQTEEventRequestData } from "../models/eft/hideout/IHandleQTEEventRequestData";
import { IHideoutArea, Stage } from "../models/eft/hideout/IHideoutArea";
import { IHideoutContinuousProductionStartRequestData } from "../models/eft/hideout/IHideoutContinuousProductionStartRequestData";
import { IHideoutImproveAreaRequestData } from "../models/eft/hideout/IHideoutImproveAreaRequestData";
import { IHideoutProduction } from "../models/eft/hideout/IHideoutProduction";
@ -21,6 +22,7 @@ import { IHideoutUpgradeRequestData } from "../models/eft/hideout/IHideoutUpgrad
import { IQteData } from "../models/eft/hideout/IQteData";
import { IRecordShootingRangePoints } from "../models/eft/hideout/IRecordShootingRangePoints";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { HideoutAreas } from "../models/enums/HideoutAreas";
import { IHideoutConfig } from "../models/spt/config/IHideoutConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { EventOutputHolder } from "../routers/EventOutputHolder";
@ -76,6 +78,37 @@ export declare class HideoutController {
* @returns IItemEventRouterResponse
*/
upgradeComplete(pmcData: IPmcData, request: HideoutUpgradeCompleteRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Upgrade wall status to visible in profile if medstation/water collector are both level 1
* @param pmcData Player profile
*/
protected checkAndUpgradeWall(pmcData: IPmcData): void;
/**
*
* @param pmcData Profile to edit
* @param output Object to send back to client
* @param sessionID Session/player id
* @param profileParentHideoutArea Current hideout area for profile
* @param dbHideoutArea Hideout area being upgraded
* @param hideoutStage Stage hideout area is being upgraded to
*/
protected addContainerImprovementToProfile(output: IItemEventRouterResponse, sessionID: string, pmcData: IPmcData, profileParentHideoutArea: HideoutArea, dbHideoutArea: IHideoutArea, hideoutStage: Stage): void;
/**
* Add an inventory item to profile from a hideout area stage data
* @param pmcData Profile to update
* @param dbHideoutData Hideout area from db being upgraded
* @param hideoutStage Stage area upgraded to
*/
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void;
/**
*
* @param output Objet to send to client
* @param sessionID Session/player id
* @param areaType Hideout area that had stash added
* @param hideoutDbData Hideout area that caused addition of stash
* @param hideoutStage Hideout area upgraded to this
*/
protected addContainerUpgradeToClientOutput(output: IItemEventRouterResponse, sessionID: string, areaType: HideoutAreas, hideoutDbData: IHideoutArea, hideoutStage: Stage): void;
/**
* Handle HideoutPutItemsInAreaSlots
* Create item in hideout slot item array, remove item from player inventory
@ -174,7 +207,7 @@ export declare class HideoutController {
*/
protected handleRecipe(sessionID: string, recipe: IHideoutProduction, pmcData: IPmcData, request: IHideoutTakeProductionRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse;
/**
* Handles giving rewards stored in player profile to player after clicking 'get rewards'
* Handles generating case rewards and sending to player inventory
* @param sessionID Session id
* @param pmcData Player profile
* @param request Get rewards from scavcase craft request

View File

@ -104,10 +104,8 @@ export declare class InraidController {
/**
* 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
*/
protected markOrRemoveFoundInRaidItems(offraidData: ISaveProgressRequestData, pmcData: IPmcData, isPlayerScav: boolean): void;
protected markOrRemoveFoundInRaidItems(offraidData: ISaveProgressRequestData): void;
/**
* Update profile after player completes scav raid
* @param scavData Scav profile

View File

@ -1,12 +1,15 @@
import { DialogueHelper } from "../helpers/DialogueHelper";
import { ItemHelper } from "../helpers/ItemHelper";
import { ProfileHelper } from "../helpers/ProfileHelper";
import { TraderHelper } from "../helpers/TraderHelper";
import { IPmcData } from "../models/eft/common/IPmcData";
import { Item } from "../models/eft/common/tables/IItem";
import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { IGetInsuranceCostRequestData } from "../models/eft/insurance/IGetInsuranceCostRequestData";
import { IGetInsuranceCostResponseData } from "../models/eft/insurance/IGetInsuranceCostResponseData";
import { IInsureRequestData } from "../models/eft/insurance/IInsureRequestData";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { Insurance } from "../models/eft/profile/IAkiProfile";
import { IInsuranceConfig } from "../models/spt/config/IInsuranceConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { EventOutputHolder } from "../routers/EventOutputHolder";
@ -14,6 +17,7 @@ import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { SaveServer } from "../servers/SaveServer";
import { InsuranceService } from "../services/InsuranceService";
import { MailSendService } from "../services/MailSendService";
import { PaymentService } from "../services/PaymentService";
import { RandomUtil } from "../utils/RandomUtil";
import { TimeUtil } from "../utils/TimeUtil";
@ -27,26 +31,134 @@ export declare class InsuranceController {
protected itemHelper: ItemHelper;
protected profileHelper: ProfileHelper;
protected dialogueHelper: DialogueHelper;
protected traderHelper: TraderHelper;
protected paymentService: PaymentService;
protected insuranceService: InsuranceService;
protected mailSendService: MailSendService;
protected configServer: ConfigServer;
protected insuranceConfig: IInsuranceConfig;
constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, paymentService: PaymentService, insuranceService: InsuranceService, configServer: ConfigServer);
constructor(logger: ILogger, randomUtil: RandomUtil, eventOutputHolder: EventOutputHolder, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileHelper: ProfileHelper, dialogueHelper: DialogueHelper, traderHelper: TraderHelper, paymentService: PaymentService, insuranceService: InsuranceService, mailSendService: MailSendService, configServer: ConfigServer);
/**
* Process insurance items prior to being given to player in mail
* Process insurance items of all profiles prior to being given back to the player through the mail service.
*
* @returns void
*/
processReturn(): void;
/**
* Should the passed in item be removed from player inventory
* @param insuredItem Insurued item to roll to lose
* @param traderId Trader the item was insured by
* @param itemsBeingDeleted All items to remove from player
* @returns True if item should be removed
* Process insurance items of a single profile prior to being given back to the player through the mail service.
*
* @returns void
*/
protected itemShouldBeLost(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean;
processReturnByProfile(sessionID: string): void;
/**
* Get all insured items that are ready to be processed in a specific profile.
*
* @param sessionID Session ID of the profile to check.
* @param time The time to check ready status against. Current time by default.
* @returns All insured items that are ready to be processed.
*/
protected filterInsuredItems(sessionID: string, time?: number): Insurance[];
/**
* This method orchestrates the processing of insured items in a profile.
*
* @param insuranceDetails The insured items to process.
* @param sessionID The session ID that should receive the processed items.
* @returns void
*/
protected processInsuredItems(insuranceDetails: Insurance[], sessionID: string): void;
/**
* Build an array of items to delete from the insured items.
*
* This method orchestrates several steps:
* - Filters items based on their presence in the database and their raid moddability.
* - Sorts base and independent child items to consider for deletion.
* - Groups child items by their parent for later evaluation.
* - Evaluates grouped child items to decide which should be deleted, based on their value and a random roll.
*
* @param insured - The insured items to build a removal array from.
* @returns An array of IDs representing items that should be deleted.
*/
protected findItemsToDelete(insured: Insurance): string[];
/**
* Filters an item based on its existence in the database, raid moddability, and slot requirements.
*
* @param item The item to be filtered.
* @param parentItemDbDetails The database details of the parent item, or null if the item has no parent.
* @param itemDbDetails A tuple where the first element is a boolean indicating if the item exists in the database,
* and the second element is the item details if it does.
* @returns true if the item exists in the database and neither of the following conditions are met:
* - The item has the RaidModdable property set to false.
* - The item is attached to a required slot in its parent item.
* Otherwise, returns false.
*/
protected filterByRaidModdability(item: Item, parentItemDbDetails: ITemplateItem | null, itemDbDetails: [boolean, ITemplateItem]): boolean;
/**
* Determines if an item is either a base item or a child item that is not equipped to its parent.
*
* @param item The item to check.
* @returns true if the item is a base or an independent child item, otherwise false.
*/
protected isBaseOrIndependentChild(item: Item): boolean;
/**
* Makes a roll to determine if a given item should be deleted. If the roll is successful, the item's ID is added
* to the `toDelete` array.
*
* @param item The item for which the roll is made.
* @param traderId The ID of the trader to consider in the rollForItemDelete method.
* @param toDelete The array accumulating the IDs of items to be deleted.
* @returns true if the item is marked for deletion, otherwise false.
*/
protected makeRollAndMarkForDeletion(item: Item, traderId: string, toDelete: string[]): boolean;
/**
* Groups child items by their parent IDs in a Map data structure.
*
* @param item The child item to be grouped by its parent.
* @param childrenGroupedByParent The Map that holds arrays of children items grouped by their parent IDs.
* @returns void
*/
protected groupChildrenByParent(item: Item, childrenGroupedByParent: Map<string, Item[]>): void;
/**
* Sorts the array of children items in descending order by their maximum price. For each child, a roll is made to
* determine if it should be deleted. The method then deletes the most valuable children based on the number of
* successful rolls made.
*
* @param children The array of children items to sort and filter.
* @param traderId The ID of the trader to consider in the rollForItemDelete method.
* @param toDelete The array that accumulates the IDs of the items to be deleted.
* @returns void
*/
protected sortAndFilterChildren(children: Item[], traderId: string, toDelete: string[]): void;
/**
* Remove items from the insured items that should not be returned to the player.
*
* @param insured The insured items to process.
* @param toDelete The items that should be deleted.
* @returns void
*/
protected removeItemsFromInsurance(insured: Insurance, toDelete: string[]): void;
/**
* Handle sending the insurance message to the user that potentially contains the valid insurance items.
*
* @param sessionID The session ID that should receive the insurance message.
* @param insurance The context of insurance to use.
* @param noItems Whether or not there are any items to return to the player.
* @returns void
*/
protected sendMail(sessionID: string, insurance: Insurance, noItems: boolean): void;
/**
* Determines whether a valid insured item should be removed from the player's inventory based on a random roll and
* trader-specific return chance.
*
* @param insuredItem The insured item being evaluated for removal.
* @param traderId The ID of the trader who insured the item.
* @param itemsBeingDeleted List of items that are already slated for removal.
* @returns true if the insured item should be removed from inventory, false otherwise.
*/
protected rollForItemDelete(insuredItem: Item, traderId: string, itemsBeingDeleted: string[]): boolean;
/**
* Handle Insure event
* Add insurance to an item
*
* @param pmcData Player profile
* @param body Insurance request
* @param sessionID Session id
@ -56,9 +168,10 @@ export declare class InsuranceController {
/**
* Handle client/insurance/items/list/cost
* Calculate insurance cost
* @param info request object
*
* @param request request object
* @param sessionID session id
* @returns IGetInsuranceCostResponseData object to send to client
*/
cost(info: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData;
cost(request: IGetInsuranceCostRequestData, sessionID: string): IGetInsuranceCostResponseData;
}

View File

@ -76,30 +76,46 @@ export declare class InventoryController {
*/
removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse;
/**
* Handle Remove event
* Implements functionality "Discard" from Main menu (Stash etc.)
* Removes item from PMC Profile
*/
discardItem(pmcData: IPmcData, body: IInventoryRemoveRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Split Item
* spliting 1 item-stack into 2 separate items ...
* spliting 1 stack into 2
* @param pmcData Player profile (unused, getOwnerInventoryItems() gets profile)
* @param request Split request
* @param sessionID Session/player id
* @returns IItemEventRouterResponse
*/
splitItem(pmcData: IPmcData, body: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse;
splitItem(pmcData: IPmcData, request: IInventorySplitRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Merge Item
* merges 2 items into one, deletes item from `body.item` and adding number of stacks into `body.with`
* Fully merge 2 inventory stacks together into one stack (merging where both stacks remain is called 'transfer')
* Deletes item from `body.item` and adding number of stacks into `body.with`
* @param pmcData Player profile (unused, getOwnerInventoryItems() gets profile)
* @param body Merge request
* @param sessionID Player id
* @returns IItemEventRouterResponse
*/
mergeItem(pmcData: IPmcData, body: IInventoryMergeRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Transfer item
* TODO: Adds no data to output to send to client, is this by design?
* TODO: should make use of getOwnerInventoryItems(), stack being transferred may not always be on pmc
* Transfer items from one stack into another while keeping original stack
* Used to take items from scav inventory into stash or to insert ammo into mags (shotgun ones) and reloading weapon by clicking "Reload"
* @param pmcData Player profile
* @param body Transfer request
* @param sessionID Session id
* @returns IItemEventRouterResponse
*/
transferItem(pmcData: IPmcData, body: IInventoryTransferRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Swap Item
* its used for "reload" if you have weapon in hands and magazine is somewhere else in rig or backpack in equipment
* Also used to swap items using quick selection on character screen
*/
swapItem(pmcData: IPmcData, body: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse;
swapItem(pmcData: IPmcData, request: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Handles folding of Weapons
*/

View File

@ -1,10 +1,13 @@
import { HttpServerHelper } from "../helpers/HttpServerHelper";
import { ProfileHelper } from "../helpers/ProfileHelper";
import { PreAkiModLoader } from "../loaders/PreAkiModLoader";
import { IChangeRequestData } from "../models/eft/launcher/IChangeRequestData";
import { ILoginRequestData } from "../models/eft/launcher/ILoginRequestData";
import { IRegisterData } from "../models/eft/launcher/IRegisterData";
import { Info } from "../models/eft/profile/IAkiProfile";
import { Info, ModDetails } from "../models/eft/profile/IAkiProfile";
import { IConnectResponse } from "../models/eft/profile/IConnectResponse";
import { ICoreConfig } from "../models/spt/config/ICoreConfig";
import { IPackageJsonData } from "../models/spt/mod/IPackageJsonData";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { SaveServer } from "../servers/SaveServer";
@ -14,11 +17,13 @@ export declare class LauncherController {
protected hashUtil: HashUtil;
protected saveServer: SaveServer;
protected httpServerHelper: HttpServerHelper;
protected profileHelper: ProfileHelper;
protected databaseServer: DatabaseServer;
protected localisationService: LocalisationService;
protected preAkiModLoader: PreAkiModLoader;
protected configServer: ConfigServer;
protected coreConfig: ICoreConfig;
constructor(hashUtil: HashUtil, saveServer: SaveServer, httpServerHelper: HttpServerHelper, databaseServer: DatabaseServer, localisationService: LocalisationService, configServer: ConfigServer);
constructor(hashUtil: HashUtil, saveServer: SaveServer, httpServerHelper: HttpServerHelper, profileHelper: ProfileHelper, databaseServer: DatabaseServer, localisationService: LocalisationService, preAkiModLoader: PreAkiModLoader, configServer: ConfigServer);
connect(): IConnectResponse;
/**
* Get descriptive text for each of the profile edtions a player can choose
@ -33,4 +38,15 @@ export declare class LauncherController {
changePassword(info: IChangeRequestData): string;
wipe(info: IRegisterData): string;
getCompatibleTarkovVersion(): string;
/**
* Get the mods the server has currently loaded
* @returns Dictionary of mod name and mod details
*/
getLoadedServerMods(): Record<string, IPackageJsonData>;
/**
* Get the mods a profile has ever loaded into game with
* @param sessionId Player id
* @returns Array of mod details
*/
getServerModsProfileUsed(sessionId: string): ModDetails[];
}

View File

@ -4,8 +4,10 @@ import { WeightedRandomHelper } from "../helpers/WeightedRandomHelper";
import { ILocationBase } from "../models/eft/common/ILocationBase";
import { ILocationsGenerateAllResponse } from "../models/eft/common/ILocationsSourceDestinationBase";
import { IAirdropLootResult } from "../models/eft/location/IAirdropLootResult";
import { IGetLocationRequestData } from "../models/eft/location/IGetLocationRequestData";
import { AirdropTypeEnum } from "../models/enums/AirdropType";
import { IAirdropConfig } from "../models/spt/config/IAirdropConfig";
import { ILocationConfig } from "../models/spt/config/ILocationConfig";
import { LootRequest } from "../models/spt/services/LootRequest";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
@ -13,10 +15,12 @@ import { DatabaseServer } from "../servers/DatabaseServer";
import { LocalisationService } from "../services/LocalisationService";
import { HashUtil } from "../utils/HashUtil";
import { JsonUtil } from "../utils/JsonUtil";
import { RandomUtil } from "../utils/RandomUtil";
import { TimeUtil } from "../utils/TimeUtil";
export declare class LocationController {
protected jsonUtil: JsonUtil;
protected hashUtil: HashUtil;
protected randomUtil: RandomUtil;
protected weightedRandomHelper: WeightedRandomHelper;
protected logger: ILogger;
protected locationGenerator: LocationGenerator;
@ -26,16 +30,18 @@ export declare class LocationController {
protected timeUtil: TimeUtil;
protected configServer: ConfigServer;
protected airdropConfig: IAirdropConfig;
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer);
protected locationConfig: ILocationConfig;
constructor(jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, weightedRandomHelper: WeightedRandomHelper, logger: ILogger, locationGenerator: LocationGenerator, localisationService: LocalisationService, lootGenerator: LootGenerator, databaseServer: DatabaseServer, timeUtil: TimeUtil, configServer: ConfigServer);
/**
* Handle client/location/getLocalloot
* Get a location (map) with generated loot data
* @param location Map to generate loot for
* @param sessionId Player id
* @param request Map request to generate
* @returns ILocationBase
*/
get(location: string): ILocationBase;
get(sessionId: string, request: IGetLocationRequestData): ILocationBase;
/**
* Generate a maps base location without loot
* Generate a maps base location with loot
* @param name Map name
* @returns ILocationBase
*/

View File

@ -9,9 +9,9 @@ import { IGetProfileRequestData } from "../models/eft/match/IGetProfileRequestDa
import { IGetRaidConfigurationRequestData } from "../models/eft/match/IGetRaidConfigurationRequestData";
import { IJoinMatchRequestData } from "../models/eft/match/IJoinMatchRequestData";
import { IJoinMatchResult } from "../models/eft/match/IJoinMatchResult";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IInRaidConfig } from "../models/spt/config/IInRaidConfig";
import { IMatchConfig } from "../models/spt/config/IMatchConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { SaveServer } from "../servers/SaveServer";
@ -32,7 +32,7 @@ export declare class MatchController {
protected applicationContext: ApplicationContext;
protected matchConfig: IMatchConfig;
protected inraidConfig: IInRaidConfig;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, saveServer: SaveServer, profileHelper: ProfileHelper, matchLocationService: MatchLocationService, traderHelper: TraderHelper, botLootCacheService: BotLootCacheService, configServer: ConfigServer, profileSnapshotService: ProfileSnapshotService, botGenerationCacheService: BotGenerationCacheService, applicationContext: ApplicationContext);
getEnabled(): boolean;
/** Handle raid/profile/list */

View File

@ -2,20 +2,35 @@ import { ItemHelper } from "../helpers/ItemHelper";
import { IPmcData } from "../models/eft/common/IPmcData";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IPresetBuildActionRequestData } from "../models/eft/presetBuild/IPresetBuildActionRequestData";
import { WeaponBuild } from "../models/eft/profile/IAkiProfile";
import { IRemoveBuildRequestData } from "../models/eft/presetBuild/IRemoveBuildRequestData";
import { IUserBuilds } from "../models/eft/profile/IAkiProfile";
import { ILogger } from "../models/spt/utils/ILogger";
import { EventOutputHolder } from "../routers/EventOutputHolder";
import { DatabaseServer } from "../servers/DatabaseServer";
import { SaveServer } from "../servers/SaveServer";
import { HashUtil } from "../utils/HashUtil";
import { JsonUtil } from "../utils/JsonUtil";
export declare class PresetBuildController {
protected logger: ILogger;
protected hashUtil: HashUtil;
protected eventOutputHolder: EventOutputHolder;
protected jsonUtil: JsonUtil;
protected databaseServer: DatabaseServer;
protected itemHelper: ItemHelper;
protected saveServer: SaveServer;
constructor(hashUtil: HashUtil, eventOutputHolder: EventOutputHolder, itemHelper: ItemHelper, saveServer: SaveServer);
constructor(logger: ILogger, hashUtil: HashUtil, eventOutputHolder: EventOutputHolder, jsonUtil: JsonUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, saveServer: SaveServer);
/** Handle client/handbook/builds/my/list */
getUserBuilds(sessionID: string): WeaponBuild[];
/** Handle SaveBuild event */
saveBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveBuild event*/
removeBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
getUserBuilds(sessionID: string): IUserBuilds;
/** Handle SaveWeaponBuild event */
saveWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionId: string): IItemEventRouterResponse;
/** Handle SaveEquipmentBuild event */
saveEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
protected saveBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string, buildType: string): IItemEventRouterResponse;
/** Handle RemoveWeaponBuild event*/
removeBuild(pmcData: IPmcData, body: IRemoveBuildRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveWeaponBuild event*/
removeWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RemoveEquipmentBuild event*/
removeEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
protected removePlayerBuild(pmcData: IPmcData, id: string, sessionID: string): IItemEventRouterResponse;
}

View File

@ -5,6 +5,7 @@ import { QuestConditionHelper } from "../helpers/QuestConditionHelper";
import { QuestHelper } from "../helpers/QuestHelper";
import { TraderHelper } from "../helpers/TraderHelper";
import { IPmcData } from "../models/eft/common/IPmcData";
import { IQuestStatus } from "../models/eft/common/tables/IBotBase";
import { Item } from "../models/eft/common/tables/IItem";
import { AvailableForConditions, IQuest, Reward } from "../models/eft/common/tables/IQuest";
import { IRepeatableQuest } from "../models/eft/common/tables/IRepeatableQuests";
@ -23,10 +24,12 @@ import { MailSendService } from "../services/MailSendService";
import { PlayerService } from "../services/PlayerService";
import { SeasonalEventService } from "../services/SeasonalEventService";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { JsonUtil } from "../utils/JsonUtil";
import { TimeUtil } from "../utils/TimeUtil";
export declare class QuestController {
protected logger: ILogger;
protected timeUtil: TimeUtil;
protected jsonUtil: JsonUtil;
protected httpResponseUtil: HttpResponseUtil;
protected eventOutputHolder: EventOutputHolder;
protected databaseServer: DatabaseServer;
@ -43,7 +46,7 @@ export declare class QuestController {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected questConfig: IQuestConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, httpResponseUtil: HttpResponseUtil, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, itemHelper: ItemHelper, dialogueHelper: DialogueHelper, mailSendService: MailSendService, profileHelper: ProfileHelper, traderHelper: TraderHelper, questHelper: QuestHelper, questConditionHelper: QuestConditionHelper, playerService: PlayerService, localeService: LocaleService, seasonalEventService: SeasonalEventService, localisationService: LocalisationService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, jsonUtil: JsonUtil, httpResponseUtil: HttpResponseUtil, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, itemHelper: ItemHelper, dialogueHelper: DialogueHelper, mailSendService: MailSendService, profileHelper: ProfileHelper, traderHelper: TraderHelper, questHelper: QuestHelper, questConditionHelper: QuestConditionHelper, playerService: PlayerService, localeService: LocaleService, seasonalEventService: SeasonalEventService, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Handle client/quest/list
* Get all quests visible to player
@ -58,7 +61,7 @@ export declare class QuestController {
* @param playerLevel level of player to test against quest
* @returns true if quest can be seen/accepted by player of defined level
*/
protected playerLevelFulfillsQuestRequrement(quest: IQuest, playerLevel: number): boolean;
protected playerLevelFulfillsQuestRequirement(quest: IQuest, playerLevel: number): boolean;
/**
* Should a quest be shown to the player in trader quest screen
* @param questId Quest to check
@ -110,6 +113,13 @@ export declare class QuestController {
* @returns ItemEvent client response
*/
completeQuest(pmcData: IPmcData, body: ICompleteQuestRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Return quests that have different statuses
* @param preQuestStatusus Quests before
* @param postQuestStatuses Quests after
* @returns QuestStatusChange array
*/
protected getQuestsWithDifferentStatuses(preQuestStatusus: IQuestStatus[], postQuestStatuses: IQuestStatus[]): IQuestStatus[];
/**
* Send a popup to player on successful completion of a quest
* @param sessionID session id
@ -137,8 +147,9 @@ export declare class QuestController {
* @param sessionID session id
* @param pmcData player profile
* @param questsToFail quests to fail
* @param output Client output
*/
protected failQuests(sessionID: string, pmcData: IPmcData, questsToFail: IQuest[]): void;
protected failQuests(sessionID: string, pmcData: IPmcData, questsToFail: IQuest[], output: IItemEventRouterResponse): void;
/**
* Handle QuestHandover event
* @param pmcData Player profile

View File

@ -8,7 +8,6 @@ import { RagfairHelper } from "../helpers/RagfairHelper";
import { RagfairOfferHelper } from "../helpers/RagfairOfferHelper";
import { RagfairSellHelper } from "../helpers/RagfairSellHelper";
import { RagfairSortHelper } from "../helpers/RagfairSortHelper";
import { RagfairTaxHelper } from "../helpers/RagfairTaxHelper";
import { TraderHelper } from "../helpers/TraderHelper";
import { IPmcData } from "../models/eft/common/IPmcData";
import { Item } from "../models/eft/common/tables/IItem";
@ -22,6 +21,7 @@ import { IGetMarketPriceRequestData } from "../models/eft/ragfair/IGetMarketPric
import { IGetOffersResult } from "../models/eft/ragfair/IGetOffersResult";
import { IRagfairOffer } from "../models/eft/ragfair/IRagfairOffer";
import { ISearchRequestData } from "../models/eft/ragfair/ISearchRequestData";
import { IProcessBuyTradeRequestData } from "../models/eft/trade/IProcessBuyTradeRequestData";
import { IRagfairConfig } from "../models/spt/config/IRagfairConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { EventOutputHolder } from "../routers/EventOutputHolder";
@ -34,6 +34,7 @@ import { PaymentService } from "../services/PaymentService";
import { RagfairOfferService } from "../services/RagfairOfferService";
import { RagfairPriceService } from "../services/RagfairPriceService";
import { RagfairRequiredItemsService } from "../services/RagfairRequiredItemsService";
import { RagfairTaxService } from "../services/RagfairTaxService";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { TimeUtil } from "../utils/TimeUtil";
/**
@ -50,7 +51,7 @@ export declare class RagfairController {
protected itemHelper: ItemHelper;
protected saveServer: SaveServer;
protected ragfairSellHelper: RagfairSellHelper;
protected ragfairTaxHelper: RagfairTaxHelper;
protected ragfairTaxService: RagfairTaxService;
protected ragfairSortHelper: RagfairSortHelper;
protected ragfairOfferHelper: RagfairOfferHelper;
protected profileHelper: ProfileHelper;
@ -66,12 +67,12 @@ export declare class RagfairController {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected ragfairConfig: IRagfairConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, httpResponse: HttpResponseUtil, eventOutputHolder: EventOutputHolder, ragfairServer: RagfairServer, ragfairPriceService: RagfairPriceService, databaseServer: DatabaseServer, itemHelper: ItemHelper, saveServer: SaveServer, ragfairSellHelper: RagfairSellHelper, ragfairTaxHelper: RagfairTaxHelper, ragfairSortHelper: RagfairSortHelper, ragfairOfferHelper: RagfairOfferHelper, profileHelper: ProfileHelper, paymentService: PaymentService, handbookHelper: HandbookHelper, paymentHelper: PaymentHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, ragfairHelper: RagfairHelper, ragfairOfferService: RagfairOfferService, ragfairRequiredItemsService: RagfairRequiredItemsService, ragfairOfferGenerator: RagfairOfferGenerator, localisationService: LocalisationService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, httpResponse: HttpResponseUtil, eventOutputHolder: EventOutputHolder, ragfairServer: RagfairServer, ragfairPriceService: RagfairPriceService, databaseServer: DatabaseServer, itemHelper: ItemHelper, saveServer: SaveServer, ragfairSellHelper: RagfairSellHelper, ragfairTaxService: RagfairTaxService, ragfairSortHelper: RagfairSortHelper, ragfairOfferHelper: RagfairOfferHelper, profileHelper: ProfileHelper, paymentService: PaymentService, handbookHelper: HandbookHelper, paymentHelper: PaymentHelper, inventoryHelper: InventoryHelper, traderHelper: TraderHelper, ragfairHelper: RagfairHelper, ragfairOfferService: RagfairOfferService, ragfairRequiredItemsService: RagfairRequiredItemsService, ragfairOfferGenerator: RagfairOfferGenerator, localisationService: LocalisationService, configServer: ConfigServer);
getOffers(sessionID: string, searchRequest: ISearchRequestData): IGetOffersResult;
/**
* Get offers for the client based on type of search being performed
* @param searchRequest Client search request data
* @param itemsToAdd
* @param itemsToAdd comes from ragfairHelper.filterCategories()
* @param traderAssorts Trader assorts
* @param pmcProfile Player profile
* @returns array of offers
@ -125,6 +126,18 @@ export declare class RagfairController {
* @returns IItemEventRouterResponse
*/
addPlayerOffer(pmcData: IPmcData, offerRequest: IAddOfferRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Charge player a listing fee for using flea, pulls charge from data previously sent by client
* @param sessionID Player id
* @param rootItem Base item being listed (used when client tax cost not found and must be done on server)
* @param pmcData Player profile
* @param requirementsPriceInRub Rouble cost player chose for listing (used when client tax cost not found and must be done on server)
* @param itemStackCount How many items were listed in player (used when client tax cost not found and must be done on server)
* @param offerRequest Add offer request object from client
* @param output IItemEventRouterResponse
* @returns True if charging tax to player failed
*/
protected chargePlayerTaxFee(sessionID: string, rootItem: Item, pmcData: IPmcData, requirementsPriceInRub: number, itemStackCount: number, offerRequest: IAddOfferRequestData, output: IItemEventRouterResponse): boolean;
/**
* Is the item to be listed on the flea valid
* @param offerRequest Client offer request
@ -149,6 +162,20 @@ export declare class RagfairController {
createPlayerOffer(profile: IAkiProfile, requirements: Requirement[], items: Item[], sellInOnePiece: boolean, amountToSend: number): IRagfairOffer;
getAllFleaPrices(): Record<string, number>;
getStaticPrices(): Record<string, number>;
/**
* User requested removal of the offer, actually reduces the time to 71 seconds,
* allowing for the possibility of extending the auction before it's end time
* @param offerId offer to 'remove'
* @param sessionID Players id
* @returns IItemEventRouterResponse
*/
removeOffer(offerId: string, sessionID: string): IItemEventRouterResponse;
extendOffer(info: IExtendOfferRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Create a basic trader request object with price and currency type
* @param currency What currency: RUB, EURO, USD
* @param value Amount of currency
* @returns IProcessBuyTradeRequestData
*/
protected createBuyTradeRequestObject(currency: string, value: number): IProcessBuyTradeRequestData;
}

View File

@ -1,11 +1,15 @@
import { ItemHelper } from "../helpers/ItemHelper";
import { ProfileHelper } from "../helpers/ProfileHelper";
import { TradeHelper } from "../helpers/TradeHelper";
import { TraderHelper } from "../helpers/TraderHelper";
import { IPmcData } from "../models/eft/common/IPmcData";
import { Upd } from "../models/eft/common/tables/IItem";
import { Item, Upd } from "../models/eft/common/tables/IItem";
import { ITraderBase } from "../models/eft/common/tables/ITrader";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IProcessBaseTradeRequestData } from "../models/eft/trade/IProcessBaseTradeRequestData";
import { IProcessRagfairTradeRequestData } from "../models/eft/trade/IProcessRagfairTradeRequestData";
import { ISellScavItemsToFenceRequestData } from "../models/eft/trade/ISellScavItemsToFenceRequestData";
import { Traders } from "../models/enums/Traders";
import { IRagfairConfig } from "../models/spt/config/IRagfairConfig";
import { ITraderConfig } from "../models/spt/config/ITraderConfig";
import { ILogger } from "../models/spt/utils/ILogger";
@ -13,24 +17,50 @@ import { EventOutputHolder } from "../routers/EventOutputHolder";
import { ConfigServer } from "../servers/ConfigServer";
import { RagfairServer } from "../servers/RagfairServer";
import { LocalisationService } from "../services/LocalisationService";
import { RagfairPriceService } from "../services/RagfairPriceService";
import { HttpResponseUtil } from "../utils/HttpResponseUtil";
import { JsonUtil } from "../utils/JsonUtil";
declare class TradeController {
protected logger: ILogger;
protected eventOutputHolder: EventOutputHolder;
protected tradeHelper: TradeHelper;
protected itemHelper: ItemHelper;
protected profileHelper: ProfileHelper;
protected traderHelper: TraderHelper;
protected jsonUtil: JsonUtil;
protected ragfairServer: RagfairServer;
protected httpResponse: HttpResponseUtil;
protected localisationService: LocalisationService;
protected ragfairPriceService: RagfairPriceService;
protected configServer: ConfigServer;
protected ragfairConfig: IRagfairConfig;
protected traderConfig: ITraderConfig;
constructor(logger: ILogger, eventOutputHolder: EventOutputHolder, tradeHelper: TradeHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, ragfairServer: RagfairServer, httpResponse: HttpResponseUtil, localisationService: LocalisationService, configServer: ConfigServer);
constructor(logger: ILogger, eventOutputHolder: EventOutputHolder, tradeHelper: TradeHelper, itemHelper: ItemHelper, profileHelper: ProfileHelper, traderHelper: TraderHelper, jsonUtil: JsonUtil, ragfairServer: RagfairServer, httpResponse: HttpResponseUtil, localisationService: LocalisationService, ragfairPriceService: RagfairPriceService, configServer: ConfigServer);
/** Handle TradingConfirm event */
confirmTrading(pmcData: IPmcData, request: IProcessBaseTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle RagFairBuyOffer event */
confirmRagfairTrading(pmcData: IPmcData, body: IProcessRagfairTradeRequestData, sessionID: string): IItemEventRouterResponse;
/** Handle SellAllFromSavage event */
sellScavItemsToFence(pmcData: IPmcData, body: ISellScavItemsToFenceRequestData, sessionId: string): IItemEventRouterResponse;
/**
* Sell all sellable items to a trader from inventory
* WILL DELETE ITEMS FROM INVENTORY + CHILDREN OF ITEMS SOLD
* @param sessionId Session id
* @param profileWithItemsToSell Profile with items to be sold to trader
* @param profileThatGetsMoney Profile that gets the money after selling items
* @param trader Trader to sell items to
* @returns IItemEventRouterResponse
*/
protected sellInventoryToTrader(sessionId: string, profileWithItemsToSell: IPmcData, profileThatGetsMoney: IPmcData, trader: Traders): IItemEventRouterResponse;
/**
* Looks up an items children and gets total handbook price for them
* @param parentItemId parent item that has children we want to sum price of
* @param items All items (parent + children)
* @param handbookPrices Prices of items from handbook
* @param traderDetails Trader being sold to to perform buy category check against
* @returns Rouble price
*/
protected getPriceOfItemAndChildren(parentItemId: string, items: Item[], handbookPrices: Record<string, number>, traderDetails: ITraderBase): number;
protected confirmTradingInternal(pmcData: IPmcData, body: IProcessBaseTradeRequestData, sessionID: string, foundInRaid?: boolean, upd?: Upd): IItemEventRouterResponse;
}
export { TradeController };

View File

@ -14,7 +14,6 @@ import { DatabaseServer } from "../servers/DatabaseServer";
import { BotEquipmentFilterService } from "../services/BotEquipmentFilterService";
import { BotEquipmentModPoolService } from "../services/BotEquipmentModPoolService";
import { BotModLimits, BotWeaponModLimitService } from "../services/BotWeaponModLimitService";
import { ItemBaseClassService } from "../services/ItemBaseClassService";
import { ItemFilterService } from "../services/ItemFilterService";
import { LocalisationService } from "../services/LocalisationService";
import { HashUtil } from "../utils/HashUtil";
@ -29,7 +28,6 @@ export declare class BotEquipmentModGenerator {
protected databaseServer: DatabaseServer;
protected itemHelper: ItemHelper;
protected botEquipmentFilterService: BotEquipmentFilterService;
protected itemBaseClassService: ItemBaseClassService;
protected itemFilterService: ItemFilterService;
protected profileHelper: ProfileHelper;
protected botWeaponModLimitService: BotWeaponModLimitService;
@ -40,7 +38,7 @@ export declare class BotEquipmentModGenerator {
protected botEquipmentModPoolService: BotEquipmentModPoolService;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
constructor(logger: ILogger, jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, probabilityHelper: ProbabilityHelper, databaseServer: DatabaseServer, itemHelper: ItemHelper, botEquipmentFilterService: BotEquipmentFilterService, itemBaseClassService: ItemBaseClassService, itemFilterService: ItemFilterService, profileHelper: ProfileHelper, botWeaponModLimitService: BotWeaponModLimitService, botHelper: BotHelper, botGeneratorHelper: BotGeneratorHelper, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, localisationService: LocalisationService, botEquipmentModPoolService: BotEquipmentModPoolService, configServer: ConfigServer);
constructor(logger: ILogger, jsonUtil: JsonUtil, hashUtil: HashUtil, randomUtil: RandomUtil, probabilityHelper: ProbabilityHelper, databaseServer: DatabaseServer, itemHelper: ItemHelper, botEquipmentFilterService: BotEquipmentFilterService, itemFilterService: ItemFilterService, profileHelper: ProfileHelper, botWeaponModLimitService: BotWeaponModLimitService, botHelper: BotHelper, botGeneratorHelper: BotGeneratorHelper, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, localisationService: LocalisationService, botEquipmentModPoolService: BotEquipmentModPoolService, configServer: ConfigServer);
/**
* Check mods are compatible and add to array
* @param equipment Equipment item to add mods to
@ -83,10 +81,11 @@ export declare class BotEquipmentModGenerator {
*/
protected modSlotCanHoldScope(modSlot: string, modsParentId: string): boolean;
/**
* Set all scope mod chances to 100%
* @param modSpawnChances Chances objet to update
* Set mod spawn chances to defined amount
* @param modSpawnChances Chance dictionary to update
*/
protected setScopeSpawnChancesToFull(modSpawnChances: ModsChances): void;
protected adjustSlotSpawnChances(modSpawnChances: ModsChances, modSlotsToAdjust: string[], newChancePercent: number): void;
protected modSlotCanHoldMuzzleDevices(modSlot: string, modsParentId: string): boolean;
protected sortModKeys(unsortedKeys: string[]): string[];
/**
* Get a Slot property for an item (chamber/cartridge/slot)
@ -193,10 +192,12 @@ export declare class BotEquipmentModGenerator {
protected mergeCamoraPoolsTogether(camorasWithShells: Record<string, string[]>): string[];
/**
* Filter out non-whitelisted weapon scopes
* Controlled by bot.json weaponSightWhitelist
* e.g. filter out rifle scopes from SMGs
* @param weapon Weapon scopes will be added to
* @param scopes Full scope pool
* @param botWeaponSightWhitelist whitelist of scope types by weapon base type
* @returns array of scope tpls that have been filtered
* @param botWeaponSightWhitelist Whitelist of scope types by weapon base type
* @returns Array of scope tpls that have been filtered to just ones allowed for that weapon type
*/
protected filterSightsByWeaponType(weapon: Item, scopes: string[], botWeaponSightWhitelist: Record<string, string[]>): string[];
}

View File

@ -3,9 +3,10 @@ import { BotHelper } from "../helpers/BotHelper";
import { ProfileHelper } from "../helpers/ProfileHelper";
import { WeightedRandomHelper } from "../helpers/WeightedRandomHelper";
import { IBaseJsonSkills, IBaseSkill, IBotBase, Info, Health as PmcHealth, Skills as botSkills } from "../models/eft/common/tables/IBotBase";
import { Health, IBotType } from "../models/eft/common/tables/IBotType";
import { Appearance, Health, IBotType } from "../models/eft/common/tables/IBotType";
import { BotGenerationDetails } from "../models/spt/bots/BotGenerationDetails";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -36,6 +37,7 @@ export declare class BotGenerator {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, timeUtil: TimeUtil, jsonUtil: JsonUtil, profileHelper: ProfileHelper, databaseServer: DatabaseServer, botInventoryGenerator: BotInventoryGenerator, botLevelGenerator: BotLevelGenerator, botEquipmentFilterService: BotEquipmentFilterService, weightedRandomHelper: WeightedRandomHelper, botHelper: BotHelper, botDifficultyHelper: BotDifficultyHelper, seasonalEventService: SeasonalEventService, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Generate a player scav bot object
@ -66,6 +68,13 @@ export declare class BotGenerator {
* @returns IBotBase object
*/
protected generateBot(sessionId: string, bot: IBotBase, botJsonTemplate: IBotType, botGenerationDetails: BotGenerationDetails): IBotBase;
/**
* Choose various appearance settings for a bot using weights
* @param bot Bot to adjust
* @param appearance Appearance settings to choose from
* @param botGenerationDetails Generation details
*/
protected setBotAppearance(bot: IBotBase, appearance: Appearance, botGenerationDetails: BotGenerationDetails): void;
/**
* Create a bot nickname
* @param botJsonTemplate x.json from database

View File

@ -1,5 +1,6 @@
import { BotGeneratorHelper } from "../helpers/BotGeneratorHelper";
import { BotHelper } from "../helpers/BotHelper";
import { ItemHelper } from "../helpers/ItemHelper";
import { WeightedRandomHelper } from "../helpers/WeightedRandomHelper";
import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase";
import { Chances, Generation, IBotType, Inventory, Mods } from "../models/eft/common/tables/IBotType";
@ -25,12 +26,13 @@ export declare class BotInventoryGenerator {
protected botGeneratorHelper: BotGeneratorHelper;
protected botHelper: BotHelper;
protected weightedRandomHelper: WeightedRandomHelper;
protected itemHelper: ItemHelper;
protected localisationService: LocalisationService;
protected botEquipmentModPoolService: BotEquipmentModPoolService;
protected botEquipmentModGenerator: BotEquipmentModGenerator;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, botWeaponGenerator: BotWeaponGenerator, botLootGenerator: BotLootGenerator, botGeneratorHelper: BotGeneratorHelper, botHelper: BotHelper, weightedRandomHelper: WeightedRandomHelper, localisationService: LocalisationService, botEquipmentModPoolService: BotEquipmentModPoolService, botEquipmentModGenerator: BotEquipmentModGenerator, configServer: ConfigServer);
constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, databaseServer: DatabaseServer, botWeaponGenerator: BotWeaponGenerator, botLootGenerator: BotLootGenerator, botGeneratorHelper: BotGeneratorHelper, botHelper: BotHelper, weightedRandomHelper: WeightedRandomHelper, itemHelper: ItemHelper, localisationService: LocalisationService, botEquipmentModPoolService: BotEquipmentModPoolService, botEquipmentModGenerator: BotEquipmentModGenerator, configServer: ConfigServer);
/**
* Add equipment/weapons/loot to bot
* @param sessionId Session id
@ -103,10 +105,10 @@ export declare class BotInventoryGenerator {
* @param equipmentChances Chances bot can have equipment equipped
* @param botRole assault/pmcBot/bossTagilla etc
* @param isPmc Is the bot being generated as a pmc
* @param itemGenerationLimitsMinMax
* @param itemGenerationWeights
*/
protected addWeaponAndMagazinesToInventory(sessionId: string, weaponSlot: {
slot: EquipmentSlots;
shouldSpawn: boolean;
}, templateInventory: Inventory, botInventory: PmcInventory, equipmentChances: Chances, botRole: string, isPmc: boolean, itemGenerationLimitsMinMax: Generation, botLevel: number): void;
}, templateInventory: Inventory, botInventory: PmcInventory, equipmentChances: Chances, botRole: string, isPmc: boolean, itemGenerationWeights: Generation, botLevel: number): void;
}

View File

@ -2,11 +2,14 @@ import { BotGeneratorHelper } from "../helpers/BotGeneratorHelper";
import { BotWeaponGeneratorHelper } from "../helpers/BotWeaponGeneratorHelper";
import { HandbookHelper } from "../helpers/HandbookHelper";
import { ItemHelper } from "../helpers/ItemHelper";
import { WeightedRandomHelper } from "../helpers/WeightedRandomHelper";
import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase";
import { IBotType, 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 { EquipmentSlots } from "../models/enums/EquipmentSlots";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -25,11 +28,13 @@ export declare class BotLootGenerator {
protected botGeneratorHelper: BotGeneratorHelper;
protected botWeaponGenerator: BotWeaponGenerator;
protected botWeaponGeneratorHelper: BotWeaponGeneratorHelper;
protected weightedRandomHelper: WeightedRandomHelper;
protected botLootCacheService: BotLootCacheService;
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, handbookHelper: HandbookHelper, botGeneratorHelper: BotGeneratorHelper, botWeaponGenerator: BotWeaponGenerator, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, botLootCacheService: BotLootCacheService, localisationService: LocalisationService, configServer: ConfigServer);
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, hashUtil: HashUtil, randomUtil: RandomUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, handbookHelper: HandbookHelper, botGeneratorHelper: BotGeneratorHelper, botWeaponGenerator: BotWeaponGenerator, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, weightedRandomHelper: WeightedRandomHelper, botLootCacheService: BotLootCacheService, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Add loot to bots containers
* @param sessionId Session id
@ -40,23 +45,36 @@ export declare class BotLootGenerator {
* @param botLevel Level of bot
*/
generateLoot(sessionId: string, botJsonTemplate: IBotType, isPmc: boolean, botRole: string, botInventory: PmcInventory, botLevel: number): void;
/**
* Get an array of the containers a bot has on them (pockets/backpack/vest)
* @param botInventory Bot to check
* @returns Array of available slots
*/
protected getAvailableContainersBotCanStoreItemsIn(botInventory: PmcInventory): EquipmentSlots[];
/**
* Force healing items onto bot to ensure they can heal in-raid
* @param botInventory Inventory to add items to
* @param botRole Role of bot (sptBear/sptUsec)
*/
protected addForcedMedicalItemsToPmcSecure(botInventory: PmcInventory, botRole: string): void;
/**
* Get a biased random number
* @param min Smallest size
* @param max Biggest size
* @param nValue Value to bias choice
* @returns Chosen number
*/
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
* @param pool pool of items to pick from
* @param equipmentSlots What equality slot will the loot items be added to
* @param pool Pool of items to pick from
* @param equipmentSlots What equipment slot will the loot items be added to
* @param totalItemCount Max count of items to add
* @param inventoryToAddItemsTo bot inventory loot will be added to
* @param botRole role of the bot loot is being generated for (assault/pmcbot)
* @param useLimits should item limit counts be used as defined in config/bot.json
* @param totalValueLimitRub total value of loot allowed in roubles
* @param isPmc is the bot being generated for a pmc
* @param inventoryToAddItemsTo Bot inventory loot will be added to
* @param botRole Role of the bot loot is being generated for (assault/pmcbot)
* @param useLimits Should item limit counts be used as defined in config/bot.json
* @param totalValueLimitRub Total value of loot allowed in roubles
* @param isPmc Is 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;
/**
@ -70,38 +88,23 @@ export declare class BotLootGenerator {
*/
protected addLooseWeaponsToInventorySlot(sessionId: string, botInventory: PmcInventory, equipmentSlot: string, templateInventory: Inventory, modChances: ModsChances, botRole: string, isPmc: boolean, botLevel: number): void;
/**
* @deprecated replaced by getRandomItemFromPoolByRole()
* Get a random item from the pool parameter using the biasedRandomNumber system
* @param pool pool of items to pick an item from
* @param isPmc is the bot being created a pmc
* @returns ITemplateItem object
*/
protected getRandomItemFromPool(pool: ITemplateItem[], isPmc: boolean): ITemplateItem;
/**
* Get a random item from the pool parameter using the biasedRandomNumber system
* @param pool pool of items to pick an item from
* @param isPmc is the bot being created a pmc
* @param pool Pool of items to pick an item from
* @param isPmc Is the bot being created a pmc
* @returns ITemplateItem object
*/
protected getRandomItemFromPoolByRole(pool: ITemplateItem[], botRole: string): ITemplateItem;
/**
* @deprecated Replaced by getBotLootNValueByRole()
* Get the loot nvalue from botconfig
* @param isPmc if true the pmc nvalue is returned
* @returns nvalue as number
*/
protected getBotLootNValue(isPmc: boolean): number;
/**
* Get the loot nvalue from botconfig
* @param botRole role of bot e.g. assault/sptBear
* @param botRole Role of bot e.g. assault/bosstagilla/sptBear
* @returns nvalue as number
*/
protected getBotLootNValueByRole(botRole: string): number;
/**
* Update item limit array to contain items that have a limit
* Hydrate item limit array to contain items that have a limit for a specific bot type
* All values are set to 0
* @param isPmc is the bot a pmc
* @param botRole role the bot has
* @param isPmc Is the bot a pmc
* @param botRole Role the bot has
* @param limitCount
*/
protected initItemLimitArray(isPmc: boolean, botRole: string, limitCount: Record<string, number>): void;
@ -110,8 +113,8 @@ export declare class BotLootGenerator {
* @param itemTemplate Item we check to see if its reached spawn limit
* @param botRole Bot type
* @param isPmc Is bot we're working with a pmc
* @param limitCount spawn limits for items on bot
* @param itemSpawnLimits the limits this bot is allowed to have
* @param limitCount Spawn limits for items on bot
* @param itemSpawnLimits The limits this bot is allowed to have
* @returns true if item has reached spawn limit
*/
protected itemHasReachedSpawnLimit(itemTemplate: ITemplateItem, botRole: string, isPmc: boolean, limitCount: Record<string, number>, itemSpawnLimits: Record<string, number>): boolean;

View File

@ -2,18 +2,20 @@ import { BotGeneratorHelper } from "../helpers/BotGeneratorHelper";
import { BotWeaponGeneratorHelper } from "../helpers/BotWeaponGeneratorHelper";
import { ItemHelper } from "../helpers/ItemHelper";
import { WeightedRandomHelper } from "../helpers/WeightedRandomHelper";
import { MinMax } from "../models/common/MinMax";
import { Inventory as PmcInventory } from "../models/eft/common/tables/IBotBase";
import { Inventory, ModsChances } from "../models/eft/common/tables/IBotType";
import { GenerationData, 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 { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { IRepairConfig } from "../models/spt/config/IRepairConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { BotWeaponModLimitService } from "../services/BotWeaponModLimitService";
import { LocalisationService } from "../services/LocalisationService";
import { RepairService } from "../services/RepairService";
import { HashUtil } from "../utils/HashUtil";
import { JsonUtil } from "../utils/JsonUtil";
import { RandomUtil } from "../utils/RandomUtil";
@ -33,10 +35,13 @@ export declare class BotWeaponGenerator {
protected botWeaponModLimitService: BotWeaponModLimitService;
protected botEquipmentModGenerator: BotEquipmentModGenerator;
protected localisationService: LocalisationService;
protected repairService: RepairService;
protected inventoryMagGenComponents: IInventoryMagGen[];
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, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, botWeaponModLimitService: BotWeaponModLimitService, botEquipmentModGenerator: BotEquipmentModGenerator, localisationService: LocalisationService, inventoryMagGenComponents: IInventoryMagGen[]);
protected pmcConfig: IPmcConfig;
protected repairConfig: IRepairConfig;
constructor(jsonUtil: JsonUtil, logger: ILogger, hashUtil: HashUtil, databaseServer: DatabaseServer, itemHelper: ItemHelper, weightedRandomHelper: WeightedRandomHelper, botGeneratorHelper: BotGeneratorHelper, randomUtil: RandomUtil, configServer: ConfigServer, botWeaponGeneratorHelper: BotWeaponGeneratorHelper, botWeaponModLimitService: BotWeaponModLimitService, botEquipmentModGenerator: BotEquipmentModGenerator, localisationService: LocalisationService, repairService: RepairService, inventoryMagGenComponents: IInventoryMagGen[]);
/**
* Pick a random weapon based on weightings and generate a functional weapon
* @param equipmentSlot Primary/secondary/holster
@ -63,7 +68,7 @@ export declare class BotWeaponGenerator {
* @param weaponParentId ParentId of the weapon being generated
* @param modChances Dictionary of item types and % chance weapon will have that mod
* @param botRole e.g. assault/exusec
* @param isPmc
* @param isPmc Is weapon being generated for a pmc
* @returns GenerateWeaponResult object
*/
generateWeaponByTpl(sessionId: string, weaponTpl: string, equipmentSlot: string, botTemplateInventory: Inventory, weaponParentId: string, modChances: ModsChances, botRole: string, isPmc: boolean, botLevel: number): GenerateWeaponResult;
@ -104,11 +109,11 @@ export declare class BotWeaponGenerator {
* Generates extra magazines or bullets (if magazine is internal) and adds them to TacticalVest and Pockets.
* Additionally, adds extra bullets to SecuredContainer
* @param generatedWeaponResult object with properties for generated weapon (weapon mods pool / weapon template / ammo tpl)
* @param magCounts Magazine count to add to inventory
* @param magWeights Magazine weights for count to add to inventory
* @param inventory Inventory to add magazines to
* @param botRole The bot type we're getting generating extra mags for
*/
addExtraMagazinesToInventory(generatedWeaponResult: GenerateWeaponResult, magCounts: MinMax, inventory: PmcInventory, botRole: string): void;
addExtraMagazinesToInventory(generatedWeaponResult: GenerateWeaponResult, magWeights: GenerationData, inventory: PmcInventory, botRole: string): void;
/**
* Add Grendaes for UBGL to bots vest and secure container
* @param weaponMods Weapon array with mods

View File

@ -2,12 +2,15 @@ import { ContainerHelper } from "../helpers/ContainerHelper";
import { ItemHelper } from "../helpers/ItemHelper";
import { PresetHelper } from "../helpers/PresetHelper";
import { RagfairServerHelper } from "../helpers/RagfairServerHelper";
import { IContainerMinMax, IStaticContainer } from "../models/eft/common/ILocation";
import { ILocationBase } from "../models/eft/common/ILocationBase";
import { ILooseLoot, Spawnpoint, SpawnpointTemplate, SpawnpointsForced } from "../models/eft/common/ILooseLoot";
import { Item } from "../models/eft/common/tables/IItem";
import { IStaticAmmoDetails, IStaticContainerProps, IStaticForcedProps, IStaticLootDetails } from "../models/eft/common/tables/ILootBase";
import { IStaticAmmoDetails, IStaticContainerData, IStaticForcedProps, IStaticLootDetails } from "../models/eft/common/tables/ILootBase";
import { ILocationConfig } from "../models/spt/config/ILocationConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { LocalisationService } from "../services/LocalisationService";
import { SeasonalEventService } from "../services/SeasonalEventService";
import { JsonUtil } from "../utils/JsonUtil";
@ -19,8 +22,15 @@ export interface IContainerItem {
width: number;
height: number;
}
export interface IContainerGroupCount {
/** Containers this group has + probabilty to spawn */
containerIdsWithProbability: Record<string, number>;
/** How many containers the map should spawn with this group id */
chosenCount: number;
}
export declare class LocationGenerator {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
protected jsonUtil: JsonUtil;
protected objectId: ObjectId;
protected randomUtil: RandomUtil;
@ -33,7 +43,39 @@ export declare class LocationGenerator {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected locationConfig: ILocationConfig;
constructor(logger: ILogger, jsonUtil: JsonUtil, objectId: ObjectId, randomUtil: RandomUtil, ragfairServerHelper: RagfairServerHelper, itemHelper: ItemHelper, mathUtil: MathUtil, seasonalEventService: SeasonalEventService, containerHelper: ContainerHelper, presetHelper: PresetHelper, localisationService: LocalisationService, configServer: ConfigServer);
constructor(logger: ILogger, databaseServer: DatabaseServer, jsonUtil: JsonUtil, objectId: ObjectId, randomUtil: RandomUtil, ragfairServerHelper: RagfairServerHelper, itemHelper: ItemHelper, mathUtil: MathUtil, seasonalEventService: SeasonalEventService, containerHelper: ContainerHelper, presetHelper: PresetHelper, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Create an array of container objects with randomised loot
* @param locationBase Map base to generate containers for
* @param staticAmmoDist Static ammo distribution - database.loot.staticAmmo
* @returns Array of container objects
*/
generateStaticContainers(locationBase: ILocationBase, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): SpawnpointTemplate[];
/**
* Get containers with a non-100% chance to spawn OR are NOT on the container type randomistion blacklist
* @param staticContainers
* @returns IStaticContainerData array
*/
protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[];
/**
* Get containers with 100% spawn rate or have a type on the randomistion ignore list
* @param staticContainersOnMap
* @returns IStaticContainerData array
*/
protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[];
/**
* Choose a number of containers based on their probabilty value to fulfil the desired count in containerData.chosenCount
* @param groupId Name of the group the containers are being collected for
* @param containerData Containers and probability values for a groupId
* @returns List of chosen container Ids
*/
protected getContainersByProbabilty(groupId: string, containerData: IContainerGroupCount): string[];
/**
* Get a mapping of each groupid and the containers in that group + count of containers to spawn on map
* @param containersGroups Container group values
* @returns dictionary keyed by groupId
*/
protected getGroupIdToContainerMappings(staticContainerGroupData: IStaticContainer | Record<string, IContainerMinMax>, staticContainersOnMap: IStaticContainerData[]): Record<string, IContainerGroupCount>;
/**
* Choose loot to put into a static container based on weighting
* Handle forced items + seasonal item removal when not in season
@ -44,7 +86,7 @@ export declare class LocationGenerator {
* @param locationName Name of the map to generate static loot for
* @returns IStaticContainerProps
*/
generateContainerLoot(staticContainer: IStaticContainerProps, staticForced: IStaticForcedProps[], staticLootDist: Record<string, IStaticLootDetails>, staticAmmoDist: Record<string, IStaticAmmoDetails[]>, locationName: string): IStaticContainerProps;
protected addLootToContainer(staticContainer: IStaticContainerData, staticForced: IStaticForcedProps[], staticLootDist: Record<string, IStaticLootDetails>, staticAmmoDist: Record<string, IStaticAmmoDetails[]>, locationName: string): IStaticContainerData;
/**
* Get a 2d grid of a containers item slots
* @param containerTpl Tpl id of the container
@ -88,9 +130,10 @@ export declare class LocationGenerator {
* Create array of item (with child items) and return
* @param chosenComposedKey Key we want to look up items for
* @param spawnPoint Dynamic spawn point item we want will be placed in
* @param staticAmmoDist ammo distributions
* @returns IContainerItem
*/
protected createDynamicLootItem(chosenComposedKey: string, spawnPoint: Spawnpoint): IContainerItem;
protected createDynamicLootItem(chosenComposedKey: string, spawnPoint: Spawnpoint, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): IContainerItem;
/**
* Replace the _id value for base item + all children items parentid value
* @param itemWithChildren Item with mods to update

View File

@ -1,6 +1,6 @@
import { ItemHelper } from "../helpers/ItemHelper";
import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
import { ItemFilterService } from "../services/ItemFilterService";
@ -18,7 +18,7 @@ export declare class PMCLootGenerator {
protected pocketLootPool: string[];
protected vestLootPool: string[];
protected backpackLootPool: string[];
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(itemHelper: ItemHelper, databaseServer: DatabaseServer, configServer: ConfigServer, itemFilterService: ItemFilterService, seasonalEventService: SeasonalEventService);
/**
* Create an array of loot items a PMC can have in their pockets
@ -31,12 +31,12 @@ export declare class PMCLootGenerator {
*/
generatePMCVestLootPool(): string[];
/**
* Check if item has a width/height that lets it fit into a 1x2/2x1 slot
* 1x1 / 1x2 / 2x1
* Check if item has a width/height that lets it fit into a 2x2 slot
* 1x1 / 1x2 / 2x1 / 2x2
* @param item Item to check size of
* @returns true if it fits
*/
protected itemFitsInto1By2Slot(item: ITemplateItem): boolean;
protected itemFitsInto2By2Slot(item: ITemplateItem): boolean;
/**
* Create an array of loot items a PMC can have in their backpack
* @returns string array of tpls

View File

@ -55,11 +55,10 @@ export declare class RagfairOfferGenerator {
* @param items Items in the offer
* @param barterScheme Cost of item (currency or barter)
* @param loyalLevel Loyalty level needed to buy item
* @param price Price of offer
* @param sellInOnePiece Set StackObjectsCount to 1
* @param sellInOnePiece Flags sellInOnePiece to be true
* @returns IRagfairOffer
*/
createFleaOffer(userID: string, time: number, items: Item[], barterScheme: IBarterScheme[], loyalLevel: number, price: number, sellInOnePiece?: boolean): IRagfairOffer;
createFleaOffer(userID: string, time: number, items: Item[], barterScheme: IBarterScheme[], loyalLevel: number, sellInOnePiece?: boolean): IRagfairOffer;
/**
* Create an offer object ready to send to ragfairOfferService.addOffer()
* @param userID Owner of the offer
@ -67,17 +66,16 @@ export declare class RagfairOfferGenerator {
* @param items Items in the offer
* @param barterScheme Cost of item (currency or barter)
* @param loyalLevel Loyalty level needed to buy item
* @param price Price of offer
* @param sellInOnePiece Set StackObjectsCount to 1
* @returns IRagfairOffer
*/
protected createOffer(userID: string, time: number, items: Item[], barterScheme: IBarterScheme[], loyalLevel: number, price: number, sellInOnePiece?: boolean): IRagfairOffer;
protected createOffer(userID: string, time: number, items: Item[], barterScheme: IBarterScheme[], loyalLevel: number, sellInOnePiece?: boolean): IRagfairOffer;
/**
* Calculate the offer price that's listed on the flea listing
* @param offerRequirements barter requirements for offer
* @returns rouble cost of offer
*/
protected calculateOfferListingPrice(offerRequirements: OfferRequirement[]): number;
protected convertOfferRequirementsIntoRoubles(offerRequirements: OfferRequirement[]): number;
/**
* Get avatar url from trader table in db
* @param isTrader Is user we're getting avatar for a trader
@ -137,7 +135,7 @@ export declare class RagfairOfferGenerator {
* @param itemDetails raw db item details
* @returns Item array
*/
protected createSingleOfferForItem(items: Item[], isPreset: boolean, itemDetails: [boolean, ITemplateItem]): Promise<Item[]>;
protected createSingleOfferForItem(items: Item[], isPreset: boolean, itemDetails: [boolean, ITemplateItem]): Promise<void>;
/**
* Generate trader offers on flea using the traders assort data
* @param traderID Trader to generate offers for
@ -151,7 +149,7 @@ export declare class RagfairOfferGenerator {
* @param itemDetails db details of first item
* @returns
*/
protected getItemCondition(userID: string, itemWithMods: Item[], itemDetails: ITemplateItem): Item[];
protected randomiseItemUpdProperties(userID: string, itemWithMods: Item[], itemDetails: ITemplateItem): Item[];
/**
* Get the relevant condition id if item tpl matches in ragfair.json/condition
* @param tpl Item to look for matching condition object
@ -184,7 +182,7 @@ export declare class RagfairOfferGenerator {
* @param offerItems Items for sale in offer
* @returns Barter scheme
*/
protected createBarterRequirement(offerItems: Item[]): IBarterScheme[];
protected createBarterBarterScheme(offerItems: Item[]): IBarterScheme[];
/**
* Get an array of flea prices + item tpl, cached in generator class inside `allowedFleaPriceItemsForBarter`
* @returns array with tpl/price values
@ -196,7 +194,9 @@ export declare class RagfairOfferGenerator {
/**
* Create a random currency-based barter scheme for an array of items
* @param offerItems Items on offer
* @param isPackOffer Is the barter scheme being created for a pack offer
* @param multipler What to multiply the resulting price by
* @returns Barter scheme for offer
*/
protected createCurrencyRequirement(offerItems: Item[]): IBarterScheme[];
protected createCurrencyBarterScheme(offerItems: Item[], isPackOffer: boolean, multipler?: number): IBarterScheme[];
}

View File

@ -25,6 +25,8 @@ export declare class ScavCaseRewardGenerator {
protected itemFilterService: ItemFilterService;
protected configServer: ConfigServer;
protected scavCaseConfig: IScavCaseConfig;
protected dbItemsCache: ITemplateItem[];
protected dbAmmoItemsCache: ITemplateItem[];
constructor(logger: ILogger, randomUtil: RandomUtil, hashUtil: HashUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, ragfairPriceService: RagfairPriceService, itemFilterService: ItemFilterService, configServer: ConfigServer);
/**
* Create an array of rewards that will be given to the player upon completing their scav case build
@ -33,12 +35,12 @@ export declare class ScavCaseRewardGenerator {
*/
generate(recipeId: string): Product[];
/**
* Get all db items that are not blacklisted in scavcase config
* @returns filtered array of db items
* Get all db items that are not blacklisted in scavcase config or global blacklist
* Store in class field
*/
protected getDbItems(): ITemplateItem[];
protected cacheDbItems(): void;
/**
* Pick a number of items to be rewards, the count is defined by the values in
* Pick a number of items to be rewards, the count is defined by the values in `itemFilters` param
* @param items item pool to pick rewards from
* @param itemFilters how the rewards should be filtered down (by item count)
* @returns

View File

@ -52,6 +52,7 @@ export declare class WeatherGenerator {
*/
protected setCurrentDateTime(weather: IWeather): void;
protected getWeightedWindDirection(): WindDirection;
protected getWeightedClouds(): number;
protected getWeightedWindSpeed(): number;
protected getWeightedFog(): number;
protected getWeightedRain(): number;

View File

@ -1,5 +1,5 @@
import { MinMax } from "../../models/common/MinMax";
import { Inventory } from "../../models/eft/common/tables/IBotBase";
import { GenerationData } from "../../models/eft/common/tables/IBotType";
import { ITemplateItem } from "../../models/eft/common/tables/ITemplateItem";
export declare class InventoryMagGen {
private magCounts;
@ -7,8 +7,8 @@ export declare class InventoryMagGen {
private weaponTemplate;
private ammoTemplate;
private pmcInventory;
constructor(magCounts: MinMax, magazineTemplate: ITemplateItem, weaponTemplate: ITemplateItem, ammoTemplate: ITemplateItem, pmcInventory: Inventory);
getMagCount(): MinMax;
constructor(magCounts: GenerationData, magazineTemplate: ITemplateItem, weaponTemplate: ITemplateItem, ammoTemplate: ITemplateItem, pmcInventory: Inventory);
getMagCount(): GenerationData;
getMagazineTemplate(): ITemplateItem;
getWeaponTemplate(): ITemplateItem;
getAmmoTemplate(): ITemplateItem;

View File

@ -1,5 +1,5 @@
import { Difficulty } from "../models/eft/common/tables/IBotType";
import { IBotConfig } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -15,7 +15,7 @@ export declare class BotDifficultyHelper {
protected localisationService: LocalisationService;
protected botHelper: BotHelper;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, jsonUtil: JsonUtil, databaseServer: DatabaseServer, randomUtil: RandomUtil, localisationService: LocalisationService, botHelper: BotHelper, configServer: ConfigServer);
getPmcDifficultySettings(pmcType: "bear" | "usec", difficulty: string, usecType: string, bearType: string): Difficulty;
/**

View File

@ -2,7 +2,8 @@ import { ApplicationContext } from "../context/ApplicationContext";
import { DurabilityLimitsHelper } from "../helpers/DurabilityLimitsHelper";
import { Item, Repairable, Upd } from "../models/eft/common/tables/IItem";
import { ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { EquipmentFilters, IBotConfig } from "../models/spt/config/IBotConfig";
import { EquipmentFilters, IBotConfig, IRandomisedResourceValues } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -20,6 +21,7 @@ export declare class BotGeneratorHelper {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, randomUtil: RandomUtil, databaseServer: DatabaseServer, durabilityLimitsHelper: DurabilityLimitsHelper, itemHelper: ItemHelper, applicationContext: ApplicationContext, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Adds properties to an item
@ -31,6 +33,13 @@ export declare class BotGeneratorHelper {
generateExtraPropertiesForItem(itemTemplate: ITemplateItem, botRole?: string): {
upd?: Upd;
};
/**
* Randomize the HpResource for bots e.g (245/400 resources)
* @param maxResource Max resource value of medical items
* @param randomizationValues Value provided from config
* @returns Randomized value from maxHpResource
*/
protected getRandomizedResourceValue(maxResource: number, randomizationValues: IRandomisedResourceValues): number;
/**
* Get the chance for the weapon attachment or helmet equipment to be set as activated
* @param botRole role of bot with weapon/helmet

View File

@ -1,6 +1,7 @@
import { MinMax } from "../models/common/MinMax";
import { Difficulty, IBotType } from "../models/eft/common/tables/IBotType";
import { EquipmentFilters, IBotConfig, RandomisationDetails } from "../models/spt/config/IBotConfig";
import { IPmcConfig } from "../models/spt/config/IPmcConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
import { DatabaseServer } from "../servers/DatabaseServer";
@ -15,6 +16,7 @@ export declare class BotHelper {
protected localisationService: LocalisationService;
protected configServer: ConfigServer;
protected botConfig: IBotConfig;
protected pmcConfig: IPmcConfig;
constructor(logger: ILogger, jsonUtil: JsonUtil, databaseServer: DatabaseServer, randomUtil: RandomUtil, localisationService: LocalisationService, configServer: ConfigServer);
/**
* Get a template object for the specified botRole from bots.types db
@ -70,7 +72,7 @@ export declare class BotHelper {
*/
getBotRandomizationDetails(botLevel: number, botEquipConfig: EquipmentFilters): RandomisationDetails;
/**
* Choose between sptBear and sptUsec at random based on the % defined in botConfig.pmc.isUsec
* Choose between sptBear and sptUsec at random based on the % defined in pmcConfig.isUsec
* @returns pmc role
*/
getRandomizedPmcRole(): string;

View File

@ -1,5 +1,5 @@
import { MinMax } from "../models/common/MinMax";
import { Inventory } from "../models/eft/common/tables/IBotBase";
import { GenerationData } from "../models/eft/common/tables/IBotType";
import { Item } from "../models/eft/common/tables/IItem";
import { Grid, ITemplateItem } from "../models/eft/common/tables/ITemplateItem";
import { EquipmentSlots } from "../models/enums/EquipmentSlots";
@ -12,6 +12,7 @@ import { RandomUtil } from "../utils/RandomUtil";
import { ContainerHelper } from "./ContainerHelper";
import { InventoryHelper } from "./InventoryHelper";
import { ItemHelper } from "./ItemHelper";
import { WeightedRandomHelper } from "./WeightedRandomHelper";
export declare class BotWeaponGeneratorHelper {
protected logger: ILogger;
protected databaseServer: DatabaseServer;
@ -19,22 +20,23 @@ export declare class BotWeaponGeneratorHelper {
protected randomUtil: RandomUtil;
protected hashUtil: HashUtil;
protected inventoryHelper: InventoryHelper;
protected weightedRandomHelper: WeightedRandomHelper;
protected localisationService: LocalisationService;
protected containerHelper: ContainerHelper;
constructor(logger: ILogger, databaseServer: DatabaseServer, itemHelper: ItemHelper, randomUtil: RandomUtil, hashUtil: HashUtil, inventoryHelper: InventoryHelper, localisationService: LocalisationService, containerHelper: ContainerHelper);
constructor(logger: ILogger, databaseServer: DatabaseServer, itemHelper: ItemHelper, randomUtil: RandomUtil, hashUtil: HashUtil, inventoryHelper: InventoryHelper, weightedRandomHelper: WeightedRandomHelper, localisationService: LocalisationService, containerHelper: ContainerHelper);
/**
* Get a randomized number of bullets for a specific magazine
* @param magCounts min and max count of magazines
* @param magCounts Weights of magazines
* @param magTemplate magazine to generate bullet count for
* @returns bullet count number
*/
getRandomizedBulletCount(magCounts: MinMax, magTemplate: ITemplateItem): number;
getRandomizedBulletCount(magCounts: GenerationData, magTemplate: ITemplateItem): number;
/**
* Get a randomized count of magazines
* @param magCounts min and max value returned value can be between
* @returns numerical value of magazine count
*/
getRandomizedMagazineCount(magCounts: MinMax): number;
getRandomizedMagazineCount(magCounts: GenerationData): number;
/**
* Is this magazine cylinder related (revolvers and grenade launchers)
* @param magazineParentName the name of the magazines parent
@ -48,7 +50,7 @@ export declare class BotWeaponGeneratorHelper {
* @param magTemplate template object of magazine
* @returns Item array
*/
createMagazine(magazineTpl: string, ammoTpl: string, magTemplate: ITemplateItem): Item[];
createMagazineWithAmmo(magazineTpl: string, ammoTpl: string, magTemplate: ITemplateItem): Item[];
/**
* Add a specific number of cartridges to a bots inventory (defaults to vest and pockets)
* @param ammoTpl Ammo tpl to add to vest/pockets

View File

@ -27,6 +27,7 @@ export declare class HealthHelper {
* @param request Heal request
* @param sessionID Session id
* @param addEffects Should effects be added or removed (default - add)
* @param deleteExistingEffects Should all prior effects be removed before apply new ones
*/
saveVitality(pmcData: IPmcData, request: ISyncHealthRequestData, sessionID: string, addEffects?: boolean, deleteExistingEffects?: boolean): void;
/**

View File

@ -51,7 +51,7 @@ export declare class HideoutHelper {
* This convenience function initializes new Production Object
* with all the constants.
*/
initProduction(recipeId: string, productionTime: number): Production;
initProduction(recipeId: string, productionTime: number, needFuelForAllProductionTime: boolean): Production;
/**
* Is the provided object a Production type
* @param productive
@ -149,6 +149,16 @@ export declare class HideoutHelper {
* @returns Updated HideoutArea object
*/
protected updateWaterFilters(waterFilterArea: HideoutArea, production: Production, isGeneratorOn: boolean, pmcData: IPmcData): HideoutArea;
/**
* Get an adjusted water filter drain rate based on time elapsed since last run,
* handle edge case when craft time has gone on longer than total production time
* @param secondsSinceServerTick Time passed
* @param totalProductionTime Total time collecting water
* @param productionProgress how far water collector has progressed
* @param baseFilterDrainRate Base drain rate
* @returns
*/
protected adjustWaterFilterDrainRate(secondsSinceServerTick: number, totalProductionTime: number, productionProgress: number, baseFilterDrainRate: number): number;
/**
* Get the water filter drain rate based on hideout bonues player has
* @param pmcData Player profile
@ -160,7 +170,7 @@ export declare class HideoutHelper {
* @param prodId Id, e.g. Water collector id
* @returns seconds to produce item
*/
protected getProductionTimeSeconds(prodId: string): number;
protected getTotalProductionTimeSeconds(prodId: string): number;
/**
* Create a upd object using passed in parameters
* @param stackCount
@ -181,9 +191,10 @@ export declare class HideoutHelper {
* Get number of ticks that have passed since hideout areas were last processed, reduced when generator is off
* @param pmcData Player profile
* @param isGeneratorOn Is the generator on for the duration of elapsed time
* @param recipe Hideout production recipe being crafted we need the ticks for
* @returns Amount of time elapsed in seconds
*/
protected getTimeElapsedSinceLastServerTick(pmcData: IPmcData, isGeneratorOn: boolean): number;
protected getTimeElapsedSinceLastServerTick(pmcData: IPmcData, isGeneratorOn: boolean, recipe?: IHideoutProduction): number;
/**
* Get a count of how many BTC can be gathered by the profile
* @param pmcData Profile to look up
@ -206,6 +217,12 @@ export declare class HideoutHelper {
* @returns Hideout management skill object
*/
protected getHideoutManagementSkill(pmcData: IPmcData): Common;
/**
* HideoutManagement skill gives a consumption bonus the higher the level
* 0.5% per level per 1-51, (25.5% at max)
* @param pmcData Profile to get hideout consumption level level from
* @returns consumption bonus
*/
protected getHideoutManagementConsumptionBonus(pmcData: IPmcData): number;
/**
* Adjust craft time based on crafting skill level found in player profile
@ -231,7 +248,7 @@ export declare class HideoutHelper {
*/
protected createBitcoinRequest(pmcData: IPmcData): IAddItemRequestData;
/**
* Upgrade hideout wall from starting level to interactable level if enough time has passed
* Upgrade hideout wall from starting level to interactable level if necessary stations have been upgraded
* @param pmcProfile Profile to upgrade wall in
*/
unlockHideoutWallInProfile(pmcProfile: IPmcData): void;

View File

@ -1,7 +1,8 @@
import { IPmcData } from "../models/eft/common/IPmcData";
import { Quest, TraderInfo, Victim } from "../models/eft/common/tables/IBotBase";
import { IPmcData, IPostRaidPmcData } from "../models/eft/common/IPmcData";
import { IQuestStatus, TraderInfo, Victim } from "../models/eft/common/tables/IBotBase";
import { Item } from "../models/eft/common/tables/IItem";
import { ISaveProgressRequestData } from "../models/eft/inRaid/ISaveProgressRequestData";
import { IInRaidConfig } from "../models/spt/config/IInRaidConfig";
import { ILostOnDeathConfig } from "../models/spt/config/ILostOnDeathConfig";
import { ILogger } from "../models/spt/utils/ILogger";
import { ConfigServer } from "../servers/ConfigServer";
@ -27,6 +28,7 @@ export declare class InRaidHelper {
protected profileFixerService: ProfileFixerService;
protected configServer: ConfigServer;
protected lostOnDeathConfig: ILostOnDeathConfig;
protected inRaidConfig: IInRaidConfig;
constructor(logger: ILogger, saveServer: SaveServer, jsonUtil: JsonUtil, itemHelper: ItemHelper, databaseServer: DatabaseServer, inventoryHelper: InventoryHelper, questHelper: QuestHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, profileFixerService: ProfileFixerService, configServer: ConfigServer);
/**
* Lookup quest item loss from lostOnDeath config
@ -34,7 +36,7 @@ export declare class InRaidHelper {
*/
removeQuestItemsOnDeath(): boolean;
/**
* Check an array of items and add an upd object to money items with a stack count of 1
* Check items array and add an upd object to money 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
*/
@ -51,7 +53,7 @@ export declare class InRaidHelper {
* @param victim Who was killed by player
* @returns a numerical standing gain or loss
*/
protected getStandingChangeForKill(victim: Victim): number;
protected getFenceStandingChangeForKillAsScav(victim: Victim): number;
/**
* Reset a profile to a baseline, used post-raid
* Reset points earned during session property
@ -70,7 +72,7 @@ export declare class InRaidHelper {
* @param preRaidQuests Quests prior to starting raid
* @param postRaidQuests Quest after raid
*/
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: Quest[], postRaidQuests: Quest[]): void;
protected processFailedQuests(sessionId: string, pmcData: IPmcData, preRaidQuests: IQuestStatus[], postRaidQuests: IQuestStatus[]): void;
protected resetSkillPointsEarnedDuringRaid(profile: IPmcData): void;
/**
* Take body part effects from client profile and apply to server profile
@ -78,7 +80,12 @@ export declare class InRaidHelper {
* @param profileData player profile on server
*/
protected transferPostRaidLimbEffectsToProfile(saveProgressRequest: ISaveProgressRequestData, profileData: IPmcData): void;
protected applyTraderStandingAdjustments(preRaid: Record<string, TraderInfo>, postRaid: Record<string, TraderInfo>): void;
/**
* Adjust server trader settings if they differ from data sent by client
* @param tradersServerProfile Server
* @param tradersClientProfile Client
*/
protected applyTraderStandingAdjustments(tradersServerProfile: Record<string, TraderInfo>, tradersClientProfile: Record<string, TraderInfo>): 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
@ -91,22 +98,13 @@ export declare class InRaidHelper {
* @param sessionID Session id
*/
protected setPlayerInRaidLocationStatusToNone(sessionID: string): void;
/**
* 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 update inventory contents of
* @param isPlayerScav Was this a p scav raid
* @returns profile with FiR items properly tagged
*/
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;
removeSpawnedInSessionPropertyFromItems(postRaidProfile: IPostRaidPmcData): IPostRaidPmcData;
/**
* Update a players inventory post-raid
* Remove equipped items from pre-raid

View File

@ -1,9 +1,11 @@
import { IPmcData } from "../models/eft/common/IPmcData";
import { Inventory } from "../models/eft/common/tables/IBotBase";
import { Item } from "../models/eft/common/tables/IItem";
import { AddItem, IAddItemRequestData } from "../models/eft/inventory/IAddItemRequestData";
import { IAddItemTempObject } from "../models/eft/inventory/IAddItemTempObject";
import { IInventoryMergeRequestData } from "../models/eft/inventory/IInventoryMergeRequestData";
import { IInventoryMoveRequestData } from "../models/eft/inventory/IInventoryMoveRequestData";
import { IInventoryRemoveRequestData } from "../models/eft/inventory/IInventoryRemoveRequestData";
import { IInventorySplitRequestData } from "../models/eft/inventory/IInventorySplitRequestData";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IInventoryConfig, RewardDetails } from "../models/spt/config/IInventoryConfig";
@ -22,7 +24,9 @@ import { PaymentHelper } from "./PaymentHelper";
import { ProfileHelper } from "./ProfileHelper";
import { TraderAssortHelper } from "./TraderAssortHelper";
export interface OwnerInventoryItems {
/** Inventory items from source */
from: Item[];
/** Inventory items at destination */
to: Item[];
sameInventory: boolean;
isMail: boolean;
@ -56,9 +60,20 @@ export declare class InventoryHelper {
* @param useSortingTable Allow items to go into sorting table when stash has no space
* @returns IItemEventRouterResponse
*/
addItem(pmcData: IPmcData, request: IAddItemRequestData, output: IItemEventRouterResponse, sessionID: string, callback: {
(): void;
}, foundInRaid?: boolean, addUpd?: any, useSortingTable?: boolean): IItemEventRouterResponse;
addItem(pmcData: IPmcData, request: IAddItemRequestData, output: IItemEventRouterResponse, sessionID: string, callback: () => void, foundInRaid?: boolean, addUpd?: any, useSortingTable?: boolean): IItemEventRouterResponse;
/**
* Take the given item, find a free slot in passed in inventory and place it there
* If no space in inventory, place in sorting table
* @param itemToAdd Item to add to inventory
* @param stashFS2D Two dimentional stash map
* @param sortingTableFS2D Two dimentional sorting table stash map
* @param itemLib
* @param pmcData Player profile
* @param useSortingTable Should sorting table be used for overflow items when no inventory space for item
* @param output Client output object
* @returns Client error output if placing item failed
*/
protected placeItemInInventory(itemToAdd: IAddItemTempObject, stashFS2D: number[][], sortingTableFS2D: number[][], itemLib: Item[], playerInventory: Inventory, useSortingTable: boolean, output: IItemEventRouterResponse): IItemEventRouterResponse;
/**
* Add ammo to ammo boxes
* @param itemToAdd Item to check is ammo box
@ -66,8 +81,10 @@ export declare class InventoryHelper {
* @param output IItemEventRouterResponse object
* @param sessionID Session id
* @param pmcData Profile to add ammobox to
* @param output object to send to client
* @param foundInRaid should ammo be FiR
*/
protected hydrateAmmoBoxWithAmmo(pmcData: IPmcData, itemToAdd: IAddItemTempObject, parentId: string, sessionID: string, output: IItemEventRouterResponse): void;
protected hydrateAmmoBoxWithAmmo(pmcData: IPmcData, itemToAdd: IAddItemTempObject, parentId: string, sessionID: string, output: IItemEventRouterResponse, foundInRaid: boolean): void;
/**
*
* @param assortItems Items to add to inventory
@ -76,23 +93,31 @@ export declare class InventoryHelper {
*/
protected splitStackIntoSmallerStacks(assortItems: Item[], requestItem: AddItem, result: IAddItemTempObject[]): void;
/**
* Handle Remove event
* Remove item from player inventory + insured items array
* @param pmcData Profile to remove item from
* Also deletes child items
* @param profile Profile to remove item from (pmc or scav)
* @param itemId Items id to remove
* @param sessionID Session id
* @param output Existing IItemEventRouterResponse object to append data to, creates new one by default if not supplied
* @returns IItemEventRouterResponse
*/
removeItem(pmcData: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse;
removeItem(profile: IPmcData, itemId: string, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse;
removeItemAndChildrenFromMailRewards(sessionId: string, removeRequest: IInventoryRemoveRequestData, output: IItemEventRouterResponse): IItemEventRouterResponse;
removeItemByCount(pmcData: IPmcData, itemId: string, count: number, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse;
getItemSize(itemTpl: string, itemID: string, inventoryItem: Item[]): number[];
protected getSizeByInventoryItemHash(itemTpl: string, itemID: string, inventoryItemHash: InventoryHelper.InventoryItemHash): number[];
protected getInventoryItemHash(inventoryItem: Item[]): InventoryHelper.InventoryItemHash;
getContainerMap(containerW: number, containerH: number, itemList: Item[], containerId: string): number[][];
/**
* Return the inventory that needs to be modified (scav/pmc etc)
* Changes made to result apply to character inventory
* Based on the item action, determine whose inventories we should be looking at for from and to.
* @param request Item interaction request
* @param sessionId Session id / playerid
* @returns OwnerInventoryItems with inventory of player/scav to adjust
*/
getOwnerInventoryItems(body: IInventoryMoveRequestData | IInventorySplitRequestData | IInventoryMergeRequestData, sessionID: string): OwnerInventoryItems;
getOwnerInventoryItems(request: IInventoryMoveRequestData | IInventorySplitRequestData | IInventoryMergeRequestData, sessionId: string): OwnerInventoryItems;
/**
* Made a 2d array table with 0 - free slot and 1 - used slot
* @param {Object} pmcData
@ -101,19 +126,36 @@ export declare class InventoryHelper {
*/
protected getStashSlotMap(pmcData: IPmcData, sessionID: string): number[][];
protected getSortingTableSlotMap(pmcData: IPmcData): number[][];
/**
* Get Player Stash Proper Size
* @param sessionID Playerid
* @returns Array of 2 values, x and y stash size
*/
protected getPlayerStashSize(sessionID: string): Record<number, number>;
/**
* Get the players stash items tpl
* @param sessionID Player id
* @returns Stash tpl
*/
protected getStashType(sessionID: string): string;
/**
* Internal helper function to transfer an item from one profile to another.
* fromProfileData: Profile of the source.
* toProfileData: Profile of the destination.
* body: Move request
* @param fromItems Inventory of the source (can be non-player)
* @param toItems Inventory of the destination
* @param body Move request
*/
moveItemToProfile(fromItems: Item[], toItems: Item[], body: IInventoryMoveRequestData): void;
/**
* Internal helper function to move item within the same profile_f.
* @param pmcData profile to edit
* @param inventoryItems
* @param moveRequest
* @returns True if move was successful
*/
moveItemInternal(pmcData: IPmcData, inventoryItems: Item[], moveRequest: IInventoryMoveRequestData): void;
moveItemInternal(pmcData: IPmcData, inventoryItems: Item[], moveRequest: IInventoryMoveRequestData): {
success: boolean;
errorMessage?: string;
};
/**
* Update fast panel bindings when an item is moved into a container that doesnt allow quick slot access
* @param pmcData Player profile

View File

@ -26,6 +26,7 @@ declare class ItemHelper {
protected itemBaseClassService: ItemBaseClassService;
protected localisationService: LocalisationService;
protected localeService: LocaleService;
protected readonly defaultInvalidBaseTypes: string[];
constructor(logger: ILogger, hashUtil: HashUtil, jsonUtil: JsonUtil, randomUtil: RandomUtil, objectId: ObjectId, mathUtil: MathUtil, databaseServer: DatabaseServer, handbookHelper: HandbookHelper, itemBaseClassService: ItemBaseClassService, localisationService: LocalisationService, localeService: LocaleService);
/**
* Checks if an id is a valid item. Valid meaning that it's an item that be stored in stash
@ -55,6 +56,13 @@ declare class ItemHelper {
* @returns Price in roubles
*/
getItemPrice(tpl: string): number;
/**
* Returns the item price based on the handbook or as a fallback from the prices.json if the item is not
* found in the handbook. If the price can't be found at all return 0
* @param tpl Item to look price up of
* @returns Price in roubles
*/
getItemMaxPrice(tpl: string): number;
/**
* Get the static (handbook) price in roubles for an item by tpl
* @param tpl Items tpl id to look up price
@ -67,6 +75,11 @@ declare class ItemHelper {
* @returns Price in roubles (undefined if not found)
*/
getDynamicItemPrice(tpl: string): number;
/**
* Update items upd.StackObjectsCount to be 1 if its upd is missing or StackObjectsCount is undefined
* @param item Item to update
* @returns Fixed item
*/
fixItemStackCount(item: Item): Item;
/**
* AmmoBoxes contain StackSlots which need to be filled for the AmmoBox to have content.
@ -125,19 +138,19 @@ declare class ItemHelper {
getItemQualityModifier(item: Item): number;
/**
* Get a quality value based on a repairable items (weapon/armor) current state between current and max durability
* @param itemDetails
* @param repairable repairable object
* @param item
* @returns a number between 0 and 1
* @param itemDetails Db details for item we want quality value for
* @param repairable Repairable properties
* @param item Item quality value is for
* @returns A number between 0 and 1
*/
protected getRepairableItemQualityValue(itemDetails: ITemplateItem, repairable: Repairable, item: Item): number;
/**
* Recursive function that looks at every item from parameter and gets their childrens Ids + includes parent item in results
* @param items
* @param itemID
* @param items Array of items (item + possible children)
* @param itemId Parent items id
* @returns an array of strings
*/
findAndReturnChildrenByItems(items: Item[], itemID: string): string[];
findAndReturnChildrenByItems(items: Item[], itemId: string): string[];
/**
* A variant of findAndReturnChildren where the output is list of item objects instead of their ids.
* @param items
@ -164,12 +177,6 @@ declare class ItemHelper {
* @returns true if it is a dogtag
*/
isDogtag(tpl: string): boolean;
/**
* Can the item passed in be sold to a trader because it is raw money
* @param tpl Item template id to check
* @returns true if unsellable
*/
isNotSellable(tpl: string): boolean;
/**
* Gets the identifier for a child using slotId, locationX and locationY.
* @param item
@ -183,19 +190,19 @@ declare class ItemHelper {
*/
isItemTplStackable(tpl: string): boolean;
/**
* split item stack if it exceeds its StackMaxSize property
* @param itemToSplit item being split into smaller stacks
* split item stack if it exceeds its items StackMaxSize property
* @param itemToSplit Item to split into smaller stacks
* @returns Array of split items
*/
splitStack(itemToSplit: Item): Item[];
/**
* Find Barter items in the inventory
* Find Barter items from array of items
* @param {string} by tpl or id
* @param {Object} pmcData
* @param {Item[]} items Array of items to iterate over
* @param {string} barterItemId
* @returns Array of Item objects
*/
findBarterItems(by: "tpl" | "id", pmcData: IPmcData, barterItemId: string): Item[];
findBarterItems(by: "tpl" | "id", items: Item[], barterItemId: string): Item[];
/**
* Regenerate all guids with new ids, exceptions are for items that cannot be altered (e.g. stash/sorting table)
* @param pmcData Player profile
@ -237,6 +244,14 @@ declare class ItemHelper {
* @param ammoBoxDetails Item template from items db
*/
addCartridgesToAmmoBox(ammoBox: Item[], ammoBoxDetails: ITemplateItem): void;
/**
* Check if item is stored inside of a container
* @param item Item to check is inside of container
* @param desiredContainerSlotId Name of slot to check item is in e.g. SecuredContainer/Backpack
* @param items Inventory with child parent items to check
* @returns True when item is in container
*/
itemIsInsideContainer(item: Item, desiredContainerSlotId: string, items: Item[]): boolean;
/**
* Add child items (cartridges) to a magazine
* @param magazine Magazine to add child items to
@ -254,10 +269,21 @@ declare class ItemHelper {
* @param minSizePercent % the magazine must be filled to
*/
fillMagazineWithCartridge(magazine: Item[], magTemplate: ITemplateItem, cartridgeTpl: string, minSizePercent?: number): void;
/**
* Choose a random bullet type from the list of possible a magazine has
* @param magTemplate Magazine template from Db
* @returns Tpl of cartridge
*/
protected getRandomValidCaliber(magTemplate: ITemplateItem): string;
/**
* Chose a randomly weighted cartridge that fits
* @param caliber Desired caliber
* @param staticAmmoDist Cartridges and thier weights
* @returns Tpl of cartrdige
*/
protected drawAmmoTpl(caliber: string, staticAmmoDist: Record<string, IStaticAmmoDetails[]>): string;
/**
*
* Create a basic cartrige object
* @param parentId container cartridges will be placed in
* @param ammoTpl Cartridge to insert
* @param stackCount Count of cartridges inside parent

View File

@ -13,6 +13,11 @@ export declare class PresetHelper {
hasPreset(templateId: string): boolean;
getPreset(id: string): IPreset;
getPresets(templateId: string): IPreset[];
/**
* Get the default preset for passed in weapon id
* @param templateId Weapon id to get preset for
* @returns Null if no default preset, otherwise IPreset
*/
getDefaultPreset(templateId: string): IPreset;
getBaseItemTpl(presetId: string): string;
}

View File

@ -21,11 +21,11 @@ export declare class ProfileHelper {
protected profileSnapshotService: ProfileSnapshotService;
constructor(logger: ILogger, jsonUtil: JsonUtil, watermark: Watermark, timeUtil: TimeUtil, saveServer: SaveServer, databaseServer: DatabaseServer, itemHelper: ItemHelper, profileSnapshotService: ProfileSnapshotService);
/**
* Remove/reset started quest condtions in player profile
* Remove/reset a completed quest condtion from players profile quest data
* @param sessionID Session id
* @param conditionIds Condition ids that need to be reset/removed
* @param questConditionId Quest with condition to remove
*/
resetProfileQuestCondition(sessionID: string, conditionIds: string[]): void;
removeCompletedQuestConditionFromProfile(pmcData: IPmcData, questConditionId: Record<string, string>): void;
/**
* Get all profiles from server
* @returns Dictionary of profiles

View File

@ -3,5 +3,6 @@ export declare class QuestConditionHelper {
getQuestConditions(q: AvailableForConditions[], furtherFilter?: (a: AvailableForConditions) => AvailableForConditions[]): AvailableForConditions[];
getLevelConditions(q: AvailableForConditions[], furtherFilter?: (a: AvailableForConditions) => AvailableForConditions[]): AvailableForConditions[];
getLoyaltyConditions(q: AvailableForConditions[], furtherFilter?: (a: AvailableForConditions) => AvailableForConditions[]): AvailableForConditions[];
getStandingConditions(q: AvailableForConditions[], furtherFilter?: (a: AvailableForConditions) => AvailableForConditions[]): AvailableForConditions[];
protected filterConditions(q: AvailableForConditions[], questType: string, furtherFilter?: (a: AvailableForConditions) => AvailableForConditions[]): AvailableForConditions[];
}

View File

@ -1,5 +1,5 @@
import { IPmcData } from "../models/eft/common/IPmcData";
import { Quest } from "../models/eft/common/tables/IBotBase";
import { IQuestStatus } from "../models/eft/common/tables/IBotBase";
import { Item } from "../models/eft/common/tables/IItem";
import { AvailableForConditions, AvailableForProps, IQuest, Reward } from "../models/eft/common/tables/IQuest";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
@ -21,6 +21,7 @@ import { DialogueHelper } from "./DialogueHelper";
import { ItemHelper } from "./ItemHelper";
import { PaymentHelper } from "./PaymentHelper";
import { ProfileHelper } from "./ProfileHelper";
import { QuestConditionHelper } from "./QuestConditionHelper";
import { RagfairServerHelper } from "./RagfairServerHelper";
import { TraderHelper } from "./TraderHelper";
export declare class QuestHelper {
@ -29,6 +30,7 @@ export declare class QuestHelper {
protected timeUtil: TimeUtil;
protected hashUtil: HashUtil;
protected itemHelper: ItemHelper;
protected questConditionHelper: QuestConditionHelper;
protected eventOutputHolder: EventOutputHolder;
protected databaseServer: DatabaseServer;
protected localeService: LocaleService;
@ -41,7 +43,7 @@ export declare class QuestHelper {
protected mailSendService: MailSendService;
protected configServer: ConfigServer;
protected questConfig: IQuestConfig;
constructor(logger: ILogger, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, itemHelper: ItemHelper, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, localeService: LocaleService, ragfairServerHelper: RagfairServerHelper, dialogueHelper: DialogueHelper, profileHelper: ProfileHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, traderHelper: TraderHelper, mailSendService: MailSendService, configServer: ConfigServer);
constructor(logger: ILogger, jsonUtil: JsonUtil, timeUtil: TimeUtil, hashUtil: HashUtil, itemHelper: ItemHelper, questConditionHelper: QuestConditionHelper, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, localeService: LocaleService, ragfairServerHelper: RagfairServerHelper, dialogueHelper: DialogueHelper, profileHelper: ProfileHelper, paymentHelper: PaymentHelper, localisationService: LocalisationService, traderHelper: TraderHelper, mailSendService: MailSendService, configServer: ConfigServer);
/**
* Get status of a quest in player profile by its id
* @param pmcData Profile to search
@ -84,7 +86,15 @@ export declare class QuestHelper {
* @param profile Player profile
* @returns true if loyalty is high enough to fulfill quest requirement
*/
traderLoyaltyLevelRequirementCheck(questProperties: AvailableForProps, profile: IPmcData): boolean;
/**
* Check if trader has sufficient standing to fulfill quest requirement
* @param questProperties Quest props
* @param profile Player profile
* @returns true if standing is high enough to fulfill quest requirement
*/
traderStandingRequirementCheck(questProperties: AvailableForProps, profile: IPmcData): boolean;
protected compareAvailableForValues(current: number, required: number, compareMethod: string): boolean;
/**
* take reward item from quest and set FiR status + fix stack sizes + fix mod Ids
* @param reward Reward item to fix
@ -104,14 +114,14 @@ export declare class QuestHelper {
* @param newState State the new quest should be in when returned
* @param acceptedQuest Details of accepted quest from client
*/
getQuestReadyForProfile(pmcData: IPmcData, newState: QuestStatus, acceptedQuest: IAcceptQuestRequestData): Quest;
getQuestReadyForProfile(pmcData: IPmcData, newState: QuestStatus, acceptedQuest: IAcceptQuestRequestData): IQuestStatus;
/**
* Get quests that can be shown to player after starting a quest
* @param startedQuestId Quest started by player
* @param sessionID Session id
* @returns Quests accessible to player incuding newly unlocked quests now quest (startedQuestId) was started
*/
acceptedUnlocked(startedQuestId: string, sessionID: string): IQuest[];
getNewlyAccessibleQuestsWhenStartingQuest(startedQuestId: string, sessionID: string): IQuest[];
/**
* Get quests that can be shown to player after failing a quest
* @param failedQuestId Id of the quest failed by player
@ -123,9 +133,10 @@ export declare class QuestHelper {
* Adjust quest money rewards by passed in multiplier
* @param quest Quest to multiple money rewards
* @param multiplier Value to adjust money rewards by
* @param questStatus Status of quest to apply money boost to rewards of
* @returns Updated quest
*/
applyMoneyBoost(quest: IQuest, multiplier: number): IQuest;
applyMoneyBoost(quest: IQuest, multiplier: number, questStatus: QuestStatus): IQuest;
/**
* Sets the item stack to new value, or delete the item if value <= 0
* // TODO maybe merge this function and the one from customization
@ -160,9 +171,10 @@ export declare class QuestHelper {
* @param pmcData Player profile
* @param failRequest Fail quest request data
* @param sessionID Session id
* @param output Client output
* @returns Item event router response
*/
failQuest(pmcData: IPmcData, failRequest: IFailQuestRequestData, sessionID: string): IItemEventRouterResponse;
failQuest(pmcData: IPmcData, failRequest: IFailQuestRequestData, sessionID: string, output?: IItemEventRouterResponse): IItemEventRouterResponse;
/**
* Get List of All Quests from db
* NOT CLONED
@ -217,17 +229,18 @@ export declare class QuestHelper {
*/
protected findAndAddHideoutProductionIdToProfile(pmcData: IPmcData, craftUnlockReward: Reward, questDetails: IQuest, sessionID: string, response: IItemEventRouterResponse): void;
/**
* Get players intel center bonus from profile
* Get players money reward bonus from profile
* @param pmcData player profile
* @returns bonus as a percent
*/
protected getIntelCenterRewardBonus(pmcData: IPmcData): number;
protected getQuestMoneyRewardBonus(pmcData: IPmcData): number;
/**
* Find quest with 'findItem' requirement that needs the item tpl be handed in
* Find quest with 'findItem' condition that needs the item tpl be handed in
* @param itemTpl item tpl to look for
* @returns 'FindItem' condition id
* @param questIds Quests to search through for the findItem condition
* @returns quest id with 'FindItem' condition id
*/
getFindItemIdForQuestHandIn(itemTpl: string): string[];
getFindItemConditionByQuestItem(itemTpl: string, questIds: string[], allQuests: IQuest[]): Record<string, string>;
/**
* Add all quests to a profile with the provided statuses
* @param pmcProfile profile to update

View File

@ -1,4 +1,5 @@
import { IPmcData } from "../models/eft/common/IPmcData";
import { Item } from "../models/eft/common/tables/IItem";
import { ITraderAssort } from "../models/eft/common/tables/ITrader";
import { IItemEventRouterResponse } from "../models/eft/itemEvent/IItemEventRouterResponse";
import { IAkiProfile } from "../models/eft/profile/IAkiProfile";
@ -13,10 +14,10 @@ import { DatabaseServer } from "../servers/DatabaseServer";
import { SaveServer } from "../servers/SaveServer";
import { LocaleService } from "../services/LocaleService";
import { LocalisationService } from "../services/LocalisationService";
import { MailSendService } from "../services/MailSendService";
import { RagfairOfferService } from "../services/RagfairOfferService";
import { HashUtil } from "../utils/HashUtil";
import { TimeUtil } from "../utils/TimeUtil";
import { DialogueHelper } from "./DialogueHelper";
import { ItemHelper } from "./ItemHelper";
import { PaymentHelper } from "./PaymentHelper";
import { PresetHelper } from "./PresetHelper";
@ -33,7 +34,6 @@ export declare class RagfairOfferHelper {
protected databaseServer: DatabaseServer;
protected traderHelper: TraderHelper;
protected saveServer: SaveServer;
protected dialogueHelper: DialogueHelper;
protected itemHelper: ItemHelper;
protected paymentHelper: PaymentHelper;
protected presetHelper: PresetHelper;
@ -44,15 +44,16 @@ export declare class RagfairOfferHelper {
protected ragfairOfferService: RagfairOfferService;
protected localeService: LocaleService;
protected localisationService: LocalisationService;
protected mailSendService: MailSendService;
protected configServer: ConfigServer;
protected static goodSoldTemplate: string;
protected ragfairConfig: IRagfairConfig;
protected questConfig: IQuestConfig;
constructor(logger: ILogger, timeUtil: TimeUtil, hashUtil: HashUtil, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, traderHelper: TraderHelper, saveServer: SaveServer, dialogueHelper: DialogueHelper, itemHelper: ItemHelper, paymentHelper: PaymentHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, ragfairServerHelper: RagfairServerHelper, ragfairSortHelper: RagfairSortHelper, ragfairHelper: RagfairHelper, ragfairOfferService: RagfairOfferService, localeService: LocaleService, localisationService: LocalisationService, configServer: ConfigServer);
constructor(logger: ILogger, timeUtil: TimeUtil, hashUtil: HashUtil, eventOutputHolder: EventOutputHolder, databaseServer: DatabaseServer, traderHelper: TraderHelper, saveServer: SaveServer, itemHelper: ItemHelper, paymentHelper: PaymentHelper, presetHelper: PresetHelper, profileHelper: ProfileHelper, ragfairServerHelper: RagfairServerHelper, ragfairSortHelper: RagfairSortHelper, ragfairHelper: RagfairHelper, ragfairOfferService: RagfairOfferService, localeService: LocaleService, localisationService: LocalisationService, mailSendService: MailSendService, configServer: ConfigServer);
/**
* Passthrough to ragfairOfferService.getOffers(), get flea offers a player should see
* @param searchRequest
* @param itemsToAdd
* @param searchRequest Data from client
* @param itemsToAdd ragfairHelper.filterCategories()
* @param traderAssorts Trader assorts
* @param pmcProfile Player profile
* @returns Offers the player should see
@ -67,6 +68,13 @@ export declare class RagfairOfferHelper {
* @returns IRagfairOffer array
*/
getOffersForBuild(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, pmcProfile: IPmcData): IRagfairOffer[];
/**
* Check if offer is from trader standing the player does not have
* @param offer Offer to check
* @param pmcProfile Player profile
* @returns True if item is locked, false if item is purchaseable
*/
protected traderOfferLockedBehindLoyaltyLevel(offer: IRagfairOffer, pmcProfile: IPmcData): boolean;
/**
* Check if offer item is quest locked for current player by looking at sptQuestLocked property in traders barter_scheme
* @param offer Offer to check is quest locked
@ -112,27 +120,42 @@ export declare class RagfairOfferHelper {
*/
protected getProfileOffers(sessionID: string): IRagfairOffer[];
/**
* Delete an offer from a desired profile
* Delete an offer from a desired profile and from ragfair offers
* @param sessionID Session id of profile to delete offer from
* @param offerId Offer id to delete
* @param offerId Id of offer to delete
*/
protected deleteOfferByOfferId(sessionID: string, offerId: string): void;
protected deleteOfferById(sessionID: string, offerId: string): void;
/**
* Complete the selling of players' offer
* @param sessionID Session id
* @param offer Sold offer details
* @param boughtAmount Amount item was purchased for
* @returns Client response
* @returns IItemEventRouterResponse
*/
protected completeOffer(sessionID: string, offer: IRagfairOffer, boughtAmount: number): IItemEventRouterResponse;
/**
* Get a localised message for when players offer has sold on flea
* @param itemTpl Item sold
* @param boughtAmount How many were purchased
* @returns Localised message text
*/
protected getLocalisedOfferSoldMessage(itemTpl: string, boughtAmount: number): string;
/**
* Should a ragfair offer be visible to the player
* @param info Search request
* @param searchRequest Search request
* @param itemsToAdd ?
* @param traderAssorts Trader assort items
* @param offer The flea offer
* @param pmcProfile Player profile
* @returns True = should be shown to player
*/
isDisplayableOffer(info: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, offer: IRagfairOffer, pmcProfile: IPmcData): boolean;
isDisplayableOffer(searchRequest: ISearchRequestData, itemsToAdd: string[], traderAssorts: Record<string, ITraderAssort>, offer: IRagfairOffer, pmcProfile: IPmcData): boolean;
/**
* Is items quality value within desired range
* @param item Item to check quality of
* @param min Desired minimum quality
* @param max Desired maximum quality
* @returns True if in range
*/
protected itemQualityInRange(item: Item, min: number, max: number): boolean;
}

View File

@ -13,12 +13,12 @@ export declare class RagfairSellHelper {
constructor(logger: ILogger, randomUtil: RandomUtil, timeUtil: TimeUtil, configServer: ConfigServer);
/**
* Get the percent chance to sell an item based on its average listed price vs player chosen listing price
* @param baseChancePercent Base chance to sell item
* @param averageOfferPriceRub Price of average offer in roubles
* @param playerListedPriceRub Price player listed item for in roubles
* @param qualityMultiplier Quality multipler of item being sold
* @returns percent value
*/
calculateSellChance(baseChancePercent: number, averageOfferPriceRub: number, playerListedPriceRub: number): number;
calculateSellChance(averageOfferPriceRub: number, playerListedPriceRub: number, qualityMultiplier: number): number;
/**
* Get percent chance to sell an item when price is below items average listing price
* @param playerListedPriceRub Price player listed item for in roubles

View File

@ -21,6 +21,7 @@ export declare class RepairHelper {
* @param isArmor Is item being repaired a piece of armor
* @param amountToRepair how many unit of durability to repair
* @param useRepairKit Is item being repaired with a repair kit
* @param traderQualityMultipler Trader quality value from traders base json
* @param applyMaxDurabilityDegradation should item have max durability reduced
*/
updateItemDurability(itemToRepair: Item, itemToRepairDetails: ITemplateItem, isArmor: boolean, amountToRepair: number, useRepairKit: boolean, traderQualityMultipler: number, applyMaxDurabilityDegradation?: boolean): void;

View File

@ -39,12 +39,13 @@ export declare class TradeHelper {
buyItem(pmcData: IPmcData, buyRequestData: IProcessBuyTradeRequestData, sessionID: string, foundInRaid: boolean, upd: Upd): IItemEventRouterResponse;
/**
* Sell item to trader
* @param pmcData Profile to update
* @param profileWithItemsToSell Profile to remove items from
* @param profileToReceiveMoney Profile to accept the money for selling item
* @param sellRequest Request data
* @param sessionID Session id
* @returns IItemEventRouterResponse
*/
sellItem(pmcData: IPmcData, sellRequest: IProcessSellTradeRequestData, sessionID: string): IItemEventRouterResponse;
sellItem(profileWithItemsToSell: IPmcData, profileToReceiveMoney: IPmcData, sellRequest: IProcessSellTradeRequestData, sessionID: string): IItemEventRouterResponse;
/**
* Increment the assorts buy count by number of items purchased
* Show error on screen if player attempts to buy more than what the buy max allows

View File

@ -1,4 +1,5 @@
import { IPmcData } from "../models/eft/common/IPmcData";
import { Item } from "../models/eft/common/tables/IItem";
import { ProfileTraderTemplate } from "../models/eft/common/tables/IProfileTemplate";
import { ITraderAssort, ITraderBase, LoyaltyLevel } from "../models/eft/common/tables/ITrader";
import { Traders } from "../models/enums/Traders";
@ -35,7 +36,19 @@ export declare class TraderHelper {
protected highestTraderBuyPriceItems: Record<string, number>;
constructor(logger: ILogger, databaseServer: DatabaseServer, saveServer: SaveServer, profileHelper: ProfileHelper, handbookHelper: HandbookHelper, itemHelper: ItemHelper, playerService: PlayerService, localisationService: LocalisationService, fenceService: FenceService, timeUtil: TimeUtil, randomUtil: RandomUtil, configServer: ConfigServer);
getTrader(traderID: string, sessionID: string): ITraderBase;
getTraderAssortsById(traderId: string): ITraderAssort;
/**
* Get all assort data for a particular trader
* @param traderId Trader to get assorts for
* @returns ITraderAssort
*/
getTraderAssortsByTraderId(traderId: string): ITraderAssort;
/**
* Retrieve the Item from a traders assort data by its id
* @param traderId Trader to get assorts for
* @param assortId Id of assort to find
* @returns Item object
*/
getTraderAssortItemByAssortId(traderId: string, assortId: string): Item;
/**
* Reset a profiles trader data back to its initial state as seen by a level 1 player
* Does NOT take into account different profile levels
@ -67,10 +80,10 @@ export declare class TraderHelper {
protected addStandingValuesTogether(currentStanding: number, standingToAdd: number): number;
/**
* Calculate traders level based on exp amount and increments level if over threshold
* @param traderID trader to process
* @param sessionID session id
* @param traderID trader to check standing of
* @param pmcData profile to update trader in
*/
lvlUp(traderID: string, sessionID: string): void;
lvlUp(traderID: string, pmcData: IPmcData): void;
/**
* Get the next update timestamp for a trader
* @param traderID Trader to look up update value for
@ -115,10 +128,31 @@ export declare class TraderHelper {
* @returns Traders key
*/
getTraderById(traderId: string): Traders;
/**
* Validates that the provided traderEnumValue exists in the Traders enum. If the value is valid, it returns the
* same enum value, effectively serving as a trader ID; otherwise, it logs an error and returns an empty string.
* This method provides a runtime check to prevent undefined behavior when using the enum as a dictionary key.
*
* For example, instead of this:
* `const traderId = Traders[Traders.PRAPOR];`
*
* You can use safely use this:
* `const traderId = this.traderHelper.getValidTraderIdByEnumValue(Traders.PRAPOR);`
*
* @param traderEnumValue The trader enum value to validate
* @returns The validated trader enum value as a string, or an empty string if invalid
*/
getValidTraderIdByEnumValue(traderEnumValue: Traders): string;
/**
* Does the 'Traders' enum has a value that matches the passed in parameter
* @param value Value to check for
* @param key Value to check for
* @returns True, values exists in Traders enum as a value
*/
traderEnumHasValue(value: string): boolean;
traderEnumHasKey(key: string): boolean;
/**
* Accepts a trader id
* @param traderId Trader id
* @returns Ttrue if Traders enum has the param as a value
*/
traderEnumHasValue(traderId: string): boolean;
}

View File

@ -1,6 +1,6 @@
export declare class WeightedRandomHelper {
/**
* USE getWeightedValue() WHERE POSSIBLE
* @deprecated USE getWeightedValue() WHERE POSSIBLE
* Gets a tplId from a weighted dictionary
* @param {tplId: weighting[]} itemArray
* @returns tplId

View File

@ -25,6 +25,8 @@ export declare class PreAkiModLoader implements IModLoader {
protected order: Record<string, number>;
protected imported: Record<string, IPackageJsonData>;
protected akiConfig: ICoreConfig;
protected serverDependencies: Record<string, string>;
protected skippedMods: string[];
constructor(logger: ILogger, vfs: VFS, jsonUtil: JsonUtil, modCompilerService: ModCompilerService, bundleLoader: BundleLoader, localisationService: LocalisationService, configServer: ConfigServer, modTypeCheck: ModTypeCheck);
load(container: DependencyContainer): Promise<void>;
/**
@ -63,6 +65,7 @@ export declare class PreAkiModLoader implements IModLoader {
protected executeMods(container: DependencyContainer): Promise<void>;
sortModsLoadOrder(): string[];
protected addMod(mod: string): Promise<void>;
protected autoInstallDependencies(modPath: string, pkg: IPackageJsonData): void;
protected areModDependenciesFulfilled(pkg: IPackageJsonData, loadedMods: Record<string, IPackageJsonData>): boolean;
protected isModCompatible(mod: IPackageJsonData, loadedMods: Record<string, IPackageJsonData>): boolean;
/**

View File

@ -29,6 +29,7 @@ export interface IConfig {
TradingUnlimitedItems: boolean;
MaxLoyaltyLevelForAll: boolean;
GlobalLootChanceModifier: number;
GraphicSettings: IGraphicSettings;
TimeBeforeDeploy: number;
TimeBeforeDeployLocal: number;
TradingSetting: number;
@ -79,6 +80,7 @@ export interface IConfig {
SkillExpPerLevel: number;
GameSearchingTimeout: number;
WallContusionAbsorption: Ixyz;
WeaponFastDrawSettings: IWeaponFastDrawSettings;
SkillsSettings: ISkillsSettings;
AzimuthPanelShowsPlayerOrientation: boolean;
Aiming: IAiming;
@ -90,6 +92,19 @@ export interface IConfig {
Ballistic: IBallistic;
RepairSettings: IRepairSettings;
}
export interface IWeaponFastDrawSettings {
HandShakeCurveFrequency: number;
HandShakeCurveIntensity: number;
HandShakeMaxDuration: number;
HandShakeTremorIntensity: number;
WeaponFastSwitchMaxSpeedMult: number;
WeaponFastSwitchMinSpeedMult: number;
WeaponPistolFastSwitchMaxSpeedMult: number;
WeaponPistolFastSwitchMinSpeedMult: number;
}
export interface IGraphicSettings {
ExperimentalFogInCity: boolean;
}
export interface IBufferZone {
CustomerAccessTime: number;
CustomerCriticalTimeStart: number;
@ -146,7 +161,11 @@ export interface IKill {
expOnDamageAllHealth: number;
longShotDistance: number;
bloodLossToLitre: number;
botExpOnDamageAllHealth: number;
botHeadShotMult: number;
victimBotLevelExp: number;
pmcExpOnDamageAllHealth: number;
pmcHeadShotMult: number;
}
export interface ICombo {
percent: number;
@ -756,6 +775,7 @@ export interface IStamina {
OverweightConsumptionByPose: Ixyz;
AimingSpeedMultiplier: number;
WalkVisualEffectMultiplier: number;
WeaponFastSwitchConsumption: number;
HandsCapacity: number;
HandsRestoration: number;
ProneConsumption: number;
@ -1215,6 +1235,11 @@ export interface IFenceLevel {
ScavAttackSupport: boolean;
ExfiltrationPriceModifier: number;
AvailableExits: number;
BotApplySilenceChance: number;
BotGetInCoverChance: number;
BotHelpChance: number;
BotSpreadoutChance: number;
BotStopChance: number;
}
export interface IInertia {
InertiaLimits: Ixyz;

View File

@ -3,4 +3,18 @@ import { ILooseLoot } from "./ILooseLoot";
export interface ILocation {
base: ILocationBase;
looseLoot: ILooseLoot;
statics: IStaticContainer;
}
export interface IStaticContainer {
containersGroups: Record<string, IContainerMinMax>;
containers: Record<string, IContainerData>;
}
export interface IContainerMinMax {
minContainers: number;
maxContainers: number;
current?: number;
chosenCount?: number;
}
export interface IContainerData {
groupId: string;
}

View File

@ -18,6 +18,8 @@ export interface ILocationBase {
BotMaxPlayer: number;
BotMaxTimePlayer: number;
BotNormal: number;
BotSpawnCountStep: number;
BotSpawnPeriodCheck: number;
BotSpawnTimeOffMax: number;
BotSpawnTimeOffMin: number;
BotSpawnTimeOnMax: number;
@ -30,6 +32,7 @@ export interface ILocationBase {
Enabled: boolean;
EnableCoop: boolean;
GlobalLootChanceModifier: number;
GlobalContainerChanceModifier: number;
IconX: number;
IconY: number;
Id: string;
@ -47,6 +50,7 @@ export interface ILocationBase {
MinPlayers: number;
MaxCoopGroup: number;
Name: string;
NonWaveGroupScenario: INonWaveGroupScenario;
NewSpawn: boolean;
OcculsionCullingEnabled: boolean;
OldSpawn: boolean;
@ -85,6 +89,12 @@ export interface ILocationBase {
users_summon_seconds: number;
waves: Wave[];
}
export interface INonWaveGroupScenario {
Chance: number;
Enabled: boolean;
MaxToBeGroup: number;
MinToBeGroup: number;
}
export interface ILimit extends MinMax {
items: any[];
}
@ -207,6 +217,7 @@ export interface Wave {
time_max: number;
time_min: number;
sptId?: string;
ChanceGroup?: number;
}
export declare enum WildSpawnType {
ASSAULT = "assault",

View File

@ -16,11 +16,12 @@ export interface SpawnpointsForced {
}
export interface SpawnpointTemplate {
Id: string;
IsStatic: boolean;
IsContainer: boolean;
useGravity: boolean;
randomRotation: boolean;
Position: Ixyz;
Rotation: Ixyz;
IsAlwaysSpawn: boolean;
IsGroupPosition: boolean;
GroupPositions: any[];
Root: string;

View File

@ -1,3 +1,7 @@
import { IBotBase } from "./tables/IBotBase";
import { IBotBase, IEftStats } from "./tables/IBotBase";
export interface IPmcData extends IBotBase {
}
export interface IPostRaidPmcData extends IBotBase {
/** Only found in profile we get from client post raid */
EftStats: IEftStats;
}

View File

@ -6,7 +6,9 @@ import { Item, Upd } from "./IItem";
import { IPmcDataRepeatableQuest } from "./IRepeatableQuests";
export interface IBotBase {
_id: string;
aid: string;
aid: number;
/** SPT property - use to store player id - TODO - move to AID ( account id as guid of choice) */
sessionId: string;
savage?: string;
Info: Info;
Customization: Customization;
@ -19,7 +21,7 @@ export interface IBotBase {
BackendCounters: Record<string, BackendCounter>;
InsuredItems: InsuredItem[];
Hideout: Hideout;
Quests: Quest[];
Quests: IQuestStatus[];
TradersInfo: Record<string, TraderInfo>;
UnlockedInfo: IUnlockedInfo;
RagfairInfo: RagfairInfo;
@ -121,6 +123,8 @@ export interface Inventory {
sortingTable: string;
questRaidItems: string;
questStashItems: string;
/** Key is hideout area enum numeric as string e.g. "24", value is area _id */
hideoutAreaStashes: Record<string, string>;
fastPanel: Record<string, string>;
}
export interface IBaseJsonSkills {
@ -146,6 +150,9 @@ export interface Common extends IBaseSkill {
export interface Mastering extends IBaseSkill {
}
export interface Stats {
Eft: IEftStats;
}
export interface IEftStats {
CarriedQuestItems: string[];
Victims: Victim[];
TotalSessionExperience: number;
@ -274,7 +281,7 @@ export interface InsuredItem {
export interface Hideout {
Production: Record<string, Productive>;
Areas: HideoutArea[];
Improvements: Record<string, IHideoutImprovement>;
Improvement: Record<string, IHideoutImprovement>;
Seed: number;
sptUpdateLastRunTimestamp: number;
}
@ -292,6 +299,12 @@ export interface Productive {
SkipTime?: number;
/** Seconds needed to fully craft */
ProductionTime?: number;
GivenItemsInStart?: string[];
Interrupted?: boolean;
/** Used in hideout prodiction.json */
needFuelForAllProductionTime?: boolean;
/** Used when sending data to client */
NeedFuelForAllProductionTime?: boolean;
sptIsScavCase?: boolean;
}
export interface Production extends Productive {
@ -342,7 +355,7 @@ export declare enum SurvivorClass {
PARAMEDIC = 3,
SURVIVOR = 4
}
export interface Quest {
export interface IQuestStatus {
qid: string;
startTime: number;
status: QuestStatus;
@ -354,10 +367,18 @@ export interface Quest {
export interface TraderInfo {
loyaltyLevel: number;
salesSum: number;
disabled: boolean;
standing: number;
nextResupply: number;
unlocked: boolean;
disabled: boolean;
}
/** This object is sent to the client as part of traderRelations */
export interface TraderData {
salesSum: number;
standing: number;
loyalty: number;
unlocked: boolean;
disabled: boolean;
}
export interface RagfairInfo {
rating: number;

View File

@ -101,18 +101,22 @@ export interface Experience {
standingForKill: number;
}
export interface Generation {
items: ItemMinMax;
items: GenerationWeightingItems;
}
export interface ItemMinMax {
grenades: MinMaxWithWhitelist;
healing: MinMaxWithWhitelist;
drugs: MinMaxWithWhitelist;
stims: MinMaxWithWhitelist;
looseLoot: MinMaxWithWhitelist;
magazines: MinMaxWithWhitelist;
specialItems: MinMaxWithWhitelist;
export interface GenerationWeightingItems {
grenades: GenerationData;
healing: GenerationData;
drugs: GenerationData;
stims: GenerationData;
backpackLoot: GenerationData;
pocketLoot: GenerationData;
vestLoot: GenerationData;
magazines: GenerationData;
specialItems: GenerationData;
}
export interface MinMaxWithWhitelist extends MinMax {
export interface GenerationData {
/** key: number of items, value: weighting */
weights: Record<string, number>;
/** Array of item tpls */
whitelist: string[];
}

View File

@ -11,31 +11,30 @@ export interface IStaticAmmoDetails {
}
export interface IStaticContainerDetails {
staticWeapons: IStaticWeaponProps[];
staticContainers: IStaticContainerProps[];
staticContainers: IStaticContainerData[];
staticForced: IStaticForcedProps[];
}
export interface IStaticWeaponProps {
export interface IStaticContainerData {
probability: number;
template: IStaticContainerProps;
}
export interface IStaticPropsBase {
Id: string;
IsStatic: boolean;
IsContainer: boolean;
useGravity: boolean;
randomRotation: boolean;
Position: Ixyz;
Rotation: Ixyz;
IsGroupPosition: boolean;
IsAlwaysSpawn: boolean;
GroupPositions: any[];
Root: string;
Items: any[];
}
export interface IStaticWeaponProps extends IStaticPropsBase {
Items: Item[];
}
export interface IStaticContainerProps {
Id: string;
IsStatic: boolean;
useGravity: boolean;
randomRotation: boolean;
Position: Ixyz;
Rotation: Ixyz;
IsGroupPosition: boolean;
GroupPositions: any[];
Root: string;
export interface IStaticContainerProps extends IStaticPropsBase {
Items: StaticItem[];
}
export interface StaticItem {

View File

@ -7,4 +7,5 @@ export interface Metrics {
RenderBins: number[];
GameUpdateBins: number[];
MemoryMeasureInterval: number;
PauseReasons: number[];
}

View File

@ -1,4 +1,4 @@
import { Dialogue, WeaponBuild } from "../../profile/IAkiProfile";
import { Dialogue, IUserBuilds } from "../../profile/IAkiProfile";
import { IPmcData } from "../IPmcData";
export interface IProfileTemplates {
Standard: IProfileSides;
@ -14,7 +14,7 @@ export interface TemplateSide {
character: IPmcData;
suits: string[];
dialogues: Record<string, Dialogue>;
weaponbuilds: Record<string, WeaponBuild>;
userbuilds: IUserBuilds;
trader: ProfileTraderTemplate;
}
export interface ProfileTraderTemplate {

View File

@ -32,6 +32,8 @@ export interface IQuest {
changeQuestMessageText: string;
/** "Pmc" or "Scav" */
side: string;
/** Status of quest to player */
sptStatus?: QuestStatus;
}
export interface Conditions {
Started: AvailableForConditions[];

View File

@ -9,6 +9,7 @@ export interface ITemplateItem {
}
export interface Props {
AllowSpawnOnLocations?: any[];
BeltMagazineRefreshCount?: number;
ChangePriceCoef?: number;
FixedPrice?: boolean;
SendToClient?: boolean;
@ -83,6 +84,7 @@ export interface Props {
Velocity?: number;
RaidModdable?: boolean;
ToolModdable?: boolean;
UniqueAnimationModID?: number;
BlocksFolding?: boolean;
BlocksCollapsible?: boolean;
IsAnimated?: boolean;
@ -106,10 +108,12 @@ export interface Props {
Intensity?: number;
Mask?: string;
MaskSize?: number;
IsMagazineForStationaryWeapon?: boolean;
NoiseIntensity?: number;
NoiseScale?: number;
Color?: IColor;
DiffuseIntensity?: number;
MagazineWithBelt?: boolean;
HasHinge?: boolean;
RampPalette?: string;
DepthFade?: number;
@ -212,6 +216,7 @@ export interface Props {
MinRepairDegradation?: number;
MaxRepairDegradation?: number;
IronSightRange?: number;
IsBeltMachineGun?: boolean;
IsFlareGun?: boolean;
IsGrenadeLauncher?: boolean;
IsOneoff?: boolean;
@ -259,7 +264,7 @@ export interface Props {
CutoffFreq?: number;
Resonance?: number;
RolloffMultiplier?: number;
ReverbVolume: number;
ReverbVolume?: number;
CompressorVolume?: number;
AmbientVolume?: number;
DryVolume?: number;

View File

@ -1,11 +1,12 @@
export interface IGameConfigResponse {
aid: string;
aid: number;
lang: string;
languages: Record<string, string>;
ndaFree: boolean;
taxonomy: number;
activeProfileId: string;
backend: Backend;
useProtobuf: boolean;
utc_time: number;
/** Total in game time */
totalInGame: number;

View File

@ -1,12 +1,14 @@
export interface IHealthTreatmentRequestData {
Action: "RestoreHealth";
trader: string;
items: Item[];
items: Cost[];
difference: Difference;
timestamp: number;
}
export interface Item {
export interface Cost {
/** Id of stack to take money from */
id: string;
/** Amount of money to take off player for treatment */
count: number;
}
export interface Difference {
@ -25,5 +27,6 @@ export interface BodyParts {
}
export interface BodyPart {
Health: number;
/** Effects in array are to be removed */
Effects: string[];
}

View File

@ -8,6 +8,7 @@ export interface IHideoutArea {
craftGivesExp: boolean;
displayLevel: boolean;
enableAreaRequirements: boolean;
parentArea?: string;
stages: Record<string, Stage>;
}
export interface IAreaRequirement {
@ -19,6 +20,8 @@ export interface Stage {
autoUpgrade: boolean;
bonuses: StageBonus[];
constructionTime: number;
/** Containers inventory tpl */
container?: string;
description: string;
displayInterface: boolean;
improvements: IStageImprovement[];
@ -67,6 +70,7 @@ export interface StageBonus {
type: string;
filter?: string[];
icon?: string;
/** CHANGES PER DUMP */
id?: string;
templateId?: string;
}

View File

@ -1,10 +1,10 @@
import { PlayerRaidEndState } from "../../../models/enums/PlayerRaidEndState";
import { IPmcData } from "../common/IPmcData";
import { IPostRaidPmcData } from "../common/IPmcData";
import { ISyncHealthRequestData } from "../health/ISyncHealthRequestData";
import { IInsuredItemsData } from "./IInsuredItemsData";
export interface ISaveProgressRequestData {
exit: PlayerRaidEndState;
profile: IPmcData;
profile: IPostRaidPmcData;
isPlayerScav: boolean;
health: ISyncHealthRequestData;
insurance: IInsuredItemsData[];

View File

@ -5,6 +5,7 @@ export interface To {
id: string;
container: string;
location?: ToLocation | number;
isSearched?: boolean;
}
export interface ToLocation {
x: number;

View File

@ -1,10 +1,7 @@
import { OwnerInfo } from "../common/request/IBaseInteractionRequestData";
import { IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
export interface IInventoryExamineRequestData extends IInventoryBaseActionRequestData {
Action: "Examine";
item: string;
fromOwner: IFromOwner;
}
export interface IFromOwner {
id: string;
type: string;
fromOwner: OwnerInfo;
}

View File

@ -1,7 +1,11 @@
import { Container, IInventoryBaseActionRequestData } from "./IInventoryBaseActionRequestData";
export interface IInventorySplitRequestData extends IInventoryBaseActionRequestData {
Action: "Split";
item: string;
/** Id of item to split */
splitItem: string;
/** Id of new item stack */
newItem: string;
/** Destination new item will be placed in */
container: Container;
count: number;
}

View File

@ -1,5 +1,5 @@
import { QuestStatus } from "../../../models/enums/QuestStatus";
import { Health, Productive, Skills, TraderInfo } from "../common/tables/IBotBase";
import { EquipmentBuildType } from "../../../models/enums/EquipmentBuildType";
import { Health, IQuestStatus, Productive, Skills, TraderData } from "../common/tables/IBotBase";
import { Item, Upd } from "../common/tables/IItem";
import { IQuest } from "../common/tables/IQuest";
import { IPmcDataRepeatableQuest } from "../common/tables/IRepeatableQuests";
@ -20,32 +20,39 @@ export interface ProfileChange {
experience: number;
quests: IQuest[];
ragFairOffers: IRagfairOffer[];
builds: BuildChange[];
weaponBuilds: IWeaponBuildChange[];
equipmentBuilds: IEquipmentBuildChange[];
items: ItemChanges;
production: Record<string, Productive>;
/** Hideout area improvement id */
improvements: Record<string, Improvement>;
skills: Skills;
health: Health;
traderRelations: Record<string, TraderInfo>;
traderRelations: Record<string, TraderData>;
repeatableQuests?: IPmcDataRepeatableQuest[];
recipeUnlocked: Record<string, boolean>;
questsStatus: QuestStatusChange[];
changedHideoutStashes?: Record<string, IHideoutStashItem>;
questsStatus: IQuestStatus[];
}
export interface QuestStatusChange {
qid: string;
startTime: number;
status: QuestStatus;
statusTimers: Record<QuestStatus, number>;
completedConditions: string[];
availableAfter: number;
export interface IHideoutStashItem {
Id: string;
Tpl: string;
}
export interface BuildChange {
export interface IWeaponBuildChange {
id: string;
name: string;
root: string;
items: Item[];
}
export interface IEquipmentBuildChange {
id: string;
name: string;
root: string;
items: Item[];
type: string;
fastpanel: any[];
buildType: EquipmentBuildType;
}
export interface ItemChanges {
new: Product[];
change: Product[];

View File

@ -14,6 +14,11 @@ export interface INotification {
}
export declare enum NotificationType {
RAGFAIR_OFFER_SOLD = "RagfairOfferSold",
RAGFAIR_RATING_CHANGE = "RagfairRatingChange",
/** ChatMessageReceived */
NEW_MESSAGE = "new_message",
PING = "ping"
PING = "ping",
TRADER_SUPPLY = "TraderSupply",
TRADER_STANDING = "TraderStanding",
UNLOCK_TRADER = "UnlockTrader"
}

View File

@ -1,6 +1,3 @@
import { INotifierChannel } from "./INotifier";
export interface ISelectProfileResponse {
status: string;
notifier: INotifierChannel;
notifierServer: string;
}

View File

@ -1,4 +1,4 @@
import { Upd } from "../common/tables/IItem";
import { Item } from "../common/tables/IItem";
export interface IPresetBuildActionRequestData {
Action: string;
id: string;
@ -6,10 +6,3 @@ export interface IPresetBuildActionRequestData {
root: string;
items: Item[];
}
export interface Item {
_id: string;
_tpl: string;
upd?: Upd;
parentId?: string;
slotId?: string;
}

View File

@ -0,0 +1,4 @@
export interface IRemoveBuildRequestData {
Action: "RemoveBuild";
id: string;
}

View File

@ -1,3 +1,4 @@
import { EquipmentBuildType } from "../../../models/enums/EquipmentBuildType";
import { MemberCategory } from "../../../models/enums/MemberCategory";
import { MessageType } from "../../enums/MessageType";
import { IPmcData } from "../common/IPmcData";
@ -7,7 +8,7 @@ export interface IAkiProfile {
characters: Characters;
/** Clothing purchases */
suits: string[];
weaponbuilds: Record<string, WeaponBuild>;
userbuilds: IUserBuilds;
dialogues: Record<string, Dialogue>;
aki: Aki;
vitality: Vitality;
@ -22,6 +23,7 @@ export declare class TraderPurchaseData {
}
export interface Info {
id: string;
aid: number;
username: string;
password: string;
wipe: boolean;
@ -31,11 +33,25 @@ export interface Characters {
pmc: IPmcData;
scav: IPmcData;
}
export interface WeaponBuild {
export interface IUserBuilds {
weaponBuilds: IWeaponBuild[];
equipmentBuilds: IEquipmentBuild[];
}
export interface IWeaponBuild {
id: string;
name: string;
root: string;
items: Item[];
type: string;
}
export interface IEquipmentBuild {
id: string;
name: string;
root: string;
items: Item[];
type: string;
fastPanel: Record<string, string>;
buildType: EquipmentBuildType;
}
export interface Dialogue {
attachmentsNew: number;
@ -74,7 +90,7 @@ export interface Message {
Member?: IUpdatableChatMember;
templateId?: string;
text?: string;
hasRewards: boolean;
hasRewards?: boolean;
rewardCollected: boolean;
items?: MessageItems;
maxStorageTime?: number;

View File

@ -0,0 +1,6 @@
export interface IStorePlayerOfferTaxAmountRequestData {
id: string;
tpl: string;
count: number;
fee: number;
}

View File

@ -0,0 +1,6 @@
import { OwnerInfo } from "../common/request/IBaseInteractionRequestData";
export interface ISellScavItemsToFenceRequestData {
Action: "SellAllFromSavage";
fromOwner: OwnerInfo;
toOwner: OwnerInfo;
}

View File

@ -0,0 +1,3 @@
export declare enum AccountTypes {
SPT_DEVELOPER = "spt developer"
}

View File

@ -6,6 +6,7 @@ export declare enum BackendErrorCodes {
WRONG_AUTHORIZATION_CODE = 211,
NEED_CAPTCHA = 214,
NO_NEED_CAPTCHA = 215,
CAPTCHA_INVALID_ANSWER = 216,
CAPTCHA_FAILED = 218,
CAPTCHA_BRUTE_FORCED = 219,
NO_ROOM_IN_STASH = 223,
@ -15,6 +16,7 @@ export declare enum BackendErrorCodes {
REPORT_NOT_ALLOWED = 238,
NICKNAME_IS_ABUSIVE = 241,
NICKNAME_CHANGE_TIMEOUT = 242,
NOT_ENOUGH_SPACE_TO_UNPACK = 257,
NOT_MODIFIED = 304,
HTTP_BAD_REQUEST = 400,
HTTP_NOT_AUTHORIZED = 401,
@ -63,5 +65,21 @@ export declare enum BackendErrorCodes {
EXAMINATIONFAILED = 22001,
ITEMALREADYEXAMINED = 22002,
UNKNOWNNGINXERROR = 9000,
PARSERESPONSEERROR = 9001
PARSERESPONSEERROR = 9001,
UNKNOWNMATCHMAKERERROR2 = 503000,
UNKNOWNGROUPERROR = 502000,
GROUPREQUESTNOTFOUND = 502002,
GROUPFULL = 502004,
PLAYERALREADYINGROUP = 502005,
PLAYERNOTINGROUP = 502006,
PLAYERNOTLEADER = 502007,
CANTCHANGEREADYSTATE = 502010,
PLAYERFORBIDDENGROUPINVITES = 502011,
LEADERALREADYREADY = 502012,
GROUPSENDINVITEERROR = 502013,
PLAYERISOFFLINE = 502014,
PLAYERISNOTSEARCHINGFORGROUP = 502018,
PLAYERALREADYLOOKINGFORGAME = 503001,
PLAYERINRAID = 503002,
LIMITFORPRESETSREACHED = 504001
}

View File

@ -3,6 +3,7 @@ export declare enum BaseClasses {
UBGL = "55818b014bdc2ddc698b456b",
ARMOR = "5448e54d4bdc2dcc718b4568",
ARMOREDEQUIPMENT = "57bef4c42459772e8d35a53b",
REPAIR_KITS = "616eb7aea207f41933308f46",
HEADWEAR = "5a341c4086f77401f2541505",
FACECOVER = "5a341c4686f77469e155819e",
VEST = "5448e5284bdc2dcb718b4567",

View File

@ -1,6 +1,7 @@
export declare enum ConfigTypes {
AIRDROP = "aki-airdrop",
BOT = "aki-bot",
PMC = "aki-pmc",
CORE = "aki-core",
HEALTH = "aki-health",
HIDEOUT = "aki-hideout",
@ -11,6 +12,7 @@ export declare enum ConfigTypes {
ITEM = "aki-item",
LOCALE = "aki-locale",
LOCATION = "aki-location",
LOOT = "aki-loot",
MATCH = "aki-match",
PLAYERSCAV = "aki-playerscav",
PMC_CHAT_RESPONSE = "aki-pmcchatresponse",

View File

@ -0,0 +1,4 @@
export declare enum EquipmentBuildType {
CUSTOM = 0,
STANDARD = 1
}

View File

@ -23,5 +23,7 @@ export declare enum HideoutAreas {
BITCOIN_FARM = 20,
CHRISTMAS_TREE = 21,
EMERGENCY_WALL = 22,
GYM = 23
GYM = 23,
WEAPON_STAND = 24,
WEAPON_STAND_SECONDARY = 25
}

View File

@ -16,5 +16,10 @@ export declare enum ItemEventActions {
DELETE_MAP_MARKER = "DeleteMapMarker",
EDIT_MAP_MARKER = "EditMapMarker",
OPEN_RANDOM_LOOT_CONTAINER = "OpenRandomLootContainer",
HIDEOUT_QTE_EVENT = "HideoutQuickTimeEvent"
HIDEOUT_QTE_EVENT = "HideoutQuickTimeEvent",
SAVE_WEAPON_BUILD = "SaveWeaponBuild",
REMOVE_WEAPON_BUILD = "RemoveWeaponBuild",
REMOVE_BUILD = "RemoveBuild",
SAVE_EQUIPMENT_BUILD = "SaveEquipmentBuild",
REMOVE_EQUIPMENT_BUILD = "RemoveEquipmentBuild"
}

View File

@ -1,19 +1,19 @@
export declare enum WeatherType {
CLEAR_DAY = 1,
CLEAR_WIND = 2,
CLEAR_NIGHT = 3,
PARTLY_CLOUD_DAY = 4,
PARTLY_CLOUD_NIGHT = 5,
CLEAR_FOG_DAY = 6,
CLEAR_FOG_NIGHT = 7,
CLOUDFOG = 8,
FOG = 9,
MOSTLY_CLOUD = 10,
LIGHT_RAIN = 11,
RAIN = 12,
CLOUD_WIND = 13,
CLOUD_WIND_RAIN = 14,
FULL_CLOUD = 15,
THUNDER_CLOUD = 16,
NONE = 0
CLEAR_DAY = 0,
CLEAR_WIND = 1,
CLEAR_NIGHT = 2,
PARTLY_CLOUD_DAY = 3,
PARTLY_CLOUD_NIGHT = 4,
CLEAR_FOG_DAY = 5,
CLEAR_FOG_NIGHT = 6,
CLOUD_FOG = 7,
FOG = 8,
MOSTLY_CLOUD = 9,
LIGHT_RAIN = 10,
RAIN = 11,
CLOUD_WIND = 12,
CLOUD_WIND_RAIN = 13,
FULL_CLOUD = 14,
THUNDER_CLOUD = 15,
NONE = 16
}

View File

@ -30,9 +30,12 @@ export declare enum WildSpawnTypeNumber {
FOLLOWERBIRDEYE = 28,
BOSSZRYACHIY = 29,
FOLLOWERZRYACHIY = 30,
ARENAFIGHTER = 31,
ARENAFIGHTEREVENT = 32,
CRAZYASSAULTEVENT = 33,
SPTUSEC = 34,
SPTBEAR = 35
BOSSBOAR = 32,
FOLLOWERBOAR = 33,
ARENAFIGHTER = 34,
ARENAFIGHTEREVENT = 35,
BOSSBOARSNIPER = 36,
CRAZYASSAULTEVENT = 37,
SPTUSEC = 38,
SPTBEAR = 39
}

View File

@ -1,10 +1,12 @@
import { IPmcData } from "../../eft/common/IPmcData";
import { IPresetBuildActionRequestData } from "../../eft/presetBuild/IPresetBuildActionRequestData";
import { IItemEventRouterResponse } from "../../eft/itemEvent/IItemEventRouterResponse";
import { IGetBodyResponseData } from "../../eft/httpResponse/IGetBodyResponseData";
import { WeaponBuild } from "../../eft/profile/IAkiProfile";
import { IItemEventRouterResponse } from "../../eft/itemEvent/IItemEventRouterResponse";
import { IPresetBuildActionRequestData } from "../../eft/presetBuild/IPresetBuildActionRequestData";
import { IWeaponBuild } from "../../eft/profile/IAkiProfile";
export interface IPresetBuildCallbacks {
getHandbookUserlist(url: string, info: any, sessionID: string): IGetBodyResponseData<WeaponBuild[]>;
saveBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
removeBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
getHandbookUserlist(url: string, info: any, sessionID: string): IGetBodyResponseData<IWeaponBuild[]>;
saveWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
removeWeaponBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
saveEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
removeEquipmentBuild(pmcData: IPmcData, body: IPresetBuildActionRequestData, sessionID: string): IItemEventRouterResponse;
}

View File

@ -1,8 +1,7 @@
import { MinMaxWithWhitelist } from "../../../models/eft/common/tables/IBotType";
import { GenerationData } from "../../../models/eft/common/tables/IBotType";
import { MinMax } from "../../common/MinMax";
import { IBaseConfig } from "./IBaseConfig";
import { IBotDurability } from "./IBotDurability";
import { IPmcConfig } from "./IPmcConfig";
export interface IBotConfig extends IBaseConfig {
kind: "aki-bot";
/** How many variants of each bot should be generated on raid start */
@ -11,12 +10,12 @@ export interface IBotConfig extends IBaseConfig {
bosses: string[];
/** Control weapon/armor durability min/max values for each bot type */
durability: IBotDurability;
/** Controls the percentage values of randomization item resources */
lootItemResourceRandomization: Record<string, IRandomisedResourceDetails>;
/** Control the weighting of how expensive an average loot item is on a PMC or Scav */
lootNValue: LootNvalue;
/** Control what bots are added to a bots revenge list key: bottype, value: bottypes to revenge on seeing their death */
revenge: Record<string, string[]>;
/** PMC bot specific config settings */
pmc: IPmcConfig;
/** Control how many items are allowed to spawn on a bot
* key: bottype, value: <key: itemTpl: value: max item count> */
itemSpawnLimits: Record<string, Record<string, number>>;
@ -24,13 +23,14 @@ export interface IBotConfig extends IBaseConfig {
equipment: Record<string, EquipmentFilters>;
/** Show a bots botType value after their name */
showTypeInNickname: boolean;
/** What ai brain should a normal scav use per map */
assaultBrainType: Record<string, Record<string, number>>;
/** Max number of bots that can be spawned in a raid at any one time */
maxBotCap: Record<string, number>;
/** Chance scav has fake pscav name e.g. Scav name (player name) */
chanceAssaultScavHasPlayerScavName: number;
/** How many stacks of secret ammo should a bot have in its bot secure container */
secureContainerAmmoStackCount: number;
/** Batch generation size when type not available in cache */
botGenerationBatchSizePerType: number;
}
/** Number of bots to generate and store in cache on raid start per bot type */
export interface PresetBatch {
@ -55,6 +55,7 @@ export interface PresetBatch {
followerBirdEye: number;
followerBigPipe: number;
followerTest: number;
followerBoar: number;
marksman: number;
pmcBot: number;
sectantPriest: number;
@ -65,6 +66,8 @@ export interface PresetBatch {
arenaFighterEvent: number;
arenaFighter: number;
crazyAssaultEvent: number;
bossBoar: number;
bossBoarSniper: number;
sptUsec: number;
sptBear: number;
}
@ -75,13 +78,19 @@ export interface LootNvalue {
export interface EquipmentFilters {
/** Limits for mod types per weapon .e.g. scopes */
weaponModLimits: ModLimits;
/** Whitelsit for weapons allowed per gun */
/** Whitelist for weapon sight types allowed per gun */
weaponSightWhitelist: Record<string, string[]>;
/** Chance face shield is down/active */
faceShieldIsActiveChancePercent?: number;
/** Chance gun flashlight is active during the day */
lightIsActiveDayChancePercent?: number;
/** Chance gun flashlight is active during the night */
lightIsActiveNightChancePercent?: number;
/** Chance gun laser is active during the day */
laserIsActiveChancePercent?: number;
/** Chance NODS are down/active during the day */
nvgIsActiveChanceDayPercent?: number;
/** Chance NODS are down/active during the night */
nvgIsActiveChanceNightPercent?: number;
/** Adjust weighting/chances of items on bot by level of bot */
randomisation: RandomisationDetails[];
@ -89,9 +98,10 @@ export interface EquipmentFilters {
blacklist: EquipmentFilterDetails[];
/** Whitelist equipment by level of bot */
whitelist: EquipmentFilterDetails[];
clothing: WeightingAdjustmentDetails[];
/** Adjust clothing choice weighting by level of bot */
weightingAdjustments: WeightingAdjustmentDetails[];
/** Adjust equipment/ammo */
weightingAdjustmentsByBotLevel: WeightingAdjustmentDetails[];
/** Same as weightingAdjustments but based on player level instead of bot level */
weightingAdjustmentsByPlayerLevel?: WeightingAdjustmentDetails[];
}
export interface ModLimits {
/** How many scopes are allowed on a weapon - hard coded to work with OPTIC_SCOPE, ASSAULT_SCOPE, COLLIMATOR, COMPACT_COLLIMATOR */
@ -102,7 +112,7 @@ export interface ModLimits {
export interface RandomisationDetails {
/** Between what levels do these randomisation setting apply to */
levelRange: MinMax;
generation?: Record<string, MinMaxWithWhitelist>;
generation?: Record<string, GenerationData>;
/** Mod slots that should be fully randomisate -ignores mods from bottype.json */
randomisedWeaponModSlots?: string[];
/** Armor slots that should be randomised e.g. 'Headwear, Armband' */
@ -127,10 +137,20 @@ export interface WeightingAdjustmentDetails {
ammo?: AdjustmentDetails;
/** Key: equipment slot e.g. TacticalVest, value: item tpl + weight */
equipment?: AdjustmentDetails;
/** Key: clothing slor e.g. feet, value: item tpl + weight */
/** Key: clothing slot e.g. feet, value: item tpl + weight */
clothing?: AdjustmentDetails;
}
export interface AdjustmentDetails {
add: Record<string, Record<string, number>>;
edit: Record<string, Record<string, number>>;
}
export interface IRandomisedResourceDetails {
food: IRandomisedResourceValues;
meds: IRandomisedResourceValues;
}
export interface IRandomisedResourceValues {
/** Minimum percent of item to randomized between min and max resource*/
resourcePercent: number;
/** Chance for randomization to not occur */
chanceMaxResourcePercent: number;
}

View File

@ -6,8 +6,13 @@ export interface ICoreConfig extends IBaseConfig {
compatibleTarkovVersion: string;
serverName: string;
profileSaveIntervalSeconds: number;
sptFriendNickname: string;
fixes: IGameFixes;
commit: string;
features: IServerFeatures;
/** Commit hash build server was created from */
commit?: string;
/** Timestamp of server build */
buildTime?: string;
}
export interface IGameFixes {
/** Shotguns use a different value than normal guns causing huge pellet dispersion */
@ -15,3 +20,6 @@ export interface IGameFixes {
/** Remove items added by mods when the mod no longer exists - can fix dead profiles stuck at game load*/
removeModItemsFromProfile: boolean;
}
export interface IServerFeatures {
autoInstallModDependencies: boolean;
}

Some files were not shown because too many files have changed in this diff Show More