mirror of
https://github.com/sp-tarkov/server.git
synced 2025-02-12 16:10:43 -05:00
Merge branch '3.8.2-DEV' into 3.9.0-DEV
# Conflicts: # project/src/callbacks/ItemEventCallbacks.ts # project/src/models/eft/common/IGlobals.ts # project/src/models/eft/common/ILocation.ts # project/src/models/eft/common/ILocationBase.ts # project/src/models/eft/common/tables/ILootBase.ts # project/src/models/eft/common/tables/ITemplateItem.ts # project/src/models/eft/weather/IWeatherData.ts # project/src/models/spt/bots/BotGenerationDetails.ts # project/src/models/spt/config/IPmcConfig.ts # project/src/models/spt/config/IWeatherConfig.ts # project/src/models/spt/server/IDatabaseTables.ts # project/src/models/spt/server/ILocations.ts # project/src/servers/http/IHttpListener.ts
This commit is contained in:
commit
ba1ac09b0b
61
.gitattributes
vendored
61
.gitattributes
vendored
@ -1,62 +1,7 @@
|
||||
###############################################################################
|
||||
# Set default behavior to automatically normalize line endings.
|
||||
###############################################################################
|
||||
# Normalize Line Endings
|
||||
* text=auto eol=lf
|
||||
###############################################################################
|
||||
# Set default behavior for command prompt diff.
|
||||
#
|
||||
# This is need for earlier builds of msysgit that does not have it on by
|
||||
# default for csharp files.
|
||||
# Note: This is only used by command line
|
||||
###############################################################################
|
||||
#*.cs diff=csharp
|
||||
###############################################################################
|
||||
# Set the merge driver for project and solution files
|
||||
#
|
||||
# Merging from the command prompt will add diff markers to the files if there
|
||||
# are conflicts (Merging from VS is not affected by the settings below, in VS
|
||||
# the diff markers are never inserted). Diff markers may cause the following
|
||||
# file extensions to fail to load in VS. An alternative would be to treat
|
||||
# these files as binary and thus will always conflict and require user
|
||||
# intervention with every merge. To do so, just uncomment the entries below
|
||||
###############################################################################
|
||||
#*.sln merge=binary
|
||||
#*.csproj merge=binary
|
||||
#*.vbproj merge=binary
|
||||
#*.vcxproj merge=binary
|
||||
#*.vcproj merge=binary
|
||||
#*.dbproj merge=binary
|
||||
#*.fsproj merge=binary
|
||||
#*.lsproj merge=binary
|
||||
#*.wixproj merge=binary
|
||||
#*.modelproj merge=binary
|
||||
#*.sqlproj merge=binary
|
||||
#*.wwaproj merge=binary
|
||||
###############################################################################
|
||||
# behavior for image files
|
||||
#
|
||||
# image files are treated as binary by default.
|
||||
###############################################################################
|
||||
#*.jpg binary
|
||||
#*.png binary
|
||||
#*.gif binary
|
||||
###############################################################################
|
||||
# diff behavior for common document formats
|
||||
#
|
||||
# Convert binary document formats to text before diffing them. This feature
|
||||
# is only available from the command line. Turn it on by uncommenting the
|
||||
# entries below.
|
||||
###############################################################################
|
||||
#*.doc diff=astextplain
|
||||
#*.DOC diff=astextplain
|
||||
#*.docx diff=astextplain
|
||||
#*.DOCX diff=astextplain
|
||||
#*.dot diff=astextplain
|
||||
#*.DOT diff=astextplain
|
||||
#*.pdf diff=astextplain
|
||||
#*.PDF diff=astextplain
|
||||
#*.rtf diff=astextplain
|
||||
#*.RTF diff=astextplain
|
||||
|
||||
# LFS File Listing
|
||||
project/assets/database/locations/interchange/looseLoot.json filter=lfs diff=lfs merge=lfs -text
|
||||
project/assets/database/locations/interchange/staticLoot.json filter=lfs diff=lfs merge=lfs -text
|
||||
project/assets/database/locations/interchange/staticContainers.json filter=lfs diff=lfs merge=lfs -text
|
||||
|
@ -53,6 +53,7 @@ jobs:
|
||||
- name: Fix Instructions
|
||||
if: failure() && steps.run-tests.outcome == 'failure'
|
||||
run: |
|
||||
echo -e "Code linting has failed. The linter has been configured to look for coding errors, defects, and questionable patterns. Please look into resolving these errors. The linter may be able to resolve some of these issues automatically. You can launch the automatic fixer by running the following command from within the 'project' directory. Anything not resolved by running this command must be resolved manually.\n\nnpm run lint:fix\n"
|
||||
echo -e "Code linting has failed. The linter has been configured to look for coding errors, defects, questionable patterns, and code formatting issues. Please look into resolving these errors. The linter may be able to resolve some of these issues automatically. You can launch the automatic fixer by running the following command from within the 'project' directory. Anything not resolved by running this command must be resolved manually.\n\nnpm run lint:fix\n"
|
||||
echo -e "To automatically format code on-save in your IDE, please install the recommended VSCode plugins listed within the 'project/Server.code-workspace' file.\n"
|
||||
echo -e "Consistency is professionalism.™"
|
||||
shell: bash
|
||||
|
@ -1,59 +0,0 @@
|
||||
name: Check Code Style
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '*'
|
||||
pull_request:
|
||||
branches: '*'
|
||||
|
||||
jobs:
|
||||
dprint:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: refringe/spt-build-node:1.0.7
|
||||
steps:
|
||||
- name: Clone
|
||||
run: |
|
||||
rm -rf /workspace/SPT-AKI/Build/server
|
||||
git clone https://dev.sp-tarkov.com/${GITHUB_REPOSITORY}.git --branch master /workspace/SPT-AKI/Build/server
|
||||
|
||||
cd /workspace/SPT-AKI/Build/server
|
||||
git checkout ${GITHUB_SHA}
|
||||
shell: bash
|
||||
|
||||
- name: Pull LFS Files
|
||||
run: |
|
||||
cd /workspace/SPT-AKI/Build/server
|
||||
git lfs pull
|
||||
git lfs ls-files
|
||||
shell: bash
|
||||
|
||||
- name: Cache NPM Dependencies
|
||||
id: cache-npm-dependencies
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: /workspace/SPT-AKI/Build/server/project/node_modules
|
||||
key: npm-dependencies-${{ hashFiles('/workspace/SPT-AKI/Build/server/project/package.json') }}
|
||||
|
||||
- name: Install NPM Dependencies
|
||||
if: steps.cache-npm-dependencies.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
cd /workspace/SPT-AKI/Build/server/project
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
shell: bash
|
||||
|
||||
- name: Check Code Style
|
||||
id: check-code-style
|
||||
run: |
|
||||
cd /workspace/SPT-AKI/Build/server/project
|
||||
npm run style
|
||||
shell: bash
|
||||
|
||||
- name: Fix Instructions
|
||||
if: failure() && steps.check-code-style.outcome == 'failure'
|
||||
run: |
|
||||
echo -e "The code style check has failed. To fix this, please ensure your code adheres to the project's style guidelines. You can automatically format the project code by running the following command from within the 'project' directory.\n\nnpm run style:fix\n"
|
||||
echo -e "To automatically format code on-save in your IDE, please install the recommended VSCode plugins listed within the 'project/Server.code-workspace' file.\n"
|
||||
echo -e "Thank you for keeping our house clean. ♥"
|
||||
shell: bash
|
44
README.md
44
README.md
@ -31,9 +31,7 @@ This project has been built in [Visual Studio Code](https://code.visualstudio.co
|
||||
There are a number of VSC extensions that we recommended for this project. VSC will prompt you to install these when you open the workspace file. If you do not see the prompt, you can install them manually:
|
||||
|
||||
- [EditorConfig](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) - Editor Settings Synchronization
|
||||
- [Dprint Code Formatter](https://marketplace.visualstudio.com/items?itemName=dprint.dprint) - Formatting on Save
|
||||
- [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) - Linting for Coding Issues & Naming Conventions
|
||||
- [Biome](https://marketplace.visualstudio.com/items?itemName=biomejs.biome) - Linting for Coding Standards
|
||||
- [Vitest](https://marketplace.visualstudio.com/items?itemName=vitest.explorer) - Debugging Tests
|
||||
- [SPT ID Highlighter](https://marketplace.visualstudio.com/items?itemName=refringe.spt-id-highlighter) - Converts IDs to Names
|
||||
|
||||
@ -54,26 +52,24 @@ To prepare the project for development you will need to:
|
||||
|
||||
The following commands are available after the initial setup. Run them with `npm run <command>`.
|
||||
|
||||
| Command | Description |
|
||||
|--------------------------|----------------------------------------------------------------------|
|
||||
| `check:circular` | Check for circular dependencies in the project. |
|
||||
| `lint` | Lint the project for coding standards. |
|
||||
| `lint:fix` | Attempt to automatically fix coding standard issues. |
|
||||
| `style` | Check the project for style/formatting issues. |
|
||||
| `style:fix` | Attempt to automatically fix style/formatting issues. |
|
||||
| `test` | Run all tests. |
|
||||
| `test:watch` | Run tests in watch mode. Tests will re-run when files are changed. |
|
||||
| `test:coverage` | Run tests and generate a coverage report. |
|
||||
| `test:ui` | Run tests in UI mode. This will open a browser window to view tests. |
|
||||
| `build:release` | Build the project for release. |
|
||||
| `build:debug` | Build the project for debugging. |
|
||||
| `build:bleeding` | Build the project on the bleeding edge. |
|
||||
| `build:bleedingmods` | Build the project on the bleeding edge with mods. |
|
||||
| `run:build` | Run the project in build mode. |
|
||||
| `run:debug` | Run the project in debug mode. |
|
||||
| `run:profiler` | Run the project in profiler mode. |
|
||||
| `gen:types` | Generate types for the project. |
|
||||
| `gen:docs` | Generate documentation for the project. |
|
||||
| Command | Description |
|
||||
|--------------------------|-----------------------------------------------------------------------|
|
||||
| `check:circular` | Check for circular dependencies in the project. |
|
||||
| `lint` | Check the project for coding standards and style/formatting issues. |
|
||||
| `lint:fix` | Automatically fix coding standard issues and style/formatting issues. |
|
||||
| `test` | Run all tests. |
|
||||
| `test:watch` | Run tests in watch mode. Tests will re-run when files are changed. |
|
||||
| `test:coverage` | Run tests and generate a coverage report. |
|
||||
| `test:ui` | Run tests in UI mode. This will open a browser window to view tests. |
|
||||
| `build:release` | Build the project for release. |
|
||||
| `build:debug` | Build the project for debugging. |
|
||||
| `build:bleeding` | Build the project on the bleeding edge. |
|
||||
| `build:bleedingmods` | Build the project on the bleeding edge with mods. |
|
||||
| `run:build` | Run the project in build mode. |
|
||||
| `run:debug` | Run the project in debug mode. |
|
||||
| `run:profiler` | Run the project in profiler mode. |
|
||||
| `gen:types` | Generate types for the project. |
|
||||
| `gen:docs` | Generate documentation for the project. |
|
||||
|
||||
### Debugging
|
||||
|
||||
@ -83,7 +79,7 @@ To debug the project in Visual Studio Code, you can select the `Run` tab and the
|
||||
|
||||
To debug a server mod in Visual Studio Code, you can copy the mod files into the `user/mods` folder and then start the server in [debug mode](#debugging). You should now be able to set breakpoints in the mod's Typescript files and they will be hit when the server runs the mod files.
|
||||
|
||||
## Contributing
|
||||
## Contributing
|
||||
|
||||
We're really excited that you're interested in contributing! Before submitting your contribution, please consider the following:
|
||||
|
||||
@ -111,7 +107,7 @@ We're really excited that you're interested in contributing! Before submitting y
|
||||
|
||||
### Style Guide
|
||||
|
||||
We use Dprint to enforce a consistent code style. Please run `npm run style` and/or `npm run style:fix` before submitting your changes. This is made easier by using the recommended VSC extensions to automatically format your code whenever you save a file.
|
||||
We use ESLint Stylistic to enforce a consistent code style. Please run `npm run lint` and/or `npm run lint:fix` before submitting your changes. This is made easier by using the recommended VSC extensions to automatically format your code whenever you save a file.
|
||||
|
||||
### Tests
|
||||
|
||||
|
@ -7,3 +7,6 @@ charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
max_line_length = 120
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
@ -1,5 +1,5 @@
|
||||
# Exclude these folders from linting
|
||||
node_modules
|
||||
node_modules/
|
||||
out/
|
||||
obj/
|
||||
build/
|
||||
@ -12,4 +12,4 @@ user/mods/
|
||||
*.ico
|
||||
*.jpg
|
||||
*.txt
|
||||
*.exe
|
||||
*.exe
|
||||
|
@ -1,23 +1,34 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended"
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@stylistic/recommended-extends",
|
||||
"plugin:import/recommended",
|
||||
"plugin:import/typescript"
|
||||
],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"@stylistic",
|
||||
"import"
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"typescript": {
|
||||
"project": "tsconfig.json"
|
||||
},
|
||||
"node": {
|
||||
"extensions": [".ts", ".mjs"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"rules": {
|
||||
"brace-style": ["error", "allman"],
|
||||
"@typescript-eslint/no-namespace": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-dynamic-delete": "off",
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"@typescript-eslint/no-empty-interface": "off",
|
||||
"@typescript-eslint/no-explicit-any": "off", // We use a bunch of these.
|
||||
"@typescript-eslint/no-unused-vars": "off", // Typescript compiler already checks--Will grey out variable.
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/explicit-module-boundary-types": ["error", { "allowArgumentsExplicitlyTypedAsAny": true }],
|
||||
"@typescript-eslint/explicit-module-boundary-types": ["error", {
|
||||
"allowArgumentsExplicitlyTypedAsAny": true
|
||||
}],
|
||||
"@typescript-eslint/naming-convention": ["error", {
|
||||
"selector": "default",
|
||||
"format": ["camelCase"],
|
||||
@ -40,24 +51,63 @@
|
||||
"selector": "property",
|
||||
"modifiers": ["readonly", "static"],
|
||||
"format": ["UPPER_CASE"]
|
||||
}],
|
||||
"@stylistic/indent": ["error", 4, { "MemberExpression": 1, "SwitchCase": 1 }],
|
||||
"@stylistic/brace-style": ["error", "allman", { "allowSingleLine": false }],
|
||||
"@stylistic/semi": ["error", "always"],
|
||||
"@stylistic/quotes": ["error", "double", { "avoidEscape": true }],
|
||||
"@stylistic/linebreak-style": ["error", "unix"],
|
||||
"@stylistic/max-len": ["error", {
|
||||
"code": 120,
|
||||
"tabWidth": 4,
|
||||
"ignoreComments": true,
|
||||
"ignoreTrailingComments": true,
|
||||
"ignoreUrls": true,
|
||||
"ignoreStrings": true,
|
||||
"ignoreTemplateLiterals": true,
|
||||
"ignoreRegExpLiterals": true
|
||||
}],
|
||||
"@stylistic/multiline-ternary": ["error", "always-multiline"],
|
||||
"@stylistic/no-extra-parens": ["error", "all"],
|
||||
"@stylistic/new-parens": "error",
|
||||
"@stylistic/newline-per-chained-call": ["error", { "ignoreChainWithDepth": 3 }],
|
||||
"@stylistic/no-extra-semi": "error",
|
||||
"@stylistic/no-floating-decimal": "error",
|
||||
"@stylistic/no-multiple-empty-lines": ["error", { "max": 2, "maxEOF": 1 }],
|
||||
"@stylistic/switch-colon-spacing": "error",
|
||||
"@stylistic/type-annotation-spacing": "error",
|
||||
"@stylistic/type-generic-spacing": ["error"],
|
||||
"@stylistic/type-named-tuple-spacing": ["error"],
|
||||
"@stylistic/wrap-regex": "error",
|
||||
"@stylistic/yield-star-spacing": ["error", "both"],
|
||||
"import/order": ["error", {
|
||||
"groups": ["builtin", "external", "internal", "parent", "sibling", "index"],
|
||||
"pathGroups": [
|
||||
{
|
||||
"pattern": "tsyringe",
|
||||
"group": "builtin",
|
||||
"position": "before"
|
||||
}
|
||||
],
|
||||
"newlines-between": "never",
|
||||
"alphabetize": {
|
||||
"order": "asc",
|
||||
"caseInsensitive": true
|
||||
}
|
||||
}]
|
||||
},
|
||||
"overrides": [{
|
||||
"files": [
|
||||
"src/loaders/**/*.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["src/di/**/*.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-extraneous-class": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["src/loaders/**/*.ts"],
|
||||
"rules": {
|
||||
"@typescript-eslint/no-var-requires": "off"
|
||||
}
|
||||
}
|
||||
}, {
|
||||
"files": [
|
||||
"**/vitest.config.ts"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/naming-convention": ["error", {
|
||||
"selector": "objectLiteralProperty",
|
||||
"format": null
|
||||
}]
|
||||
}
|
||||
}]
|
||||
]
|
||||
}
|
||||
|
6
project/.vscode/extensions.json
vendored
6
project/.vscode/extensions.json
vendored
@ -1,10 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"EditorConfig.EditorConfig",
|
||||
"dprint.dprint",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"biomejs.biome",
|
||||
"vitest.explorer",
|
||||
"refringe.spt-id-highlighter"
|
||||
"refringe.spt-id-highlighter",
|
||||
"dbaeumer.vscode-eslint"
|
||||
]
|
||||
}
|
||||
|
@ -7,9 +7,11 @@
|
||||
"settings": {
|
||||
"window.title": "SPT-AKI Server",
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "dprint.dprint",
|
||||
"editor.codeActionsOnSave": [
|
||||
"source.organizeImports.biome"
|
||||
]
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": "explicit"
|
||||
},
|
||||
"eslint.debug": true,
|
||||
"eslint.experimental.useFlatConfig": false
|
||||
}
|
||||
}
|
||||
|
@ -2495,7 +2495,8 @@
|
||||
"Gizzy",
|
||||
"LuckyCharmT",
|
||||
"Rena-chan",
|
||||
"HB"
|
||||
"HB",
|
||||
"John Pork"
|
||||
],
|
||||
"generation": {
|
||||
"items": {
|
||||
|
@ -2492,7 +2492,8 @@
|
||||
"Gizzy",
|
||||
"LuckyCharmT",
|
||||
"Rena-chan",
|
||||
"HB"
|
||||
"HB",
|
||||
"John Pork"
|
||||
],
|
||||
"generation": {
|
||||
"items": {
|
||||
|
@ -1,69 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
|
||||
"javascript": {
|
||||
"parser": {
|
||||
"unsafeParameterDecoratorsEnabled": true
|
||||
}
|
||||
},
|
||||
"organizeImports": {
|
||||
"enabled": true
|
||||
},
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
"style": {
|
||||
"useImportType": "off",
|
||||
"noImplicitBoolean": "off",
|
||||
"noParameterAssign": "warn",
|
||||
"useTemplate": "warn",
|
||||
"useSingleVarDeclarator": "warn"
|
||||
},
|
||||
"a11y": {
|
||||
"useKeyWithClickEvents": "off",
|
||||
"useValidAnchor": "warn"
|
||||
},
|
||||
"suspicious": {
|
||||
"noExplicitAny": "off",
|
||||
"noDoubleEquals": "warn",
|
||||
"noShadowRestrictedNames": "warn",
|
||||
"noEmptyInterface": "off"
|
||||
},
|
||||
"performance": {
|
||||
"noDelete": "off"
|
||||
},
|
||||
"correctness": {
|
||||
"noUnnecessaryContinue": "warn"
|
||||
},
|
||||
"complexity": {
|
||||
"noStaticOnlyClass": "off",
|
||||
"useSimplifiedLogicExpression": "warn",
|
||||
"useOptionalChain": "warn"
|
||||
}
|
||||
}
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": false
|
||||
},
|
||||
"files": {
|
||||
"ignore": [
|
||||
"**/*.js",
|
||||
"**/*.json",
|
||||
"**/*.d.ts",
|
||||
"**/Dockerfile.*",
|
||||
"**/.git/**/*",
|
||||
"**/.vscode/**/*",
|
||||
"**/node_modules/**/*",
|
||||
"**/build/**/*",
|
||||
"**/obj/**/*",
|
||||
"**/dist/**/*",
|
||||
"**/user/**/*",
|
||||
"**/logs/**/*",
|
||||
"**/assets/**/*",
|
||||
"**/Aki_Data/**/*",
|
||||
"**/types/**/*",
|
||||
"**/tests/__cache__/**/*",
|
||||
"**/tests/__coverage__/**/*"
|
||||
]
|
||||
}
|
||||
}
|
@ -1,90 +0,0 @@
|
||||
{
|
||||
"incremental": false,
|
||||
"lineWidth": 120,
|
||||
"indentWidth": 4,
|
||||
"newLineKind": "lf",
|
||||
"useTabs": false,
|
||||
"typescript": {
|
||||
"semiColons": "always",
|
||||
"quoteStyle": "alwaysDouble",
|
||||
"quoteProps": "asNeeded",
|
||||
"useBraces": "always",
|
||||
"bracePosition": "nextLine",
|
||||
"singleBodyPosition": "maintain",
|
||||
"nextControlFlowPosition": "nextLine",
|
||||
"trailingCommas": "onlyMultiLine",
|
||||
"operatorPosition": "nextLine",
|
||||
"preferHanging": false,
|
||||
"preferSingleLine": true,
|
||||
"arrowFunction.useParentheses": "force",
|
||||
"binaryExpression.linePerExpression": false,
|
||||
"memberExpression.linePerExpression": false,
|
||||
"typeLiteral.separatorKind": "semiColon",
|
||||
"enumDeclaration.memberSpacing": "newLine",
|
||||
"spaceAround": false,
|
||||
"spaceSurroundingProperties": true,
|
||||
"objectExpression.spaceSurroundingProperties": true,
|
||||
"objectPattern.spaceSurroundingProperties": true,
|
||||
"typeLiteral.spaceSurroundingProperties": true,
|
||||
"binaryExpression.spaceSurroundingBitwiseAndArithmeticOperator": true,
|
||||
"commentLine.forceSpaceAfterSlashes": true,
|
||||
"constructor.spaceBeforeParentheses": false,
|
||||
"constructorType.spaceAfterNewKeyword": false,
|
||||
"constructSignature.spaceAfterNewKeyword": false,
|
||||
"doWhileStatement.spaceAfterWhileKeyword": true,
|
||||
"module.sortImportDeclarations": "maintain",
|
||||
"module.sortExportDeclarations": "maintain",
|
||||
"exportDeclaration.sortNamedExports": "maintain",
|
||||
"importDeclaration.sortNamedImports": "maintain",
|
||||
"exportDeclaration.spaceSurroundingNamedExports": false,
|
||||
"forInStatement.spaceAfterForKeyword": true,
|
||||
"forOfStatement.spaceAfterForKeyword": true,
|
||||
"forStatement.spaceAfterForKeyword": true,
|
||||
"forStatement.spaceAfterSemiColons": true,
|
||||
"functionDeclaration.spaceBeforeParentheses": false,
|
||||
"functionExpression.spaceBeforeParentheses": false,
|
||||
"functionExpression.spaceAfterFunctionKeyword": false,
|
||||
"getAccessor.spaceBeforeParentheses": false,
|
||||
"ifStatement.spaceAfterIfKeyword": true,
|
||||
"importDeclaration.spaceSurroundingNamedImports": true,
|
||||
"method.spaceBeforeParentheses": false,
|
||||
"setAccessor.spaceBeforeParentheses": false,
|
||||
"taggedTemplate.spaceBeforeLiteral": false,
|
||||
"typeAnnotation.spaceBeforeColon": false,
|
||||
"typeAssertion.spaceBeforeExpression": false,
|
||||
"whileStatement.spaceAfterWhileKeyword": true
|
||||
},
|
||||
"json": {
|
||||
"trailingCommas": "never",
|
||||
"preferSingleLine": false
|
||||
},
|
||||
"markdown": {
|
||||
"textWrap": "always",
|
||||
"emphasisKind": "underscores",
|
||||
"strongKind": "asterisks"
|
||||
},
|
||||
"dockerfile": {},
|
||||
"excludes": [
|
||||
"**/*.js",
|
||||
"**/*.d.ts",
|
||||
"**/*-lock.json",
|
||||
"**/.git/**/*",
|
||||
"**/node_modules/**/*",
|
||||
"**/build/**/*",
|
||||
"**/obj/**/*",
|
||||
"**/dist/**/*",
|
||||
"**/user/**/*",
|
||||
"**/logs/**/*",
|
||||
"**/assets/**/*",
|
||||
"**/Aki_Data/**/*",
|
||||
"**/types/**/*",
|
||||
"**/tests/__cache__/**/*",
|
||||
"**/tests/__coverage__/**/*"
|
||||
],
|
||||
"plugins": [
|
||||
"https://plugins.dprint.dev/typescript-0.88.3.wasm",
|
||||
"https://plugins.dprint.dev/json-0.19.0.wasm",
|
||||
"https://plugins.dprint.dev/markdown-0.16.2.wasm",
|
||||
"https://plugins.dprint.dev/dockerfile-0.3.0.wasm"
|
||||
]
|
||||
}
|
@ -12,10 +12,8 @@
|
||||
},
|
||||
"scripts": {
|
||||
"check:circular": "madge --circular --ts-config tsconfig.json --extensions ts ./src/",
|
||||
"lint": "biome ci src --formatter-enabled=false --max-diagnostics=200",
|
||||
"lint:fix": "biome check --apply-unsafe --max-diagnostics=200 . && dprint fmt --incremental=false",
|
||||
"style": "dprint check --incremental=false",
|
||||
"style:fix": "dprint fmt --incremental=false",
|
||||
"lint": "eslint src",
|
||||
"lint:fix": "eslint src --fix",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
@ -32,7 +30,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"atomically": "~1.7",
|
||||
"buffer-crc32": "^1.0.0",
|
||||
"buffer-crc32": "~1.0",
|
||||
"date-fns": "~2.30",
|
||||
"date-fns-tz": "~2.0",
|
||||
"i18n": "~0.15",
|
||||
@ -51,8 +49,9 @@
|
||||
"ws": "~8.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "~1.6",
|
||||
"@eslint/js": "~9.2",
|
||||
"@pnpm/exe": "8.15.4",
|
||||
"@stylistic/eslint-plugin": "~1.8",
|
||||
"@swc/cli": "~0.3",
|
||||
"@swc/core": "~1.4",
|
||||
"@types/i18n": "~0.13",
|
||||
@ -60,15 +59,16 @@
|
||||
"@types/proper-lockfile": "~4.1",
|
||||
"@types/semver": "~7.5",
|
||||
"@types/ws": "~8.5",
|
||||
"@typescript-eslint/eslint-plugin": "~7.2",
|
||||
"@typescript-eslint/parser": "~7.2",
|
||||
"@typescript-eslint/eslint-plugin": "~7.8",
|
||||
"@typescript-eslint/parser": "~7.8",
|
||||
"@vitest/coverage-istanbul": "~1.3",
|
||||
"@vitest/ui": "~1.3",
|
||||
"@yao-pkg/pkg": "5.11.5",
|
||||
"@yao-pkg/pkg-fetch": "3.5.9",
|
||||
"cross-env": "~7.0",
|
||||
"dprint": "~0.45",
|
||||
"eslint": "~8.57",
|
||||
"eslint-import-resolver-typescript": "~3.6",
|
||||
"eslint-plugin-import": "~2.29",
|
||||
"fs-extra": "~11.2",
|
||||
"gulp": "~4.0",
|
||||
"gulp-decompress": "~3.0",
|
||||
@ -82,6 +82,7 @@
|
||||
"tsconfig-paths": "~4.2",
|
||||
"typedoc": "~0.25",
|
||||
"typemoq": "~2.1",
|
||||
"typescript-eslint": "~7.8",
|
||||
"vitest": "~1.3"
|
||||
},
|
||||
"targets": {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import readline from "node:readline";
|
||||
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { AsyncQueue } from "@spt-aki/utils/AsyncQueue";
|
||||
import { WinstonMainLogger } from "@spt-aki/utils/logging/WinstonMainLogger";
|
||||
@ -24,7 +23,7 @@ export class ErrorHandler
|
||||
this.logger.error(`\nStacktrace:\n${err.stack}`);
|
||||
}
|
||||
|
||||
this.readLine.question("Press Enter to close the window", (_ans) => this.readLine.close());
|
||||
this.readLine.question("Press Enter to close the window", _ans => this.readLine.close());
|
||||
this.readLine.on("close", () => process.exit(1));
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { container } from "tsyringe";
|
||||
|
||||
import { ErrorHandler } from "@spt-aki/ErrorHandler";
|
||||
import { Container } from "@spt-aki/di/Container";
|
||||
import { ErrorHandler } from "@spt-aki/ErrorHandler";
|
||||
import type { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { App } from "@spt-aki/utils/App";
|
||||
import { Watermark } from "@spt-aki/utils/Watermark";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { AchievementController } from "@spt-aki/controllers/AchievementController";
|
||||
import { ProfileController } from "@spt-aki/controllers/ProfileController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
@ -6,7 +7,6 @@ import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyR
|
||||
import { ICompletedAchievementsResponse } from "@spt-aki/models/eft/profile/ICompletedAchievementsResponse";
|
||||
import { IGetAchievementsResponse } from "@spt-aki/models/eft/profile/IGetAchievementsResponse";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class AchievementCallbacks
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotController } from "@spt-aki/controllers/BotController";
|
||||
import { IGenerateBotsRequestData } from "@spt-aki/models/eft/bot/IGenerateBotsRequestData";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { BuildController } from "@spt-aki/controllers/BuildController";
|
||||
import { ISetMagazineRequest } from "@spt-aki/models/eft/builds/ISetMagazineRequest";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
@ -7,7 +8,6 @@ import { IPresetBuildActionRequestData } from "@spt-aki/models/eft/presetBuild/I
|
||||
import { IRemoveBuildRequestData } from "@spt-aki/models/eft/presetBuild/IRemoveBuildRequestData";
|
||||
import { IUserBuilds } from "@spt-aki/models/eft/profile/IAkiProfile";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class BuildsCallbacks
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BundleLoader } from "@spt-aki/loaders/BundleLoader";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
import { IHttpConfig } from "@spt-aki/models/spt/config/IHttpConfig";
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { ClientLogController } from "@spt-aki/controllers/ClientLogController";
|
||||
import { ModLoadOrder } from "@spt-aki/loaders/ModLoadOrder";
|
||||
import { INullResponseData } from "@spt-aki/models/eft/httpResponse/INullResponseData";
|
||||
@ -7,7 +8,6 @@ import { IClientLogRequest } from "@spt-aki/models/spt/logging/IClientLogRequest
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
/** Handle client logging related events */
|
||||
@injectable()
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { CustomizationController } from "@spt-aki/controllers/CustomizationController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HideoutController } from "@spt-aki/controllers/HideoutController";
|
||||
import { RagfairController } from "@spt-aki/controllers/RagfairController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { DialogueController } from "@spt-aki/controllers/DialogueController";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IUIDRequestData } from "@spt-aki/models/eft/common/request/IUIDRequestData";
|
||||
import {
|
||||
IAcceptFriendRequestData,
|
||||
ICancelFriendRequestData,
|
||||
@ -247,14 +247,14 @@ export class DialogueCallbacks implements OnUpdate
|
||||
|
||||
/** Handle client/friend/ignore/set */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public ignoreFriend(url: string, request: { uid: string; }, sessionID: string): INullResponseData
|
||||
public ignoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData
|
||||
{
|
||||
return this.httpResponse.nullResponse();
|
||||
}
|
||||
|
||||
/** Handle client/friend/ignore/remove */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public unIgnoreFriend(url: string, request: { uid: string; }, sessionID: string): INullResponseData
|
||||
public unIgnoreFriend(url: string, request: IUIDRequestData, sessionID: string): INullResponseData
|
||||
{
|
||||
return this.httpResponse.nullResponse();
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { GameController } from "@spt-aki/controllers/GameController";
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IUIDRequestData } from "@spt-aki/models/eft/common/request/IUIDRequestData";
|
||||
import { ICheckVersionResponse } from "@spt-aki/models/eft/game/ICheckVersionResponse";
|
||||
import { ICurrentGroupResponse } from "@spt-aki/models/eft/game/ICurrentGroupResponse";
|
||||
import { IGameConfigResponse } from "@spt-aki/models/eft/game/IGameConfigResponse";
|
||||
@ -14,7 +14,6 @@ import { IGameModeResponse } from "@spt-aki/models/eft/game/IGameModeResponse";
|
||||
import { IGameStartResponse } from "@spt-aki/models/eft/game/IGameStartResponse";
|
||||
import { IGetRaidTimeRequest } from "@spt-aki/models/eft/game/IGetRaidTimeRequest";
|
||||
import { IGetRaidTimeResponse } from "@spt-aki/models/eft/game/IGetRaidTimeResponse";
|
||||
import { IReportNicknameRequestData } from "@spt-aki/models/eft/game/IReportNicknameRequestData";
|
||||
import { IServerDetails } from "@spt-aki/models/eft/game/IServerDetails";
|
||||
import { IVersionValidateRequestData } from "@spt-aki/models/eft/game/IVersionValidateRequestData";
|
||||
import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData";
|
||||
@ -160,7 +159,7 @@ export class GameCallbacks implements OnLoad
|
||||
return this.httpResponse.noBody({ Version: this.watermark.getInGameVersionLabel() });
|
||||
}
|
||||
|
||||
public reportNickname(url: string, info: IReportNicknameRequestData, sessionID: string): INullResponseData
|
||||
public reportNickname(url: string, info: IUIDRequestData, sessionID: string): INullResponseData
|
||||
{
|
||||
return this.httpResponse.nullResponse();
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HandbookController } from "@spt-aki/controllers/HandbookController";
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HealthController } from "@spt-aki/controllers/HealthController";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HideoutController } from "@spt-aki/controllers/HideoutController";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { HttpServer } from "@spt-aki/servers/HttpServer";
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { InraidController } from "@spt-aki/controllers/InraidController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { INullResponseData } from "@spt-aki/models/eft/httpResponse/INullResponseData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { InsuranceController } from "@spt-aki/controllers/InsuranceController";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { InventoryController } from "@spt-aki/controllers/InventoryController";
|
||||
import { QuestController } from "@spt-aki/controllers/QuestController";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData";
|
||||
import { Warning } from "@spt-aki/models/eft/itemEvent/IItemEventRouterBase";
|
||||
import { IItemEventRouterRequest } from "@spt-aki/models/eft/itemEvent/IItemEventRouterRequest";
|
||||
@ -24,7 +23,7 @@ export class ItemEventCallbacks
|
||||
): Promise<IGetBodyResponseData<IItemEventRouterResponse>>
|
||||
{
|
||||
const eventResponse = await this.itemEventRouter.handleEvents(info, sessionID);
|
||||
const result = (this.isCriticalError(eventResponse.warnings))
|
||||
const result = this.isCriticalError(eventResponse.warnings)
|
||||
? this.httpResponse.getBody(
|
||||
eventResponse,
|
||||
this.getErrorCode(eventResponse.warnings),
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { LauncherController } from "@spt-aki/controllers/LauncherController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IChangeRequestData } from "@spt-aki/models/eft/launcher/IChangeRequestData";
|
||||
@ -29,13 +28,13 @@ export class LauncherCallbacks
|
||||
public login(url: string, info: ILoginRequestData, sessionID: string): string
|
||||
{
|
||||
const output = this.launcherController.login(info);
|
||||
return (!output) ? "FAILED" : output;
|
||||
return !output ? "FAILED" : output;
|
||||
}
|
||||
|
||||
public register(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK"
|
||||
{
|
||||
const output = this.launcherController.register(info);
|
||||
return (!output) ? "FAILED" : "OK";
|
||||
return !output ? "FAILED" : "OK";
|
||||
}
|
||||
|
||||
public get(url: string, info: ILoginRequestData, sessionID: string): string
|
||||
@ -47,19 +46,19 @@ export class LauncherCallbacks
|
||||
public changeUsername(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK"
|
||||
{
|
||||
const output = this.launcherController.changeUsername(info);
|
||||
return (!output) ? "FAILED" : "OK";
|
||||
return !output ? "FAILED" : "OK";
|
||||
}
|
||||
|
||||
public changePassword(url: string, info: IChangeRequestData, sessionID: string): "FAILED" | "OK"
|
||||
{
|
||||
const output = this.launcherController.changePassword(info);
|
||||
return (!output) ? "FAILED" : "OK";
|
||||
return !output ? "FAILED" : "OK";
|
||||
}
|
||||
|
||||
public wipe(url: string, info: IRegisterData, sessionID: string): "FAILED" | "OK"
|
||||
{
|
||||
const output = this.launcherController.wipe(info);
|
||||
return (!output) ? "FAILED" : "OK";
|
||||
return !output ? "FAILED" : "OK";
|
||||
}
|
||||
|
||||
public getServerVersion(): string
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { LocationController } from "@spt-aki/controllers/LocationController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { ILocationBase } from "@spt-aki/models/eft/common/ILocationBase";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { MatchController } from "@spt-aki/controllers/MatchController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
@ -112,6 +111,7 @@ export class MatchCallbacks
|
||||
{
|
||||
return this.httpResponse.getBody(true);
|
||||
}
|
||||
|
||||
/** Handle client/match/group/transfer */
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public transferGroup(url: string, info: ITransferGroupRequest, sessionID: string): IGetBodyResponseData<boolean>
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { PostAkiModLoader } from "@spt-aki/loaders/PostAkiModLoader";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { NoteController } from "@spt-aki/controllers/NoteController";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { NotifierController } from "@spt-aki/controllers/NotifierController";
|
||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IUIDRequestData } from "@spt-aki/models/eft/common/request/IUIDRequestData";
|
||||
import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData";
|
||||
import { INotifierChannel } from "@spt-aki/models/eft/notifier/INotifier";
|
||||
import { ISelectProfileRequestData } from "@spt-aki/models/eft/notifier/ISelectProfileRequestData";
|
||||
import { ISelectProfileResponse } from "@spt-aki/models/eft/notifier/ISelectProfileResponse";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
@ -38,8 +37,8 @@ export class NotifierCallbacks
|
||||
* be sent to client as NEWLINE separated strings... yup.
|
||||
*/
|
||||
this.notifierController.notifyAsync(tmpSessionID).then((messages: any) =>
|
||||
messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n")
|
||||
).then((text) => this.httpServerHelper.sendTextJson(resp, text));
|
||||
messages.map((message: any) => this.jsonUtil.serialize(message)).join("\n"),
|
||||
).then(text => this.httpServerHelper.sendTextJson(resp, text));
|
||||
}
|
||||
|
||||
/** Handle push/notifier/get */
|
||||
@ -68,7 +67,7 @@ export class NotifierCallbacks
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
public selectProfile(
|
||||
url: string,
|
||||
info: ISelectProfileRequestData,
|
||||
info: IUIDRequestData,
|
||||
sessionID: string,
|
||||
): IGetBodyResponseData<ISelectProfileResponse>
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { PresetController } from "@spt-aki/controllers/PresetController";
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ProfileController } from "@spt-aki/controllers/ProfileController";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { QuestController } from "@spt-aki/controllers/QuestController";
|
||||
import { RepeatableQuestController } from "@spt-aki/controllers/RepeatableQuestController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RagfairController } from "@spt-aki/controllers/RagfairController";
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RepairController } from "@spt-aki/controllers/RepairController";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { TradeController } from "@spt-aki/controllers/TradeController";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { TraderController } from "@spt-aki/controllers/TraderController";
|
||||
import { OnLoad } from "@spt-aki/di/OnLoad";
|
||||
import { OnUpdate } from "@spt-aki/di/OnUpdate";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { WeatherController } from "@spt-aki/controllers/WeatherController";
|
||||
import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData";
|
||||
import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { WishlistController } from "@spt-aki/controllers/WishlistController";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { injectable } from "tsyringe";
|
||||
|
||||
import { ContextVariable } from "@spt-aki/context/ContextVariable";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { LinkedList } from "@spt-aki/utils/collections/lists/LinkedList";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ICompletedAchievementsResponse } from "@spt-aki/models/eft/profile/ICompletedAchievementsResponse";
|
||||
import { IGetAchievementsResponse } from "@spt-aki/models/eft/profile/IGetAchievementsResponse";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { BotGenerator } from "@spt-aki/generators/BotGenerator";
|
||||
@ -62,7 +61,7 @@ export class BotController
|
||||
*/
|
||||
public getBotPresetGenerationLimit(type: string): number
|
||||
{
|
||||
const value = this.botConfig.presetBatch[(type === "assaultGroup") ? "assault" : type];
|
||||
const value = this.botConfig.presetBatch[type === "assaultGroup" ? "assault" : type];
|
||||
|
||||
if (!value)
|
||||
{
|
||||
@ -148,7 +147,7 @@ export class BotController
|
||||
const result = {};
|
||||
|
||||
const botDb = this.databaseServer.getTables().bots.types;
|
||||
const botTypes = Object.keys(WildSpawnTypeNumber).filter((v) => Number.isNaN(Number(v)));
|
||||
const botTypes = Object.keys(WildSpawnTypeNumber).filter(v => Number.isNaN(Number(v)));
|
||||
for (let botType of botTypes)
|
||||
{
|
||||
const enumType = botType.toLowerCase();
|
||||
@ -212,8 +211,8 @@ export class BotController
|
||||
const raidSettings = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue<
|
||||
IGetRaidConfigurationRequestData
|
||||
>();
|
||||
const pmcLevelRangeForMap =
|
||||
this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings?.location.toLowerCase()];
|
||||
const pmcLevelRangeForMap
|
||||
= this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings?.location.toLowerCase()];
|
||||
|
||||
const allPmcsHaveSameNameAsPlayer = this.randomUtil.getChance100(
|
||||
this.pmcConfig.allPMCsHavePlayerNameWithRandomPrefixChance,
|
||||
@ -239,7 +238,7 @@ export class BotController
|
||||
conditionPromises.push(this.generateWithBotDetails(condition, botGenerationDetails, sessionId));
|
||||
}
|
||||
|
||||
await Promise.all(conditionPromises).then((p) => Promise.all(p));
|
||||
await Promise.all(conditionPromises).then(p => Promise.all(p));
|
||||
|
||||
return [];
|
||||
}
|
||||
@ -326,8 +325,8 @@ export class BotController
|
||||
const raidSettings = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue<
|
||||
IGetRaidConfigurationRequestData
|
||||
>();
|
||||
const pmcLevelRangeForMap =
|
||||
this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings.location.toLowerCase()];
|
||||
const pmcLevelRangeForMap
|
||||
= this.pmcConfig.locationSpecificPmcLevelOverride[raidSettings.location.toLowerCase()];
|
||||
|
||||
// Create gen request for when cache is empty
|
||||
const botGenerationDetails: BotGenerationDetails = {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { ISetMagazineRequest } from "@spt-aki/models/eft/builds/ISetMagazineRequest";
|
||||
@ -43,11 +42,11 @@ export class BuildController
|
||||
const defaultEquipmentPresetsClone = this.jsonUtil.clone(
|
||||
this.databaseServer.getTables().templates.defaultEquipmentPresets,
|
||||
);
|
||||
const playerSecureContainer = profile.characters.pmc.Inventory.items?.find((x) =>
|
||||
x.slotId === secureContainerSlotId
|
||||
const playerSecureContainer = profile.characters.pmc.Inventory.items?.find(x =>
|
||||
x.slotId === secureContainerSlotId,
|
||||
);
|
||||
const firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone[0]?.Items?.find((x) =>
|
||||
x.slotId === secureContainerSlotId
|
||||
const firstDefaultItemsSecureContainer = defaultEquipmentPresetsClone[0]?.Items?.find(x =>
|
||||
x.slotId === secureContainerSlotId,
|
||||
);
|
||||
if (playerSecureContainer && playerSecureContainer?._tpl !== firstDefaultItemsSecureContainer?._tpl)
|
||||
{
|
||||
@ -55,7 +54,7 @@ export class BuildController
|
||||
for (const defaultPreset of defaultEquipmentPresetsClone)
|
||||
{
|
||||
// Find presets secure container
|
||||
const secureContainer = defaultPreset.Items.find((item) => item.slotId === secureContainerSlotId);
|
||||
const secureContainer = defaultPreset.Items.find(item => item.slotId === secureContainerSlotId);
|
||||
if (secureContainer)
|
||||
{
|
||||
secureContainer._tpl = playerSecureContainer._tpl;
|
||||
@ -84,7 +83,7 @@ export class BuildController
|
||||
const newBuild: IWeaponBuild = { Id: body.Id, Name: body.Name, Root: body.Root, Items: body.Items };
|
||||
|
||||
const savedWeaponBuilds = this.saveServer.getProfile(sessionId).userbuilds.weaponBuilds;
|
||||
const existingBuild = savedWeaponBuilds.find((x) => x.Id === body.Id);
|
||||
const existingBuild = savedWeaponBuilds.find(x => x.Id === body.Id);
|
||||
if (existingBuild)
|
||||
{
|
||||
// exists, replace
|
||||
@ -107,8 +106,8 @@ export class BuildController
|
||||
const buildType = "equipmentBuilds";
|
||||
const pmcData = this.profileHelper.getPmcProfile(sessionID);
|
||||
|
||||
const existingSavedEquipmentBuilds: IEquipmentBuild[] =
|
||||
this.saveServer.getProfile(sessionID).userbuilds[buildType];
|
||||
const existingSavedEquipmentBuilds: IEquipmentBuild[] = this.saveServer.getProfile(sessionID)
|
||||
.userbuilds[buildType];
|
||||
|
||||
// Replace duplicate ID's. The first item is the base item.
|
||||
// Root ID and the base item ID need to match.
|
||||
@ -122,8 +121,8 @@ export class BuildController
|
||||
Items: request.Items,
|
||||
};
|
||||
|
||||
const existingBuild = existingSavedEquipmentBuilds.find((build) =>
|
||||
build.Name === request.Name || build.Id === request.Id
|
||||
const existingBuild = existingSavedEquipmentBuilds.find(build =>
|
||||
build.Name === request.Name || build.Id === request.Id,
|
||||
);
|
||||
if (existingBuild)
|
||||
{
|
||||
@ -141,7 +140,7 @@ export class BuildController
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle client/builds/delete*/
|
||||
/** Handle client/builds/delete */
|
||||
public removeBuild(sessionID: string, request: IRemoveBuildRequestData): void
|
||||
{
|
||||
this.removePlayerBuild(request.id, sessionID);
|
||||
@ -155,7 +154,7 @@ export class BuildController
|
||||
const magazineBuilds = profile.userbuilds.magazineBuilds;
|
||||
|
||||
// Check for id in weapon array first
|
||||
const matchingWeaponBuild = weaponBuilds.find((weaponBuild) => weaponBuild.Id === idToRemove);
|
||||
const matchingWeaponBuild = weaponBuilds.find(weaponBuild => weaponBuild.Id === idToRemove);
|
||||
if (matchingWeaponBuild)
|
||||
{
|
||||
weaponBuilds.splice(weaponBuilds.indexOf(matchingWeaponBuild), 1);
|
||||
@ -164,7 +163,7 @@ export class BuildController
|
||||
}
|
||||
|
||||
// Id not found in weapons, try equipment
|
||||
const matchingEquipmentBuild = equipmentBuilds.find((equipmentBuild) => equipmentBuild.Id === idToRemove);
|
||||
const matchingEquipmentBuild = equipmentBuilds.find(equipmentBuild => equipmentBuild.Id === idToRemove);
|
||||
if (matchingEquipmentBuild)
|
||||
{
|
||||
equipmentBuilds.splice(equipmentBuilds.indexOf(matchingEquipmentBuild), 1);
|
||||
@ -173,7 +172,7 @@ export class BuildController
|
||||
}
|
||||
|
||||
// Id not found in weapons/equipment, try mags
|
||||
const matchingMagazineBuild = magazineBuilds.find((magBuild) => magBuild.Id === idToRemove);
|
||||
const matchingMagazineBuild = magazineBuilds.find(magBuild => magBuild.Id === idToRemove);
|
||||
if (matchingMagazineBuild)
|
||||
{
|
||||
magazineBuilds.splice(magazineBuilds.indexOf(matchingMagazineBuild), 1);
|
||||
@ -208,7 +207,7 @@ export class BuildController
|
||||
profile.userbuilds.magazineBuilds = [];
|
||||
}
|
||||
|
||||
const existingArrayId = profile.userbuilds.magazineBuilds.findIndex((item) => item.Name === request.Name);
|
||||
const existingArrayId = profile.userbuilds.magazineBuilds.findIndex(item => item.Name === request.Name);
|
||||
|
||||
if (existingArrayId === -1)
|
||||
{
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
import { IClientLogRequest } from "@spt-aki/models/spt/logging/IClientLogRequest";
|
||||
import { LogBackgroundColor } from "@spt-aki/models/spt/logging/LogBackgroundColor";
|
||||
import { LogLevel } from "@spt-aki/models/spt/logging/LogLevel";
|
||||
import { LogTextColor } from "@spt-aki/models/spt/logging/LogTextColor";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
@injectable()
|
||||
export class ClientLogController
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { ISuit } from "@spt-aki/models/eft/common/tables/ITrader";
|
||||
@ -43,10 +42,10 @@ export class CustomizationController
|
||||
const suits = this.databaseServer.getTables().traders[traderID].suits;
|
||||
|
||||
// Get an inner join of clothing from templates.customization and Ragman's suits array
|
||||
const matchingSuits = suits.filter((x) => x.suiteId in templates);
|
||||
const matchingSuits = suits.filter(x => x.suiteId in templates);
|
||||
|
||||
// Return all suits that have a side array containing the players side (usec/bear)
|
||||
return matchingSuits.filter((x) => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side));
|
||||
return matchingSuits.filter(x => templates[x.suiteId]._props.Side.includes(pmcData.Info.Side));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,7 +132,7 @@ export class CustomizationController
|
||||
|
||||
protected getTraderClothingOffer(sessionId: string, offerId: string): ISuit
|
||||
{
|
||||
return this.getAllTraderSuits(sessionId).find((x) => x._id === offerId);
|
||||
return this.getAllTraderSuits(sessionId).find(x => x._id === offerId);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,7 +180,7 @@ export class CustomizationController
|
||||
output: IItemEventRouterResponse,
|
||||
): void
|
||||
{
|
||||
const relatedItem = pmcData.Inventory.items.find((x) => x._id === clothingItem.id);
|
||||
const relatedItem = pmcData.Inventory.items.find(x => x._id === clothingItem.id);
|
||||
if (!relatedItem)
|
||||
{
|
||||
this.logger.error(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectAll, injectable } from "tsyringe";
|
||||
|
||||
import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot";
|
||||
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
|
||||
import { IGetAllAttachmentsResponse } from "@spt-aki/models/eft/dialog/IGetAllAttachmentsResponse";
|
||||
@ -34,21 +33,21 @@ export class DialogueController
|
||||
// if give command is disabled or commando commands are disabled
|
||||
if (!coreConfigs.features?.chatbotFeatures?.commandoEnabled)
|
||||
{
|
||||
const sptCommando = this.dialogueChatBots.find((c) =>
|
||||
c.getChatBot()._id.toLocaleLowerCase() === "sptcommando"
|
||||
const sptCommando = this.dialogueChatBots.find(c =>
|
||||
c.getChatBot()._id.toLocaleLowerCase() === "sptcommando",
|
||||
);
|
||||
this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptCommando), 1);
|
||||
}
|
||||
if (!coreConfigs.features?.chatbotFeatures?.sptFriendEnabled)
|
||||
{
|
||||
const sptFriend = this.dialogueChatBots.find((c) => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend");
|
||||
const sptFriend = this.dialogueChatBots.find(c => c.getChatBot()._id.toLocaleLowerCase() === "sptFriend");
|
||||
this.dialogueChatBots.splice(this.dialogueChatBots.indexOf(sptFriend), 1);
|
||||
}
|
||||
}
|
||||
|
||||
public registerChatBot(chatBot: IDialogueChatBot): void
|
||||
{
|
||||
if (this.dialogueChatBots.some((cb) => cb.getChatBot()._id === chatBot.getChatBot()._id))
|
||||
if (this.dialogueChatBots.some(cb => cb.getChatBot()._id === chatBot.getChatBot()._id))
|
||||
{
|
||||
throw new Error(`The chat bot ${chatBot.getChatBot()._id} being registered already exists!`);
|
||||
}
|
||||
@ -73,7 +72,7 @@ export class DialogueController
|
||||
public getFriendList(sessionID: string): IGetFriendListDataResponse
|
||||
{
|
||||
// Force a fake friend called SPT into friend list
|
||||
return { Friends: this.dialogueChatBots.map((v) => v.getChatBot()), Ignore: [], InIgnoreList: [] };
|
||||
return { Friends: this.dialogueChatBots.map(v => v.getChatBot()), Ignore: [], InIgnoreList: [] };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -117,6 +116,7 @@ export class DialogueController
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users involved in a dialog (player + other party)
|
||||
* @param dialog The dialog to check for users
|
||||
@ -131,7 +131,7 @@ export class DialogueController
|
||||
// User to user messages are special in that they need the player to exist in them, add if they don't
|
||||
if (
|
||||
messageType === MessageType.USER_MESSAGE
|
||||
&& !dialog.Users?.find((userDialog) => userDialog._id === profile.characters.pmc.sessionId)
|
||||
&& !dialog.Users?.find(userDialog => userDialog._id === profile.characters.pmc.sessionId)
|
||||
)
|
||||
{
|
||||
if (!dialog.Users)
|
||||
@ -207,7 +207,7 @@ export class DialogueController
|
||||
if (request.type === MessageType.USER_MESSAGE)
|
||||
{
|
||||
profile.dialogues[request.dialogId].Users = [];
|
||||
const chatBot = this.dialogueChatBots.find((cb) => cb.getChatBot()._id === request.dialogId);
|
||||
const chatBot = this.dialogueChatBots.find(cb => cb.getChatBot()._id === request.dialogId);
|
||||
if (chatBot)
|
||||
{
|
||||
profile.dialogues[request.dialogId].Users.push(chatBot.getChatBot());
|
||||
@ -217,6 +217,7 @@ export class DialogueController
|
||||
|
||||
return profile.dialogues[request.dialogId];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the users involved in a mail between two entities
|
||||
* @param fullProfile Player profile
|
||||
@ -230,7 +231,7 @@ export class DialogueController
|
||||
{
|
||||
result.push(...dialogUsers);
|
||||
|
||||
if (!result.find((userDialog) => userDialog._id === fullProfile.info.id))
|
||||
if (!result.find(userDialog => userDialog._id === fullProfile.info.id))
|
||||
{
|
||||
// Player doesnt exist, add them in before returning
|
||||
const pmcProfile = fullProfile.characters.pmc;
|
||||
@ -278,7 +279,7 @@ export class DialogueController
|
||||
*/
|
||||
protected messagesHaveUncollectedRewards(messages: Message[]): boolean
|
||||
{
|
||||
return messages.some((message) => message.items?.data?.length > 0);
|
||||
return messages.some(message => message.items?.data?.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -375,7 +376,7 @@ export class DialogueController
|
||||
{
|
||||
this.mailSendService.sendPlayerMessageToNpc(sessionId, request.dialogId, request.text);
|
||||
|
||||
return this.dialogueChatBots.find((cb) => cb.getChatBot()._id === request.dialogId)?.handleMessage(
|
||||
return this.dialogueChatBots.find(cb => cb.getChatBot()._id === request.dialogId)?.handleMessage(
|
||||
sessionId,
|
||||
request,
|
||||
) ?? request.dialogId;
|
||||
@ -391,7 +392,7 @@ export class DialogueController
|
||||
{
|
||||
const timeNow = this.timeUtil.getTimestamp();
|
||||
const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId);
|
||||
return dialogs[dialogueId].messages.filter((message) => timeNow < (message.dt + message.maxStorageTime));
|
||||
return dialogs[dialogueId].messages.filter(message => timeNow < message.dt + message.maxStorageTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,7 +402,7 @@ export class DialogueController
|
||||
*/
|
||||
protected getMessagesWithAttachments(messages: Message[]): Message[]
|
||||
{
|
||||
return messages.filter((message) => message.items?.data?.length > 0);
|
||||
return messages.filter(message => message.items?.data?.length > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -446,6 +447,6 @@ export class DialogueController
|
||||
*/
|
||||
protected messageHasExpired(message: Message): boolean
|
||||
{
|
||||
return (this.timeUtil.getTimestamp()) > (message.dt + message.maxStorageTime);
|
||||
return this.timeUtil.getTimestamp() > message.dt + message.maxStorageTime;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
||||
@ -360,8 +359,8 @@ export class GameController
|
||||
for (const positionToAdd of positionsToAdd)
|
||||
{
|
||||
// Exists already, add new items to existing positions pool
|
||||
const existingLootPosition = mapLooseLoot.spawnpoints.find((x) =>
|
||||
x.template.Id === positionToAdd.template.Id
|
||||
const existingLootPosition = mapLooseLoot.spawnpoints.find(x =>
|
||||
x.template.Id === positionToAdd.template.Id,
|
||||
);
|
||||
if (existingLootPosition)
|
||||
{
|
||||
@ -391,7 +390,7 @@ export class GameController
|
||||
const mapLootAdjustmentsDict = adjustments[mapId];
|
||||
for (const lootKey in mapLootAdjustmentsDict)
|
||||
{
|
||||
const lootPostionToAdjust = mapLooseLootData.spawnpoints.find((x) => x.template.Id === lootKey);
|
||||
const lootPostionToAdjust = mapLooseLootData.spawnpoints.find(x => x.template.Id === lootKey);
|
||||
if (!lootPostionToAdjust)
|
||||
{
|
||||
this.logger.warning(`Unable to adjust loot position: ${lootKey} on map: ${mapId}`);
|
||||
@ -424,7 +423,7 @@ export class GameController
|
||||
|
||||
for (const botToLimit of this.locationConfig.botTypeLimits[mapId])
|
||||
{
|
||||
const index = map.base.MinMaxBots.findIndex((x) => x.WildSpawnType === botToLimit.type);
|
||||
const index = map.base.MinMaxBots.findIndex(x => x.WildSpawnType === botToLimit.type);
|
||||
if (index !== -1)
|
||||
{
|
||||
// Existing bot type found in MinMaxBots array, edit
|
||||
@ -452,9 +451,9 @@ export class GameController
|
||||
public getGameConfig(sessionID: string): IGameConfigResponse
|
||||
{
|
||||
const profile = this.profileHelper.getPmcProfile(sessionID);
|
||||
const gameTime =
|
||||
profile.Stats?.Eft.OverallCounters.Items?.find((counter) =>
|
||||
counter.Key.includes("LifeTime") && counter.Key.includes("Pmc")
|
||||
const gameTime
|
||||
= profile.Stats?.Eft.OverallCounters.Items?.find(counter =>
|
||||
counter.Key.includes("LifeTime") && counter.Key.includes("Pmc"),
|
||||
)?.Value ?? 0;
|
||||
|
||||
const config: IGameConfigResponse = {
|
||||
@ -599,12 +598,12 @@ export class GameController
|
||||
let hpRegenPerHour = 456.6;
|
||||
|
||||
// Set new values, whatever is smallest
|
||||
energyRegenPerHour += pmcProfile.Bonuses.filter((bonus) => bonus.type === BonusType.ENERGY_REGENERATION)
|
||||
energyRegenPerHour += pmcProfile.Bonuses.filter(bonus => bonus.type === BonusType.ENERGY_REGENERATION)
|
||||
.reduce((sum, curr) => sum + curr.value, 0);
|
||||
hydrationRegenPerHour += pmcProfile.Bonuses.filter((bonus) =>
|
||||
bonus.type === BonusType.HYDRATION_REGENERATION
|
||||
hydrationRegenPerHour += pmcProfile.Bonuses.filter(bonus =>
|
||||
bonus.type === BonusType.HYDRATION_REGENERATION,
|
||||
).reduce((sum, curr) => sum + curr.value, 0);
|
||||
hpRegenPerHour += pmcProfile.Bonuses.filter((bonus) => bonus.type === BonusType.HEALTH_REGENERATION).reduce(
|
||||
hpRegenPerHour += pmcProfile.Bonuses.filter(bonus => bonus.type === BonusType.HEALTH_REGENERATION).reduce(
|
||||
(sum, curr) => sum + curr.value,
|
||||
0,
|
||||
);
|
||||
@ -701,7 +700,7 @@ export class GameController
|
||||
|
||||
for (const wave of location.base.waves ?? [])
|
||||
{
|
||||
if ((wave.slots_max - wave.slots_min === 0))
|
||||
if (wave.slots_max - wave.slots_min === 0)
|
||||
{
|
||||
this.logger.debug(
|
||||
`Fixed ${wave.WildSpawnType} Spawn: ${locationKey} wave: ${wave.number} of type: ${wave.WildSpawnType} in zone: ${wave.SpawnPoints} with Max Slots of ${wave.slots_max}`,
|
||||
@ -739,13 +738,13 @@ export class GameController
|
||||
const currentTimeStamp = this.timeUtil.getTimestamp();
|
||||
|
||||
// One day post-profile creation
|
||||
if (currentTimeStamp > (timeStampProfileCreated + oneDaySeconds))
|
||||
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds)
|
||||
{
|
||||
this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 1);
|
||||
}
|
||||
|
||||
// Two day post-profile creation
|
||||
if (currentTimeStamp > (timeStampProfileCreated + (oneDaySeconds * 2)))
|
||||
if (currentTimeStamp > timeStampProfileCreated + oneDaySeconds * 2)
|
||||
{
|
||||
this.giftService.sendPraporStartingGift(pmcProfile.sessionId, 2);
|
||||
}
|
||||
@ -771,7 +770,7 @@ export class GameController
|
||||
// Wave has size that makes it candidate for splitting
|
||||
if (
|
||||
wave.slots_max - wave.slots_min
|
||||
>= this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold
|
||||
>= this.locationConfig.splitWaveIntoSingleSpawnsSettings.waveSizeThreshold
|
||||
)
|
||||
{
|
||||
// Get count of bots to be spawned in wave
|
||||
@ -842,8 +841,8 @@ export class GameController
|
||||
{
|
||||
const modDetails = activeMods[modKey];
|
||||
if (
|
||||
fullProfile.aki.mods.some((x) =>
|
||||
x.author === modDetails.author && x.name === modDetails.name && x.version === modDetails.version
|
||||
fullProfile.aki.mods.some(x =>
|
||||
x.author === modDetails.author && x.name === modDetails.name && x.version === modDetails.version,
|
||||
)
|
||||
)
|
||||
{
|
||||
@ -958,8 +957,8 @@ export class GameController
|
||||
protected adjustLabsRaiderSpawnRate(): void
|
||||
{
|
||||
const labsBase = this.databaseServer.getTables().locations.laboratory.base;
|
||||
const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter((x) =>
|
||||
x.TriggerId === "" && x.TriggerName === ""
|
||||
const nonTriggerLabsBossSpawns = labsBase.BossLocationSpawn.filter(x =>
|
||||
x.TriggerId === "" && x.TriggerName === "",
|
||||
);
|
||||
if (nonTriggerLabsBossSpawns)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HealthHelper } from "@spt-aki/helpers/HealthHelper";
|
||||
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
@ -66,7 +65,7 @@ export class HealthController
|
||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||
|
||||
// Update medkit used (hpresource)
|
||||
const healingItemToUse = pmcData.Inventory.items.find((item) => item._id === request.item);
|
||||
const healingItemToUse = pmcData.Inventory.items.find(item => item._id === request.item);
|
||||
if (!healingItemToUse)
|
||||
{
|
||||
const errorMessage = this.localisationService.getText(
|
||||
@ -114,7 +113,7 @@ export class HealthController
|
||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||
let resourceLeft = 0;
|
||||
|
||||
const itemToConsume = pmcData.Inventory.items.find((x) => x._id === request.item);
|
||||
const itemToConsume = pmcData.Inventory.items.find(x => x._id === request.item);
|
||||
if (!itemToConsume)
|
||||
{
|
||||
// Item not found, very bad
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ScavCaseRewardGenerator } from "@spt-aki/generators/ScavCaseRewardGenerator";
|
||||
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
||||
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
||||
@ -106,7 +105,7 @@ export class HideoutController
|
||||
{
|
||||
const items = request.items.map((reqItem) =>
|
||||
{
|
||||
const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id);
|
||||
const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id);
|
||||
return { inventoryItem: item, requestedItem: reqItem };
|
||||
});
|
||||
|
||||
@ -139,7 +138,7 @@ export class HideoutController
|
||||
}
|
||||
|
||||
// Construction time management
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
|
||||
if (!profileHideoutArea)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
|
||||
@ -148,8 +147,8 @@ export class HideoutController
|
||||
return;
|
||||
}
|
||||
|
||||
const hideoutDataDb = this.databaseServer.getTables().hideout.areas.find((area) =>
|
||||
area.type === request.areaType
|
||||
const hideoutDataDb = this.databaseServer.getTables().hideout.areas.find(area =>
|
||||
area.type === request.areaType,
|
||||
);
|
||||
if (!hideoutDataDb)
|
||||
{
|
||||
@ -192,7 +191,7 @@ export class HideoutController
|
||||
{
|
||||
const db = this.databaseServer.getTables();
|
||||
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
|
||||
if (!profileHideoutArea)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
|
||||
@ -206,7 +205,7 @@ export class HideoutController
|
||||
profileHideoutArea.completeTime = 0;
|
||||
profileHideoutArea.constructing = false;
|
||||
|
||||
const hideoutData = db.hideout.areas.find((area) => area.type === profileHideoutArea.type);
|
||||
const hideoutData = db.hideout.areas.find(area => area.type === profileHideoutArea.type);
|
||||
if (!hideoutData)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -264,11 +263,11 @@ export class HideoutController
|
||||
*/
|
||||
protected checkAndUpgradeWall(pmcData: IPmcData): void
|
||||
{
|
||||
const medStation = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.MEDSTATION);
|
||||
const waterCollector = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.WATER_COLLECTOR);
|
||||
const medStation = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.MEDSTATION);
|
||||
const waterCollector = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.WATER_COLLECTOR);
|
||||
if (medStation?.level >= 1 && waterCollector?.level >= 1)
|
||||
{
|
||||
const wall = pmcData.Hideout.Areas.find((area) => area.type === HideoutAreas.EMERGENCY_WALL);
|
||||
const wall = pmcData.Hideout.Areas.find(area => area.type === HideoutAreas.EMERGENCY_WALL);
|
||||
if (wall?.level === 0)
|
||||
{
|
||||
wall.level = 3;
|
||||
@ -310,8 +309,8 @@ export class HideoutController
|
||||
}
|
||||
|
||||
// Some areas like gun stand have a child area linked to it, it needs to do the same as above
|
||||
const childDbArea = this.databaseServer.getTables().hideout.areas.find((x) =>
|
||||
x.parentArea === dbHideoutArea._id
|
||||
const childDbArea = this.databaseServer.getTables().hideout.areas.find(x =>
|
||||
x.parentArea === dbHideoutArea._id,
|
||||
);
|
||||
if (childDbArea)
|
||||
{
|
||||
@ -322,8 +321,8 @@ export class HideoutController
|
||||
}
|
||||
|
||||
// Set child area level to same as parent area
|
||||
pmcData.Hideout.Areas.find((x) => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find((x) =>
|
||||
x.type === profileParentHideoutArea.type
|
||||
pmcData.Hideout.Areas.find(x => x.type === childDbArea.type).level = pmcData.Hideout.Areas.find(x =>
|
||||
x.type === profileParentHideoutArea.type,
|
||||
).level;
|
||||
|
||||
// Add/upgrade stash item in player inventory
|
||||
@ -343,7 +342,7 @@ export class HideoutController
|
||||
*/
|
||||
protected addUpdateInventoryItemToProfile(pmcData: IPmcData, dbHideoutData: IHideoutArea, hideoutStage: Stage): void
|
||||
{
|
||||
const existingInventoryItem = pmcData.Inventory.items.find((x) => x._id === dbHideoutData._id);
|
||||
const existingInventoryItem = pmcData.Inventory.items.find(x => x._id === dbHideoutData._id);
|
||||
if (existingInventoryItem)
|
||||
{
|
||||
// Update existing items container tpl to point to new id (tpl)
|
||||
@ -400,11 +399,11 @@ export class HideoutController
|
||||
|
||||
const itemsToAdd = Object.entries(addItemToHideoutRequest.items).map((kvp) =>
|
||||
{
|
||||
const item = pmcData.Inventory.items.find((invItem) => invItem._id === kvp[1].id);
|
||||
const item = pmcData.Inventory.items.find(invItem => invItem._id === kvp[1].id);
|
||||
return { inventoryItem: item, requestedItem: kvp[1], slot: kvp[0] };
|
||||
});
|
||||
|
||||
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === addItemToHideoutRequest.areaType);
|
||||
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === addItemToHideoutRequest.areaType);
|
||||
if (!hideoutArea)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -431,7 +430,7 @@ export class HideoutController
|
||||
|
||||
// Add item to area.slots
|
||||
const destinationLocationIndex = Number(item.slot);
|
||||
const hideoutSlotIndex = hideoutArea.slots.findIndex((x) => x.locationIndex === destinationLocationIndex);
|
||||
const hideoutSlotIndex = hideoutArea.slots.findIndex(x => x.locationIndex === destinationLocationIndex);
|
||||
hideoutArea.slots[hideoutSlotIndex].item = [{
|
||||
_id: item.inventoryItem._id,
|
||||
_tpl: item.inventoryItem._tpl,
|
||||
@ -463,7 +462,7 @@ export class HideoutController
|
||||
{
|
||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||
|
||||
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
|
||||
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
|
||||
if (!hideoutArea)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
|
||||
@ -520,7 +519,7 @@ export class HideoutController
|
||||
const slotIndexToRemove = removeResourceRequest.slots[0];
|
||||
|
||||
// Assume only one item in slot
|
||||
const itemToReturn = hideoutArea.slots.find((slot) => slot.locationIndex === slotIndexToRemove).item[0];
|
||||
const itemToReturn = hideoutArea.slots.find(slot => slot.locationIndex === slotIndexToRemove).item[0];
|
||||
|
||||
const request: IAddItemDirectRequest = {
|
||||
itemWithModsToAdd: [itemToReturn],
|
||||
@ -537,7 +536,7 @@ export class HideoutController
|
||||
}
|
||||
|
||||
// Remove items from slot, locationIndex remains
|
||||
const hideoutSlotIndex = hideoutArea.slots.findIndex((slot) => slot.locationIndex === slotIndexToRemove);
|
||||
const hideoutSlotIndex = hideoutArea.slots.findIndex(slot => slot.locationIndex === slotIndexToRemove);
|
||||
hideoutArea.slots[hideoutSlotIndex].item = undefined;
|
||||
|
||||
return output;
|
||||
@ -562,7 +561,7 @@ export class HideoutController
|
||||
// Force a production update (occur before area is toggled as it could be generator and doing it after generator enabled would cause incorrect calculaton of production progress)
|
||||
this.hideoutHelper.updatePlayerHideout(sessionID);
|
||||
|
||||
const hideoutArea = pmcData.Hideout.Areas.find((area) => area.type === request.areaType);
|
||||
const hideoutArea = pmcData.Hideout.Areas.find(area => area.type === request.areaType);
|
||||
if (!hideoutArea)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
|
||||
@ -592,20 +591,20 @@ export class HideoutController
|
||||
this.hideoutHelper.registerProduction(pmcData, body, sessionID);
|
||||
|
||||
// Find the recipe of the production
|
||||
const recipe = this.databaseServer.getTables().hideout.production.find((p) => p._id === body.recipeId);
|
||||
const recipe = this.databaseServer.getTables().hideout.production.find(p => p._id === body.recipeId);
|
||||
|
||||
// Find the actual amount of items we need to remove because body can send weird data
|
||||
const recipeRequirementsClone = this.jsonUtil.clone(
|
||||
recipe.requirements.filter((i) => i.type === "Item" || i.type === "Tool"),
|
||||
recipe.requirements.filter(i => i.type === "Item" || i.type === "Tool"),
|
||||
);
|
||||
|
||||
const output = this.eventOutputHolder.getOutput(sessionID);
|
||||
const itemsToDelete = body.items.concat(body.tools);
|
||||
for (const itemToDelete of itemsToDelete)
|
||||
{
|
||||
const itemToCheck = pmcData.Inventory.items.find((i) => i._id === itemToDelete.id);
|
||||
const requirement = recipeRequirementsClone.find((requirement) =>
|
||||
requirement.templateId === itemToCheck._tpl
|
||||
const itemToCheck = pmcData.Inventory.items.find(i => i._id === itemToDelete.id);
|
||||
const requirement = recipeRequirementsClone.find(requirement =>
|
||||
requirement.templateId === itemToCheck._tpl,
|
||||
);
|
||||
|
||||
// Handle tools not having a `count`, but always only requiring 1
|
||||
@ -645,7 +644,7 @@ export class HideoutController
|
||||
|
||||
for (const requestedItem of body.items)
|
||||
{
|
||||
const inventoryItem = pmcData.Inventory.items.find((item) => item._id === requestedItem.id);
|
||||
const inventoryItem = pmcData.Inventory.items.find(item => item._id === requestedItem.id);
|
||||
if (!inventoryItem)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -667,7 +666,7 @@ export class HideoutController
|
||||
}
|
||||
}
|
||||
|
||||
const recipe = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === body.recipeId);
|
||||
const recipe = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === body.recipeId);
|
||||
if (!recipe)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -679,13 +678,12 @@ export class HideoutController
|
||||
// @Important: Here we need to be very exact:
|
||||
// - normal recipe: Production time value is stored in attribute "productionTime" with small "p"
|
||||
// - scav case recipe: Production time value is stored in attribute "ProductionTime" with capital "P"
|
||||
const adjustedCraftTime = recipe.ProductionTime
|
||||
- this.hideoutHelper.getSkillProductionTimeReduction(
|
||||
pmcData,
|
||||
recipe.ProductionTime,
|
||||
SkillTypes.CRAFTING,
|
||||
this.databaseServer.getTables().globals.config.SkillsSettings.Crafting.CraftTimeReductionPerLevel,
|
||||
);
|
||||
const adjustedCraftTime = recipe.ProductionTime - this.hideoutHelper.getSkillProductionTimeReduction(
|
||||
pmcData,
|
||||
recipe.ProductionTime,
|
||||
SkillTypes.CRAFTING,
|
||||
this.databaseServer.getTables().globals.config.SkillsSettings.Crafting.CraftTimeReductionPerLevel,
|
||||
);
|
||||
|
||||
const modifiedScavCaseTime = this.getScavCaseTime(pmcData, adjustedCraftTime);
|
||||
|
||||
@ -772,7 +770,7 @@ export class HideoutController
|
||||
return output;
|
||||
}
|
||||
|
||||
const recipe = hideoutDb.production.find((r) => r._id === request.recipeId);
|
||||
const recipe = hideoutDb.production.find(r => r._id === request.recipeId);
|
||||
if (recipe)
|
||||
{
|
||||
this.handleRecipe(sessionID, recipe, pmcData, request, output);
|
||||
@ -780,7 +778,7 @@ export class HideoutController
|
||||
return output;
|
||||
}
|
||||
|
||||
const scavCase = hideoutDb.scavcase.find((r) => r._id === request.recipeId);
|
||||
const scavCase = hideoutDb.scavcase.find(r => r._id === request.recipeId);
|
||||
if (scavCase)
|
||||
{
|
||||
this.handleScavCase(sessionID, pmcData, request, output);
|
||||
@ -938,7 +936,7 @@ export class HideoutController
|
||||
}
|
||||
|
||||
// Check if the recipe is the same as the last one - get bonus when crafting same thing multiple times
|
||||
const area = pmcData.Hideout.Areas.find((area) => area.type === recipe.areaType);
|
||||
const area = pmcData.Hideout.Areas.find(area => area.type === recipe.areaType);
|
||||
if (area && request.recipeId !== area.lastRecipe)
|
||||
{
|
||||
// 1 point per craft upon the end of production for alternating between 2 different crafting recipes in the same module
|
||||
@ -948,7 +946,7 @@ export class HideoutController
|
||||
// Update variable with time spent crafting item(s)
|
||||
// 1 point per 8 hours of crafting
|
||||
hoursCrafting += recipe.productionTime;
|
||||
if ((hoursCrafting / this.hideoutConfig.hoursForSkillCrafting) >= 1)
|
||||
if (hoursCrafting / this.hideoutConfig.hoursForSkillCrafting >= 1)
|
||||
{
|
||||
// Spent enough time crafting to get a bonus xp multipler
|
||||
const multiplierCrafting = Math.floor(hoursCrafting / this.hideoutConfig.hoursForSkillCrafting);
|
||||
@ -1016,7 +1014,7 @@ export class HideoutController
|
||||
{
|
||||
this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.CRAFTING, craftingExpAmount);
|
||||
|
||||
const intellectAmountToGive = 0.5 * (Math.round(craftingExpAmount / 15));
|
||||
const intellectAmountToGive = 0.5 * Math.round(craftingExpAmount / 15);
|
||||
if (intellectAmountToGive > 0)
|
||||
{
|
||||
this.profileHelper.addSkillPointsToPlayer(pmcData, SkillTypes.INTELLECT, intellectAmountToGive);
|
||||
@ -1189,14 +1187,14 @@ export class HideoutController
|
||||
public recordShootingRangePoints(sessionId: string, pmcData: IPmcData, request: IRecordShootingRangePoints): void
|
||||
{
|
||||
// Check if counter exists, add placeholder if it doesnt
|
||||
if (!pmcData.Stats.Eft.OverallCounters.Items.find((x) => x.Key.includes("ShootingRangePoints")))
|
||||
if (!pmcData.Stats.Eft.OverallCounters.Items.find(x => x.Key.includes("ShootingRangePoints")))
|
||||
{
|
||||
pmcData.Stats.Eft.OverallCounters.Items.push({ Key: ["ShootingRangePoints"], Value: 0 });
|
||||
}
|
||||
|
||||
// Find counter by key and update value
|
||||
const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find((x) =>
|
||||
x.Key.includes("ShootingRangePoints")
|
||||
const shootingRangeHighScore = pmcData.Stats.Eft.OverallCounters.Items.find(x =>
|
||||
x.Key.includes("ShootingRangePoints"),
|
||||
);
|
||||
shootingRangeHighScore.Value = request.points;
|
||||
}
|
||||
@ -1218,7 +1216,7 @@ export class HideoutController
|
||||
// Create mapping of required item with corrisponding item from player inventory
|
||||
const items = request.items.map((reqItem) =>
|
||||
{
|
||||
const item = pmcData.Inventory.items.find((invItem) => invItem._id === reqItem.id);
|
||||
const item = pmcData.Inventory.items.find(invItem => invItem._id === reqItem.id);
|
||||
return { inventoryItem: item, requestedItem: reqItem };
|
||||
});
|
||||
|
||||
@ -1248,14 +1246,14 @@ export class HideoutController
|
||||
}
|
||||
}
|
||||
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find((x) => x.type === request.areaType);
|
||||
const profileHideoutArea = pmcData.Hideout.Areas.find(x => x.type === request.areaType);
|
||||
if (!profileHideoutArea)
|
||||
{
|
||||
this.logger.error(this.localisationService.getText("hideout-unable_to_find_area", request.areaType));
|
||||
return this.httpResponse.appendErrorToOutput(output);
|
||||
}
|
||||
|
||||
const hideoutDbData = this.databaseServer.getTables().hideout.areas.find((x) => x.type === request.areaType);
|
||||
const hideoutDbData = this.databaseServer.getTables().hideout.areas.find(x => x.type === request.areaType);
|
||||
if (!hideoutDbData)
|
||||
{
|
||||
this.logger.error(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { PlayerScavGenerator } from "@spt-aki/generators/PlayerScavGenerator";
|
||||
@ -204,8 +203,8 @@ export class InraidController
|
||||
if (locationName === "lighthouse" && postRaidRequest.profile.Info.Side.toLowerCase() === "usec")
|
||||
{
|
||||
// Decrement counter if it exists, don't go below 0
|
||||
const remainingCounter = serverPmcProfile?.Stats.Eft.OverallCounters.Items.find((x) =>
|
||||
x.Key.includes("UsecRaidRemainKills")
|
||||
const remainingCounter = serverPmcProfile?.Stats.Eft.OverallCounters.Items.find(x =>
|
||||
x.Key.includes("UsecRaidRemainKills"),
|
||||
);
|
||||
if (remainingCounter?.Value > 0)
|
||||
{
|
||||
@ -229,9 +228,9 @@ export class InraidController
|
||||
// Not dead
|
||||
|
||||
// Check for cultist amulets in special slot (only slot it can fit)
|
||||
const amuletOnPlayer = serverPmcProfile.Inventory.items.filter((item) =>
|
||||
item.slotId?.startsWith("SpecialSlot")
|
||||
).find((item) => item._tpl === "64d0b40fbe2eed70e254e2d4");
|
||||
const amuletOnPlayer = serverPmcProfile.Inventory.items.filter(item =>
|
||||
item.slotId?.startsWith("SpecialSlot"),
|
||||
).find(item => item._tpl === "64d0b40fbe2eed70e254e2d4");
|
||||
if (amuletOnPlayer)
|
||||
{
|
||||
// No charges left, delete it
|
||||
@ -250,8 +249,8 @@ export class InraidController
|
||||
}
|
||||
}
|
||||
|
||||
const victims = postRaidRequest.profile.Stats.Eft.Victims.filter((x) =>
|
||||
["sptbear", "sptusec"].includes(x.Role.toLowerCase())
|
||||
const victims = postRaidRequest.profile.Stats.Eft.Victims.filter(x =>
|
||||
["sptbear", "sptusec"].includes(x.Role.toLowerCase()),
|
||||
);
|
||||
if (victims?.length > 0)
|
||||
{
|
||||
@ -283,9 +282,13 @@ export class InraidController
|
||||
// Find and remove the completed condition from profile if player died, otherwise quest is stuck in limbo
|
||||
// and quest items cannot be picked up again
|
||||
const allQuests = this.questHelper.getQuestsFromDb();
|
||||
const activeQuestIdsInProfile = pmcData.Quests.filter((profileQuest) =>
|
||||
![QuestStatus.AvailableForStart, QuestStatus.Success, QuestStatus.Expired].includes(profileQuest.status)
|
||||
).map((x) => x.qid);
|
||||
const activeQuestIdsInProfile = pmcData.Quests.filter(
|
||||
profileQuest => ![
|
||||
QuestStatus.AvailableForStart,
|
||||
QuestStatus.Success,
|
||||
QuestStatus.Expired,
|
||||
].includes(profileQuest.status),
|
||||
).map(x => x.qid);
|
||||
for (const questItem of postRaidSaveRequest.profile.Stats.Eft.CarriedQuestItems)
|
||||
{
|
||||
// Get quest/find condition for carried quest item
|
||||
@ -399,7 +402,7 @@ export class InraidController
|
||||
*/
|
||||
protected mergePmcAndScavEncyclopedias(primary: IPmcData, secondary: IPmcData): void
|
||||
{
|
||||
function extend(target: { [key: string]: boolean; }, source: Record<string, boolean>)
|
||||
function extend(target: { [key: string]: boolean }, source: Record<string, boolean>)
|
||||
{
|
||||
for (const key in source)
|
||||
{
|
||||
@ -469,7 +472,7 @@ export class InraidController
|
||||
|
||||
for (const quest of scavProfile.Quests)
|
||||
{
|
||||
const pmcQuest = pmcProfile.Quests.find((x) => x.qid === quest.qid);
|
||||
const pmcQuest = pmcProfile.Quests.find(x => x.qid === quest.qid);
|
||||
if (!pmcQuest)
|
||||
{
|
||||
this.logger.warning(`No PMC quest found for ID: ${quest.qid}`);
|
||||
@ -504,7 +507,7 @@ export class InraidController
|
||||
for (const scavCounter of Object.values(scavProfile.TaskConditionCounters))
|
||||
{
|
||||
// If this is an achievement that isn't for the scav, don't process it
|
||||
const achievement = achievements.find((achievement) => achievement.id === scavCounter.sourceId);
|
||||
const achievement = achievements.find(achievement => achievement.id === scavCounter.sourceId);
|
||||
if (achievement && achievement.side !== "Savage")
|
||||
{
|
||||
continue;
|
||||
@ -541,7 +544,7 @@ export class InraidController
|
||||
*/
|
||||
protected isPlayerDead(statusOnExit: PlayerRaidEndState): boolean
|
||||
{
|
||||
return (statusOnExit !== PlayerRaidEndState.SURVIVED && statusOnExit !== PlayerRaidEndState.RUNNER);
|
||||
return statusOnExit !== PlayerRaidEndState.SURVIVED && statusOnExit !== PlayerRaidEndState.RUNNER;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -686,8 +689,8 @@ export class InraidController
|
||||
|
||||
// Remove any items that were returned by the item delivery, but also insured, from the player's insurance list
|
||||
// This is to stop items being duplicated by being returned from both the item delivery, and insurance
|
||||
const deliveredItemIds = items.map((x) => x._id);
|
||||
pmcData.InsuredItems = pmcData.InsuredItems.filter((x) => !deliveredItemIds.includes(x.itemId));
|
||||
const deliveredItemIds = items.map(x => x._id);
|
||||
pmcData.InsuredItems = pmcData.InsuredItems.filter(x => !deliveredItemIds.includes(x.itemId));
|
||||
|
||||
// Send the items to the player
|
||||
this.mailSendService.sendLocalisedNpcMessageToPlayer(
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
@ -113,7 +112,7 @@ export class InsuranceController
|
||||
this.logger.debug(`Found ${profileInsuranceDetails.length} insurance packages in profile ${sessionID}`);
|
||||
}
|
||||
|
||||
return profileInsuranceDetails.filter((insured) => insuranceTime >= insured.scheduledTime);
|
||||
return profileInsuranceDetails.filter(insured => insuranceTime >= insured.scheduledTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,7 +160,7 @@ export class InsuranceController
|
||||
*/
|
||||
protected countAllInsuranceItems(insurance: Insurance[]): number
|
||||
{
|
||||
return this.mathUtil.arraySum(insurance.map((ins) => ins.items.length));
|
||||
return this.mathUtil.arraySum(insurance.map(ins => ins.items.length));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -174,11 +173,11 @@ export class InsuranceController
|
||||
protected removeInsurancePackageFromProfile(sessionID: string, insPackage: Insurance): void
|
||||
{
|
||||
const profile = this.saveServer.getProfile(sessionID);
|
||||
profile.insurance = profile.insurance.filter((insurance) =>
|
||||
profile.insurance = profile.insurance.filter(insurance =>
|
||||
insurance.traderId !== insPackage.traderId
|
||||
|| insurance.systemData.date !== insPackage.systemData.date
|
||||
|| insurance.systemData.time !== insPackage.systemData.time
|
||||
|| insurance.systemData.location !== insPackage.systemData.location
|
||||
|| insurance.systemData.location !== insPackage.systemData.location,
|
||||
);
|
||||
|
||||
this.logger.debug(`Removed processed insurance package. Remaining packages: ${profile.insurance.length}`);
|
||||
@ -201,8 +200,8 @@ export class InsuranceController
|
||||
let parentAttachmentsMap = this.populateParentAttachmentsMap(rootItemParentID, insured, itemsMap);
|
||||
|
||||
// Check to see if any regular items are present.
|
||||
const hasRegularItems = Array.from(itemsMap.values()).some((item) =>
|
||||
!this.itemHelper.isAttachmentAttached(item)
|
||||
const hasRegularItems = Array.from(itemsMap.values()).some(item =>
|
||||
!this.itemHelper.isAttachmentAttached(item),
|
||||
);
|
||||
|
||||
// Process all items that are not attached, attachments; those are handled separately, by value.
|
||||
@ -250,7 +249,7 @@ export class InsuranceController
|
||||
for (const insuredItem of insured.items)
|
||||
{
|
||||
// Use the parent ID from the item to get the parent item.
|
||||
const parentItem = insured.items.find((item) => item._id === insuredItem.parentId);
|
||||
const parentItem = insured.items.find(item => item._id === insuredItem.parentId);
|
||||
|
||||
// The parent (not the hideout) could not be found. Skip and warn.
|
||||
if (!parentItem && insuredItem.parentId !== rootItemParentID)
|
||||
@ -490,7 +489,7 @@ export class InsuranceController
|
||||
{
|
||||
this.logger.debug(
|
||||
`Attachment ${index} Id: ${attachmentId} Tpl: ${
|
||||
attachments.find((x) => x._id === attachmentId)?._tpl
|
||||
attachments.find(x => x._id === attachmentId)?._tpl
|
||||
} - Price: ${attachmentPrices[attachmentId]}`,
|
||||
);
|
||||
index++;
|
||||
@ -557,7 +556,7 @@ export class InsuranceController
|
||||
*/
|
||||
protected removeItemsFromInsurance(insured: Insurance, toDelete: Set<string>): void
|
||||
{
|
||||
insured.items = insured.items.filter((item) => !toDelete.has(item._id));
|
||||
insured.items = insured.items.filter(item => !toDelete.has(item._id));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -746,6 +745,6 @@ export class InsuranceController
|
||||
// Represents an insurance item that has had it's common locale-name and value added to it.
|
||||
interface EnrichedItem extends Item
|
||||
{
|
||||
name: string;
|
||||
dynamicPrice: number;
|
||||
name: string
|
||||
dynamicPrice: number
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
|
||||
import { HideoutHelper } from "@spt-aki/helpers/HideoutHelper";
|
||||
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
||||
@ -107,7 +106,7 @@ export class InventoryController
|
||||
}
|
||||
|
||||
// Check for item in inventory before allowing internal transfer
|
||||
const originalItemLocation = ownerInventoryItems.from.find((item) => item._id === moveRequest.item);
|
||||
const originalItemLocation = ownerInventoryItems.from.find(item => item._id === moveRequest.item);
|
||||
if (!originalItemLocation)
|
||||
{
|
||||
// Internal item move but item never existed, possible dupe glitch
|
||||
@ -169,7 +168,7 @@ export class InventoryController
|
||||
return;
|
||||
}
|
||||
|
||||
const profileToRemoveItemFrom = (!request.fromOwner || request.fromOwner.id === pmcData._id)
|
||||
const profileToRemoveItemFrom = !request.fromOwner || request.fromOwner.id === pmcData._id
|
||||
? pmcData
|
||||
: this.profileHelper.getFullProfile(sessionID).characters.scav;
|
||||
|
||||
@ -198,12 +197,12 @@ export class InventoryController
|
||||
// Handle cartridge edge-case
|
||||
if (!request.container.location && request.container.container === "cartridges")
|
||||
{
|
||||
const matchingItems = inventoryItems.to.filter((x) => x.parentId === request.container.id);
|
||||
const matchingItems = inventoryItems.to.filter(x => x.parentId === request.container.id);
|
||||
request.container.location = matchingItems.length; // Wrong location for first cartridge
|
||||
}
|
||||
|
||||
// The item being merged has three possible sources: pmc, scav or mail, getOwnerInventoryItems() handles getting correct one
|
||||
const itemToSplit = inventoryItems.from.find((x) => x._id === request.splitItem);
|
||||
const itemToSplit = inventoryItems.from.find(x => x._id === request.splitItem);
|
||||
if (!itemToSplit)
|
||||
{
|
||||
const errorMessage = `Unable to split stack as source item: ${request.splitItem} cannot be found`;
|
||||
@ -259,7 +258,7 @@ export class InventoryController
|
||||
const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID);
|
||||
|
||||
// Get source item (can be from player or trader or mail)
|
||||
const sourceItem = inventoryItems.from.find((x) => x._id === body.item);
|
||||
const sourceItem = inventoryItems.from.find(x => x._id === body.item);
|
||||
if (!sourceItem)
|
||||
{
|
||||
const errorMessage = `Unable to merge stacks as source item: ${body.with} cannot be found`;
|
||||
@ -271,7 +270,7 @@ export class InventoryController
|
||||
}
|
||||
|
||||
// Get item being merged into
|
||||
const destinationItem = inventoryItems.to.find((x) => x._id === body.with);
|
||||
const destinationItem = inventoryItems.to.find(x => x._id === body.with);
|
||||
if (!destinationItem)
|
||||
{
|
||||
const errorMessage = `Unable to merge stacks as destination item: ${body.with} cannot be found`;
|
||||
@ -282,7 +281,7 @@ export class InventoryController
|
||||
return output;
|
||||
}
|
||||
|
||||
if (!(destinationItem.upd?.StackObjectsCount))
|
||||
if (!destinationItem.upd?.StackObjectsCount)
|
||||
{
|
||||
// No stackcount on destination, add one
|
||||
destinationItem.upd = { StackObjectsCount: 1 };
|
||||
@ -307,7 +306,7 @@ export class InventoryController
|
||||
destinationItem.upd.StackObjectsCount += sourceItem.upd.StackObjectsCount; // Add source stackcount to destination
|
||||
output.profileChanges[sessionID].items.del.push({ _id: sourceItem._id }); // Inform client source item being deleted
|
||||
|
||||
const indexOfItemToRemove = inventoryItems.from.findIndex((x) => x._id === sourceItem._id);
|
||||
const indexOfItemToRemove = inventoryItems.from.findIndex(x => x._id === sourceItem._id);
|
||||
if (indexOfItemToRemove === -1)
|
||||
{
|
||||
const errorMessage = `Unable to find item: ${sourceItem._id} to remove from sender inventory`;
|
||||
@ -340,8 +339,8 @@ export class InventoryController
|
||||
): IItemEventRouterResponse
|
||||
{
|
||||
const inventoryItems = this.inventoryHelper.getOwnerInventoryItems(body, sessionID);
|
||||
const sourceItem = inventoryItems.from.find((item) => item._id === body.item);
|
||||
const destinationItem = inventoryItems.to.find((item) => item._id === body.with);
|
||||
const sourceItem = inventoryItems.from.find(item => item._id === body.item);
|
||||
const destinationItem = inventoryItems.to.find(item => item._id === body.with);
|
||||
|
||||
if (sourceItem === null)
|
||||
{
|
||||
@ -397,13 +396,13 @@ export class InventoryController
|
||||
*/
|
||||
public swapItem(pmcData: IPmcData, request: IInventorySwapRequestData, sessionID: string): IItemEventRouterResponse
|
||||
{
|
||||
const itemOne = pmcData.Inventory.items.find((x) => x._id === request.item);
|
||||
const itemOne = pmcData.Inventory.items.find(x => x._id === request.item);
|
||||
if (!itemOne)
|
||||
{
|
||||
this.logger.error(`Unable to find item: ${request.item} to swap positions with: ${request.item2}`);
|
||||
}
|
||||
|
||||
const itemTwo = pmcData.Inventory.items.find((x) => x._id === request.item2);
|
||||
const itemTwo = pmcData.Inventory.items.find(x => x._id === request.item2);
|
||||
if (!itemTwo)
|
||||
{
|
||||
this.logger.error(`Unable to find item: ${request.item2} to swap positions with: ${request.item}`);
|
||||
@ -454,7 +453,7 @@ export class InventoryController
|
||||
playerData = this.profileHelper.getScavProfile(sessionID);
|
||||
}
|
||||
|
||||
const itemToFold = playerData.Inventory.items.find((item) => item?._id === request.item);
|
||||
const itemToFold = playerData.Inventory.items.find(item => item?._id === request.item);
|
||||
if (!itemToFold)
|
||||
{
|
||||
// Item not found
|
||||
@ -488,7 +487,7 @@ export class InventoryController
|
||||
playerData = this.profileHelper.getScavProfile(sessionID);
|
||||
}
|
||||
|
||||
const itemToToggle = playerData.Inventory.items.find((x) => x._id === body.item);
|
||||
const itemToToggle = playerData.Inventory.items.find(x => x._id === body.item);
|
||||
if (itemToToggle)
|
||||
{
|
||||
this.itemHelper.addUpdObjectToItem(
|
||||
@ -689,15 +688,15 @@ export class InventoryController
|
||||
if (request.fromOwner.id === Traders.FENCE)
|
||||
{
|
||||
// Get tpl from fence assorts
|
||||
return this.fenceService.getRawFenceAssorts().items.find((x) => x._id === request.item)._tpl;
|
||||
return this.fenceService.getRawFenceAssorts().items.find(x => x._id === request.item)._tpl;
|
||||
}
|
||||
|
||||
if (request.fromOwner.type === "Trader")
|
||||
{
|
||||
// Not fence
|
||||
// get tpl from trader assort
|
||||
return this.databaseServer.getTables().traders[request.fromOwner.id].assort.items.find((item) =>
|
||||
item._id === request.item
|
||||
return this.databaseServer.getTables().traders[request.fromOwner.id].assort.items.find(item =>
|
||||
item._id === request.item,
|
||||
)._tpl;
|
||||
}
|
||||
|
||||
@ -718,7 +717,7 @@ export class InventoryController
|
||||
}
|
||||
|
||||
// Try find examine item inside offer items array
|
||||
const matchingItem = offer.items.find((offerItem) => offerItem._id === request.item);
|
||||
const matchingItem = offer.items.find(offerItem => offerItem._id === request.item);
|
||||
if (matchingItem)
|
||||
{
|
||||
return matchingItem._tpl;
|
||||
@ -754,7 +753,7 @@ export class InventoryController
|
||||
{
|
||||
for (const change of request.changedItems)
|
||||
{
|
||||
const inventoryItem = pmcData.Inventory.items.find((x) => x._id === change._id);
|
||||
const inventoryItem = pmcData.Inventory.items.find(x => x._id === change._id);
|
||||
if (!inventoryItem)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -793,7 +792,7 @@ export class InventoryController
|
||||
): void
|
||||
{
|
||||
// Get map from inventory
|
||||
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
|
||||
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
|
||||
|
||||
// add marker
|
||||
mapItem.upd.Map = mapItem.upd.Map || { Markers: [] };
|
||||
@ -819,7 +818,7 @@ export class InventoryController
|
||||
): void
|
||||
{
|
||||
// Get map from inventory
|
||||
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
|
||||
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
|
||||
|
||||
// remove marker
|
||||
const markers = mapItem.upd.Map.Markers.filter((marker) =>
|
||||
@ -847,10 +846,10 @@ export class InventoryController
|
||||
): void
|
||||
{
|
||||
// Get map from inventory
|
||||
const mapItem = pmcData.Inventory.items.find((i) => i._id === request.item);
|
||||
const mapItem = pmcData.Inventory.items.find(i => i._id === request.item);
|
||||
|
||||
// edit marker
|
||||
const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex((m) => m.X === request.X && m.Y === request.Y);
|
||||
const indexOfExistingNote = mapItem.upd.Map.Markers.findIndex(m => m.X === request.X && m.Y === request.Y);
|
||||
request.mapMarker.Note = this.sanitiseMapMarkerText(request.mapMarker.Note);
|
||||
mapItem.upd.Map.Markers[indexOfExistingNote] = request.mapMarker;
|
||||
|
||||
@ -884,7 +883,7 @@ export class InventoryController
|
||||
): void
|
||||
{
|
||||
/** Container player opened in their inventory */
|
||||
const openedItem = pmcData.Inventory.items.find((item) => item._id === body.item);
|
||||
const openedItem = pmcData.Inventory.items.find(item => item._id === body.item);
|
||||
const containerDetailsDb = this.itemHelper.getItem(openedItem._tpl);
|
||||
const isSealedWeaponBox = containerDetailsDb[1]._name.includes("event_container_airdrop");
|
||||
|
||||
@ -935,8 +934,8 @@ export class InventoryController
|
||||
// Hard coded to `SYSTEM` for now
|
||||
// TODO: make this dynamic
|
||||
const dialog = fullProfile.dialogues["59e7125688a45068a6249071"];
|
||||
const mail = dialog.messages.find((x) => x._id === event.MessageId);
|
||||
const mailEvent = mail.profileChangeEvents.find((x) => x._id === event.EventId);
|
||||
const mail = dialog.messages.find(x => x._id === event.MessageId);
|
||||
const mailEvent = mail.profileChangeEvents.find(x => x._id === event.EventId);
|
||||
|
||||
switch (mailEvent.Type)
|
||||
{
|
||||
@ -955,15 +954,15 @@ export class InventoryController
|
||||
break;
|
||||
case "SkillPoints":
|
||||
{
|
||||
const profileSkill = pmcData.Skills.Common.find((x) => x.Id === mailEvent.entity);
|
||||
const profileSkill = pmcData.Skills.Common.find(x => x.Id === mailEvent.entity);
|
||||
profileSkill.Progress = mailEvent.value;
|
||||
this.logger.success(`Set profile skill: ${mailEvent.entity} to: ${mailEvent.value}`);
|
||||
break;
|
||||
}
|
||||
case "ExamineAllItems":
|
||||
{
|
||||
const itemsToInspect = this.itemHelper.getItems().filter((x) => x._type !== "Node");
|
||||
this.flagItemsAsInspectedAndRewardXp(itemsToInspect.map((x) => x._id), fullProfile);
|
||||
const itemsToInspect = this.itemHelper.getItems().filter(x => x._type !== "Node");
|
||||
this.flagItemsAsInspectedAndRewardXp(itemsToInspect.map(x => x._id), fullProfile);
|
||||
this.logger.success(`Flagged ${itemsToInspect.length} items as examined`);
|
||||
break;
|
||||
}
|
||||
@ -988,7 +987,7 @@ export class InventoryController
|
||||
for (const itemId of request.items)
|
||||
{
|
||||
// If id already exists in array, we're removing it
|
||||
const indexOfItemAlreadyFavorited = pmcData.Inventory.favoriteItems.findIndex((x) => x === itemId);
|
||||
const indexOfItemAlreadyFavorited = pmcData.Inventory.favoriteItems.findIndex(x => x === itemId);
|
||||
if (indexOfItemAlreadyFavorited > -1)
|
||||
{
|
||||
pmcData.Inventory.favoriteItems.splice(indexOfItemAlreadyFavorited, 1);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
|
||||
@ -191,7 +190,7 @@ export class MatchController
|
||||
return false;
|
||||
}
|
||||
|
||||
return (this.inRaidConfig.coopExtracts.includes(extractName.trim()));
|
||||
return this.inRaidConfig.coopExtracts.includes(extractName.trim());
|
||||
}
|
||||
|
||||
protected sendCoopTakenFenceMessage(sessionId: string): void
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { Note } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HttpServerHelper } from "@spt-aki/helpers/HttpServerHelper";
|
||||
import { NotifierHelper } from "@spt-aki/helpers/NotifierHelper";
|
||||
import { INotifierChannel } from "@spt-aki/models/eft/notifier/INotifier";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
||||
import { ILogger } from "@spt-aki/models/spt/utils/ILogger";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { PlayerScavGenerator } from "@spt-aki/generators/PlayerScavGenerator";
|
||||
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
@ -81,7 +80,7 @@ export class ProfileController
|
||||
const pmc = profile.characters.pmc;
|
||||
|
||||
// make sure character completed creation
|
||||
if (!(pmc?.Info?.Level))
|
||||
if (!pmc?.Info?.Level)
|
||||
{
|
||||
return {
|
||||
username: profile.info.username,
|
||||
@ -104,7 +103,7 @@ export class ProfileController
|
||||
side: pmc.Info.Side,
|
||||
currlvl: pmc.Info.Level,
|
||||
currexp: pmc.Info.Experience ?? 0,
|
||||
prevexp: (currlvl === 0) ? 0 : this.profileHelper.getExperience(currlvl),
|
||||
prevexp: currlvl === 0 ? 0 : this.profileHelper.getExperience(currlvl),
|
||||
nextlvl: nextlvl,
|
||||
maxlvl: maxlvl,
|
||||
akiData: profile.aki,
|
||||
@ -130,8 +129,10 @@ export class ProfileController
|
||||
public createProfile(info: IProfileCreateRequestData, sessionID: string): string
|
||||
{
|
||||
const account = this.saveServer.getProfile(sessionID).info;
|
||||
const profile: ITemplateSide =
|
||||
this.databaseServer.getTables().templates.profiles[account.edition][info.side.toLowerCase()];
|
||||
const profile: ITemplateSide = this.databaseServer
|
||||
.getTables()
|
||||
.templates
|
||||
.profiles[account.edition][info.side.toLowerCase()];
|
||||
const pmcData = profile.character;
|
||||
|
||||
// Delete existing profile
|
||||
@ -151,7 +152,7 @@ export class ProfileController
|
||||
pmcData.Customization.Head = info.headId;
|
||||
pmcData.Health.UpdateTime = this.timeUtil.getTimestamp();
|
||||
pmcData.Quests = [];
|
||||
pmcData.Hideout.Seed = this.timeUtil.getTimestamp() + (8 * 60 * 60 * 24 * 365); // 8 years in future why? who knows, we saw it in live
|
||||
pmcData.Hideout.Seed = this.timeUtil.getTimestamp() + 8 * 60 * 60 * 24 * 365; // 8 years in future why? who knows, we saw it in live
|
||||
pmcData.RepeatableQuests = [];
|
||||
pmcData.CarExtractCounts = {};
|
||||
pmcData.CoopExtractCounts = {};
|
||||
@ -458,7 +459,7 @@ export class ProfileController
|
||||
skills: playerPmc.Skills,
|
||||
equipment: {
|
||||
// Default inventory tpl
|
||||
Id: playerPmc.Inventory.items.find((x) => x._tpl === "55d7217a4bdc2d86028b456d")._id,
|
||||
Id: playerPmc.Inventory.items.find(x => x._tpl === "55d7217a4bdc2d86028b456d")._id,
|
||||
Items: playerPmc.Inventory.items,
|
||||
},
|
||||
achievements: playerPmc.Achievements,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
@ -79,7 +78,7 @@ export class QuestController
|
||||
for (const quest of allQuests)
|
||||
{
|
||||
// Player already accepted the quest, show it regardless of status
|
||||
const questInProfile = profile.Quests.find((x) => x.qid === quest._id);
|
||||
const questInProfile = profile.Quests.find(x => x.qid === quest._id);
|
||||
if (questInProfile)
|
||||
{
|
||||
quest.sptStatus = questInProfile.status;
|
||||
@ -137,8 +136,8 @@ export class QuestController
|
||||
for (const conditionToFulfil of questRequirements)
|
||||
{
|
||||
// If the previous quest isn't in the user profile, it hasn't been completed or started
|
||||
const prerequisiteQuest = profile.Quests.find((profileQuest) =>
|
||||
conditionToFulfil.target.includes(profileQuest.qid)
|
||||
const prerequisiteQuest = profile.Quests.find(profileQuest =>
|
||||
conditionToFulfil.target.includes(profileQuest.qid),
|
||||
);
|
||||
if (!prerequisiteQuest)
|
||||
{
|
||||
@ -148,7 +147,7 @@ export class QuestController
|
||||
|
||||
// Prereq does not have its status requirement fulfilled
|
||||
// Some bsg status ids are strings, MUST convert to number before doing includes check
|
||||
if (!conditionToFulfil.status.map((status) => Number(status)).includes(prerequisiteQuest.status))
|
||||
if (!conditionToFulfil.status.map(status => Number(status)).includes(prerequisiteQuest.status))
|
||||
{
|
||||
haveCompletedPreviousQuest = false;
|
||||
break;
|
||||
@ -292,7 +291,7 @@ export class QuestController
|
||||
|
||||
// Does quest exist in profile
|
||||
// Restarting a failed quest can mean quest exists in profile
|
||||
const existingQuestStatus = pmcData.Quests.find((x) => x.qid === acceptedQuest.qid);
|
||||
const existingQuestStatus = pmcData.Quests.find(x => x.qid === acceptedQuest.qid);
|
||||
if (existingQuestStatus)
|
||||
{
|
||||
// Update existing
|
||||
@ -399,15 +398,15 @@ export class QuestController
|
||||
fullProfile.characters.scav.Quests.push(newRepeatableQuest);
|
||||
}
|
||||
|
||||
const repeatableSettings = pmcData.RepeatableQuests.find((x) =>
|
||||
x.name === repeatableQuestProfile.sptRepatableGroupName
|
||||
const repeatableSettings = pmcData.RepeatableQuests.find(x =>
|
||||
x.name === repeatableQuestProfile.sptRepatableGroupName,
|
||||
);
|
||||
|
||||
const change = {};
|
||||
change[repeatableQuestProfile._id] = repeatableSettings.changeRequirement[repeatableQuestProfile._id];
|
||||
const responseData: IPmcDataRepeatableQuest = {
|
||||
id: repeatableSettings.id ?? this.questConfig.repeatableQuests.find((x) =>
|
||||
x.name === repeatableQuestProfile.sptRepatableGroupName
|
||||
id: repeatableSettings.id ?? this.questConfig.repeatableQuests.find(x =>
|
||||
x.name === repeatableQuestProfile.sptRepatableGroupName,
|
||||
).id,
|
||||
name: repeatableSettings.name,
|
||||
endTime: repeatableSettings.endTime,
|
||||
@ -435,7 +434,7 @@ export class QuestController
|
||||
{
|
||||
for (const repeatableQuest of pmcData.RepeatableQuests)
|
||||
{
|
||||
const matchingQuest = repeatableQuest.activeQuests.find((x) => x._id === acceptedQuest.qid);
|
||||
const matchingQuest = repeatableQuest.activeQuests.find(x => x._id === acceptedQuest.qid);
|
||||
if (matchingQuest)
|
||||
{
|
||||
this.logger.debug(`Accepted repeatable quest ${acceptedQuest.qid} from ${repeatableQuest.name}`);
|
||||
@ -504,8 +503,8 @@ export class QuestController
|
||||
// Check if it's a repeatable quest. If so, remove from Quests
|
||||
for (const currentRepeatable of pmcData.RepeatableQuests)
|
||||
{
|
||||
const repeatableQuest = currentRepeatable.activeQuests.find((activeRepeatable) =>
|
||||
activeRepeatable._id === completedQuestId
|
||||
const repeatableQuest = currentRepeatable.activeQuests.find(activeRepeatable =>
|
||||
activeRepeatable._id === completedQuestId,
|
||||
);
|
||||
if (repeatableQuest)
|
||||
{
|
||||
@ -548,15 +547,15 @@ export class QuestController
|
||||
|
||||
// Quest already failed in profile, skip
|
||||
if (
|
||||
pmcProfile.Quests.some((profileQuest) =>
|
||||
profileQuest.qid === quest._id && profileQuest.status === QuestStatus.Fail
|
||||
pmcProfile.Quests.some(profileQuest =>
|
||||
profileQuest.qid === quest._id && profileQuest.status === QuestStatus.Fail,
|
||||
)
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return quest.conditions.Fail.some((condition) => condition.target?.includes(completedQuestId));
|
||||
return quest.conditions.Fail.some(condition => condition.target?.includes(completedQuestId));
|
||||
});
|
||||
}
|
||||
|
||||
@ -568,7 +567,7 @@ export class QuestController
|
||||
protected removeQuestFromScavProfile(sessionId: string, questIdToRemove: string): void
|
||||
{
|
||||
const fullProfile = this.profileHelper.getFullProfile(sessionId);
|
||||
const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find((x) => x.qid === questIdToRemove);
|
||||
const repeatableInScavProfile = fullProfile.characters.scav.Quests?.find(x => x.qid === questIdToRemove);
|
||||
if (!repeatableInScavProfile)
|
||||
{
|
||||
this.logger.warning(
|
||||
@ -600,7 +599,7 @@ export class QuestController
|
||||
for (const quest of postQuestStatuses)
|
||||
{
|
||||
// Add quest if status differs or quest not found
|
||||
const preQuest = preQuestStatusus.find((x) => x.qid === quest.qid);
|
||||
const preQuest = preQuestStatusus.find(x => x.qid === quest.qid);
|
||||
if (!preQuest || preQuest.status !== quest.status)
|
||||
{
|
||||
result.push(quest);
|
||||
@ -653,8 +652,8 @@ export class QuestController
|
||||
for (const quest of quests)
|
||||
{
|
||||
// If quest has prereq of completed quest + availableAfter value > 0 (quest has wait time)
|
||||
const nextQuestWaitCondition = quest.conditions.AvailableForStart.find((x) =>
|
||||
x.target?.includes(completedQuestId) && x.availableAfter > 0
|
||||
const nextQuestWaitCondition = quest.conditions.AvailableForStart.find(x =>
|
||||
x.target?.includes(completedQuestId) && x.availableAfter > 0,
|
||||
);
|
||||
if (nextQuestWaitCondition)
|
||||
{
|
||||
@ -662,7 +661,7 @@ export class QuestController
|
||||
const availableAfterTimestamp = this.timeUtil.getTimestamp() + nextQuestWaitCondition.availableAfter;
|
||||
|
||||
// Update quest in profile with status of AvailableAfter
|
||||
const existingQuestInProfile = pmcData.Quests.find((x) => x.qid === quest._id);
|
||||
const existingQuestInProfile = pmcData.Quests.find(x => x.qid === quest._id);
|
||||
if (existingQuestInProfile)
|
||||
{
|
||||
existingQuestInProfile.availableAfter = availableAfterTimestamp;
|
||||
@ -679,7 +678,7 @@ export class QuestController
|
||||
status: QuestStatus.AvailableAfter,
|
||||
statusTimers: {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
"9": this.timeUtil.getTimestamp(),
|
||||
9: this.timeUtil.getTimestamp(),
|
||||
},
|
||||
availableAfter: availableAfterTimestamp,
|
||||
});
|
||||
@ -705,12 +704,12 @@ export class QuestController
|
||||
for (const questToFail of questsToFail)
|
||||
{
|
||||
// Skip failing a quest that has a fail status of something other than success
|
||||
if (questToFail.conditions.Fail?.some((x) => x.status?.some((status) => status !== QuestStatus.Success)))
|
||||
if (questToFail.conditions.Fail?.some(x => x.status?.some(status => status !== QuestStatus.Success)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const isActiveQuestInPlayerProfile = pmcData.Quests.find((quest) => quest.qid === questToFail._id);
|
||||
const isActiveQuestInPlayerProfile = pmcData.Quests.find(quest => quest.qid === questToFail._id);
|
||||
if (isActiveQuestInPlayerProfile)
|
||||
{
|
||||
if (isActiveQuestInPlayerProfile.status !== QuestStatus.Fail)
|
||||
@ -772,7 +771,7 @@ export class QuestController
|
||||
isItemHandoverQuest = condition.conditionType === handoverQuestTypes[0];
|
||||
handoverRequirements = condition;
|
||||
|
||||
const profileCounter = (handoverQuestRequest.conditionId in pmcData.TaskConditionCounters)
|
||||
const profileCounter = handoverQuestRequest.conditionId in pmcData.TaskConditionCounters
|
||||
? pmcData.TaskConditionCounters[handoverQuestRequest.conditionId].value
|
||||
: 0;
|
||||
handedInCount -= profileCounter;
|
||||
@ -806,7 +805,7 @@ export class QuestController
|
||||
let totalItemCountToRemove = 0;
|
||||
for (const itemHandover of handoverQuestRequest.items)
|
||||
{
|
||||
const matchingItemInProfile = pmcData.Inventory.items.find((item) => item._id === itemHandover.id);
|
||||
const matchingItemInProfile = pmcData.Inventory.items.find(item => item._id === itemHandover.id);
|
||||
if (!(matchingItemInProfile && handoverRequirements.target.includes(matchingItemInProfile._tpl)))
|
||||
{
|
||||
// Item handed in by player doesnt match what was requested
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RagfairOfferGenerator } from "@spt-aki/generators/RagfairOfferGenerator";
|
||||
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
||||
@ -160,7 +159,7 @@ export class RagfairController
|
||||
public getOfferById(sessionId: string, request: IGetRagfairOfferByIdRequest): IRagfairOffer
|
||||
{
|
||||
const offers = this.ragfairOfferService.getOffers();
|
||||
const offerToReturn = offers.find((x) => x.intId === request.id);
|
||||
const offerToReturn = offers.find(x => x.intId === request.id);
|
||||
|
||||
return offerToReturn;
|
||||
}
|
||||
@ -208,14 +207,18 @@ export class RagfairController
|
||||
): Record<string, number>
|
||||
{
|
||||
// Linked/required search categories
|
||||
const playerHasFleaUnlocked =
|
||||
pmcProfile.Info.Level >= this.databaseServer.getTables().globals.config.RagFair.minUserLevel;
|
||||
const playerHasFleaUnlocked = pmcProfile.Info.Level >= this.databaseServer
|
||||
.getTables()
|
||||
.globals
|
||||
.config
|
||||
.RagFair
|
||||
.minUserLevel;
|
||||
let offerPool = [];
|
||||
if (this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))
|
||||
{
|
||||
offerPool = offers;
|
||||
}
|
||||
else if ((!(this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest))))
|
||||
else if (!(this.isLinkedSearch(searchRequest) || this.isRequiredSearch(searchRequest)))
|
||||
{
|
||||
// Get all categories
|
||||
offerPool = this.ragfairOfferService.getOffers();
|
||||
@ -260,7 +263,7 @@ export class RagfairController
|
||||
|
||||
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items;
|
||||
const assortId = offer.items[0]._id;
|
||||
const assortData = traderAssorts.find((x) => x._id === assortId);
|
||||
const assortData = traderAssorts.find(x => x._id === assortId);
|
||||
|
||||
// Use value stored in profile, otherwise use value directly from in-memory trader assort data
|
||||
offer.buyRestrictionCurrent = fullProfile.traderPurchases[offer.user.id][assortId]
|
||||
@ -279,7 +282,7 @@ export class RagfairController
|
||||
const firstItem = offer.items[0];
|
||||
const traderAssorts = this.traderHelper.getTraderAssortsByTraderId(offer.user.id).items;
|
||||
|
||||
const assortPurchased = traderAssorts.find((x) => x._id === offer.items[0]._id);
|
||||
const assortPurchased = traderAssorts.find(x => x._id === offer.items[0]._id);
|
||||
if (!assortPurchased)
|
||||
{
|
||||
this.logger.warning(
|
||||
@ -357,7 +360,7 @@ export class RagfairController
|
||||
const avg = offers.reduce((sum, offer) =>
|
||||
{
|
||||
// Exclude barter items, they tend to have outrageous equivalent prices
|
||||
if (offer.requirements.some((req) => !this.paymentHelper.isMoneyTpl(req._tpl)))
|
||||
if (offer.requirements.some(req => !this.paymentHelper.isMoneyTpl(req._tpl)))
|
||||
{
|
||||
return sum;
|
||||
}
|
||||
@ -456,15 +459,15 @@ export class RagfairController
|
||||
// Multiply single item price by stack count and quality
|
||||
averageOfferPrice *= rootItem.upd.StackObjectsCount * qualityMultiplier;
|
||||
|
||||
const itemStackCount = (offerRequest.sellInOnePiece) ? 1 : rootItem.upd.StackObjectsCount;
|
||||
const itemStackCount = offerRequest.sellInOnePiece ? 1 : rootItem.upd.StackObjectsCount;
|
||||
|
||||
// Get averaged price of a single item being listed
|
||||
const averageSingleItemPrice = (offerRequest.sellInOnePiece)
|
||||
const averageSingleItemPrice = offerRequest.sellInOnePiece
|
||||
? averageOfferPrice / rootItem.upd.StackObjectsCount // Packs are a single offer made of many items
|
||||
: averageOfferPrice / itemStackCount;
|
||||
|
||||
// Get averaged price of listing
|
||||
const averagePlayerListedPriceInRub = (offerRequest.sellInOnePiece)
|
||||
const averagePlayerListedPriceInRub = offerRequest.sellInOnePiece
|
||||
? playerListedPriceInRub / rootItem.upd.StackObjectsCount
|
||||
: playerListedPriceInRub;
|
||||
|
||||
@ -540,7 +543,7 @@ export class RagfairController
|
||||
offerRequest.sellInOnePiece,
|
||||
);
|
||||
|
||||
this.logger.debug(`Offer tax to charge: ${tax}, pulled from client: ${(!!storedClientTaxValue)}`);
|
||||
this.logger.debug(`Offer tax to charge: ${tax}, pulled from client: ${!!storedClientTaxValue}`);
|
||||
|
||||
// cleanup of cache now we've used the tax value from it
|
||||
this.ragfairTaxService.clearStoredOfferTaxById(offerRequest.items[0]);
|
||||
@ -602,8 +605,8 @@ export class RagfairController
|
||||
}
|
||||
else
|
||||
{
|
||||
requirementsPriceInRub += this.ragfairPriceService.getDynamicPriceForItem(requestedItemTpl)
|
||||
* item.count;
|
||||
requirementsPriceInRub += this.ragfairPriceService
|
||||
.getDynamicPriceForItem(requestedItemTpl) * item.count;
|
||||
}
|
||||
}
|
||||
|
||||
@ -619,7 +622,7 @@ export class RagfairController
|
||||
protected getItemsToListOnFleaFromInventory(
|
||||
pmcData: IPmcData,
|
||||
itemIdsFromFleaOfferRequest: string[],
|
||||
): { items: Item[] | null; errorMessage: string | null; }
|
||||
): { items: Item[] | null, errorMessage: string | null }
|
||||
{
|
||||
const itemsToReturn = [];
|
||||
let errorMessage: string | null = null;
|
||||
@ -627,7 +630,7 @@ export class RagfairController
|
||||
// Count how many items are being sold and multiply the requested amount accordingly
|
||||
for (const itemId of itemIdsFromFleaOfferRequest)
|
||||
{
|
||||
let item = pmcData.Inventory.items.find((i) => i._id === itemId);
|
||||
let item = pmcData.Inventory.items.find(i => i._id === itemId);
|
||||
if (!item)
|
||||
{
|
||||
errorMessage = this.localisationService.getText("ragfair-unable_to_find_item_in_inventory", {
|
||||
@ -663,7 +666,7 @@ export class RagfairController
|
||||
const loyalLevel = 1;
|
||||
const formattedItems: Item[] = items.map((item) =>
|
||||
{
|
||||
const isChild = items.find((it) => it._id === item.parentId);
|
||||
const isChild = items.find(it => it._id === item.parentId);
|
||||
|
||||
return {
|
||||
_id: item._id,
|
||||
@ -724,7 +727,7 @@ export class RagfairController
|
||||
pmcData.RagfairInfo.offers = [];
|
||||
}
|
||||
|
||||
const playerOfferIndex = playerProfileOffers.findIndex((offer) => offer._id === removeRequest.offerId);
|
||||
const playerOfferIndex = playerProfileOffers.findIndex(offer => offer._id === removeRequest.offerId);
|
||||
if (playerOfferIndex === -1)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -761,7 +764,7 @@ export class RagfairController
|
||||
|
||||
const pmcData = this.saveServer.getProfile(sessionId).characters.pmc;
|
||||
const playerOffers = pmcData.RagfairInfo.offers;
|
||||
const playerOfferIndex = playerOffers.findIndex((offer) => offer._id === extendRequest.offerId);
|
||||
const playerOfferIndex = playerOffers.findIndex(offer => offer._id === extendRequest.offerId);
|
||||
const secondsToAdd = extendRequest.renewalTime * TimeUtil.ONE_HOUR_AS_SECONDS;
|
||||
|
||||
if (playerOfferIndex === -1)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { QuestHelper } from "@spt-aki/helpers/QuestHelper";
|
||||
import { RepairHelper } from "@spt-aki/helpers/RepairHelper";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RepeatableQuestGenerator } from "@spt-aki/generators/RepeatableQuestGenerator";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { QuestHelper } from "@spt-aki/helpers/QuestHelper";
|
||||
@ -83,15 +82,15 @@ export class RepeatableQuestController
|
||||
* @param {string} _info Request from client
|
||||
* @param {string} sessionID Player's session id
|
||||
*
|
||||
* @returns {array} Array of "repeatableQuestObjects" as descibed above
|
||||
* @returns {array} Array of "repeatableQuestObjects" as described above
|
||||
*/
|
||||
public getClientRepeatableQuests(_info: IEmptyRequestData, sessionID: string): IPmcDataRepeatableQuest[]
|
||||
{
|
||||
const returnData: Array<IPmcDataRepeatableQuest> = [];
|
||||
const pmcData = this.profileHelper.getPmcProfile(sessionID);
|
||||
const time = this.timeUtil.getTimestamp();
|
||||
const scavQuestUnlocked =
|
||||
pmcData?.Hideout?.Areas?.find((hideoutArea) => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1;
|
||||
const scavQuestUnlocked
|
||||
= pmcData?.Hideout?.Areas?.find(hideoutArea => hideoutArea.type === HideoutAreas.INTEL_CENTER)?.level >= 1;
|
||||
|
||||
// Daily / weekly / Daily_Savage
|
||||
for (const repeatableConfig of this.questConfig.repeatableQuests)
|
||||
@ -119,7 +118,7 @@ export class RepeatableQuestController
|
||||
for (const activeQuest of currentRepeatableQuestType.activeQuests)
|
||||
{
|
||||
// Keep finished quests in list so player can hand in
|
||||
const quest = pmcData.Quests.find((quest) => quest.qid === activeQuest._id);
|
||||
const quest = pmcData.Quests.find(quest => quest.qid === activeQuest._id);
|
||||
if (quest)
|
||||
{
|
||||
if (quest.status === QuestStatus.AvailableForFinish)
|
||||
@ -135,7 +134,7 @@ export class RepeatableQuestController
|
||||
this.profileFixerService.removeDanglingConditionCounters(pmcData);
|
||||
|
||||
// Remove expired quest from pmc.quest array
|
||||
pmcData.Quests = pmcData.Quests.filter((quest) => quest.qid !== activeQuest._id);
|
||||
pmcData.Quests = pmcData.Quests.filter(quest => quest.qid !== activeQuest._id);
|
||||
currentRepeatableQuestType.inactiveQuests.push(activeQuest);
|
||||
}
|
||||
currentRepeatableQuestType.activeQuests = questsToKeep;
|
||||
@ -217,9 +216,14 @@ export class RepeatableQuestController
|
||||
)
|
||||
{
|
||||
// Elite charisma skill gives extra daily quest(s)
|
||||
return repeatableConfig.numQuests
|
||||
+ this.databaseServer.getTables().globals.config.SkillsSettings.Charisma.BonusSettings
|
||||
.EliteBonusSettings.RepeatableQuestExtraCount;
|
||||
return repeatableConfig.numQuests + this.databaseServer.getTables()
|
||||
.globals
|
||||
.config
|
||||
.SkillsSettings
|
||||
.Charisma
|
||||
.BonusSettings
|
||||
.EliteBonusSettings
|
||||
.RepeatableQuestExtraCount;
|
||||
}
|
||||
|
||||
return repeatableConfig.numQuests;
|
||||
@ -237,7 +241,7 @@ export class RepeatableQuestController
|
||||
): IPmcDataRepeatableQuest
|
||||
{
|
||||
// Get from profile, add if missing
|
||||
let repeatableQuestDetails = pmcData.RepeatableQuests.find((x) => x.name === repeatableConfig.name);
|
||||
let repeatableQuestDetails = pmcData.RepeatableQuests.find(x => x.name === repeatableConfig.name);
|
||||
if (!repeatableQuestDetails)
|
||||
{
|
||||
repeatableQuestDetails = {
|
||||
@ -327,8 +331,8 @@ export class RepeatableQuestController
|
||||
const possibleLocations = Object.keys(locations);
|
||||
|
||||
// Set possible locations for elimination task, if target is savage, exclude labs from locations
|
||||
questPool.pool.Elimination.targets[probabilityObject.key] = (probabilityObject.key === "Savage")
|
||||
? { locations: possibleLocations.filter((x) => x !== "laboratory") }
|
||||
questPool.pool.Elimination.targets[probabilityObject.key] = probabilityObject.key === "Savage"
|
||||
? { locations: possibleLocations.filter(x => x !== "laboratory") }
|
||||
: { locations: possibleLocations };
|
||||
}
|
||||
}
|
||||
@ -396,7 +400,7 @@ export class RepeatableQuestController
|
||||
return true;
|
||||
}
|
||||
|
||||
return (pmcLevel <= locationBase.RequiredPlayerLevelMax && pmcLevel >= locationBase.RequiredPlayerLevelMin);
|
||||
return pmcLevel <= locationBase.RequiredPlayerLevelMax && pmcLevel >= locationBase.RequiredPlayerLevelMin;
|
||||
}
|
||||
|
||||
public debugLogRepeatableQuestIds(pmcData: IPmcData): void
|
||||
@ -439,7 +443,7 @@ export class RepeatableQuestController
|
||||
for (const currentRepeatablePool of pmcData.RepeatableQuests)
|
||||
{
|
||||
// Check for existing quest in (daily/weekly/scav arrays)
|
||||
const questToReplace = currentRepeatablePool.activeQuests.find((x) => x._id === changeRequest.qid);
|
||||
const questToReplace = currentRepeatablePool.activeQuests.find(x => x._id === changeRequest.qid);
|
||||
if (!questToReplace)
|
||||
{
|
||||
continue;
|
||||
@ -449,8 +453,8 @@ export class RepeatableQuestController
|
||||
replacedQuestTraderId = questToReplace.traderId;
|
||||
|
||||
// Update active quests to exclude the quest we're replacing
|
||||
currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter((x) =>
|
||||
x._id !== changeRequest.qid
|
||||
currentRepeatablePool.activeQuests = currentRepeatablePool.activeQuests.filter(x =>
|
||||
x._id !== changeRequest.qid,
|
||||
);
|
||||
|
||||
// Get cost to replace existing quest
|
||||
@ -458,8 +462,8 @@ export class RepeatableQuestController
|
||||
delete currentRepeatablePool.changeRequirement[changeRequest.qid];
|
||||
// TODO: somehow we need to reduce the questPool by the currently active quests (for all repeatables)
|
||||
|
||||
const repeatableConfig = this.questConfig.repeatableQuests.find((x) =>
|
||||
x.name === currentRepeatablePool.name
|
||||
const repeatableConfig = this.questConfig.repeatableQuests.find(x =>
|
||||
x.name === currentRepeatablePool.name,
|
||||
);
|
||||
const questTypePool = this.generateQuestPool(repeatableConfig, pmcData.Info.Level);
|
||||
const newRepeatableQuest = this.attemptToGenerateRepeatableQuest(pmcData, questTypePool, repeatableConfig);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { TradeHelper } from "@spt-aki/helpers/TradeHelper";
|
||||
@ -294,7 +293,7 @@ export class TradeController
|
||||
this.traderHelper.getTraderById(trader),
|
||||
MessageType.MESSAGE_WITH_ITEMS,
|
||||
this.randomUtil.getArrayValue(this.databaseServer.getTables().traders[trader].dialogue.soldItems),
|
||||
curencyReward.flatMap((x) => x),
|
||||
curencyReward.flatMap(x => x),
|
||||
this.timeUtil.getHoursAsSeconds(72),
|
||||
);
|
||||
}
|
||||
@ -320,12 +319,12 @@ export class TradeController
|
||||
for (const itemToSell of itemWithChildren)
|
||||
{
|
||||
const itemDetails = this.itemHelper.getItem(itemToSell._tpl);
|
||||
if (
|
||||
!(itemDetails[0]
|
||||
&& this.itemHelper.isOfBaseclasses(itemDetails[1]._id, traderDetails.items_buy.category))
|
||||
)
|
||||
if (!(itemDetails[0] && this.itemHelper.isOfBaseclasses(
|
||||
itemDetails[1]._id,
|
||||
traderDetails.items_buy.category,
|
||||
)))
|
||||
{
|
||||
// Skip if tpl isnt item OR item doesn't fulfill match traders buy categories
|
||||
// Skip if tpl isn't item OR item doesn't fulfil match traders buy categories
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { FenceBaseAssortGenerator } from "@spt-aki/generators/FenceBaseAssortGenerator";
|
||||
import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper";
|
||||
import { TraderAssortHelper } from "@spt-aki/helpers/TraderAssortHelper";
|
||||
@ -30,8 +29,7 @@ export class TraderController
|
||||
@inject("ProfileHelper") protected profileHelper: ProfileHelper,
|
||||
@inject("TraderHelper") protected traderHelper: TraderHelper,
|
||||
@inject("TraderAssortService") protected traderAssortService: TraderAssortService,
|
||||
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService:
|
||||
TraderPurchasePersisterService,
|
||||
@inject("TraderPurchasePersisterService") protected traderPurchasePersisterService: TraderPurchasePersisterService,
|
||||
@inject("FenceService") protected fenceService: FenceService,
|
||||
@inject("FenceBaseAssortGenerator") protected fenceBaseAssortGenerator: FenceBaseAssortGenerator,
|
||||
@inject("JsonUtil") protected jsonUtil: JsonUtil,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { WeatherGenerator } from "@spt-aki/generators/WeatherGenerator";
|
||||
import { IWeatherData } from "@spt-aki/models/eft/weather/IWeatherData";
|
||||
import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { IPmcData } from "@spt-aki/models/eft/common/IPmcData";
|
||||
import { IItemEventRouterResponse } from "@spt-aki/models/eft/itemEvent/IItemEventRouterResponse";
|
||||
import { IWishlistActionData } from "@spt-aki/models/eft/wishlist/IWishlistActionData";
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { DependencyContainer, Lifecycle } from "tsyringe";
|
||||
|
||||
import { AchievementCallbacks } from "@spt-aki/callbacks/AchievementCallbacks";
|
||||
import { BotCallbacks } from "@spt-aki/callbacks/BotCallbacks";
|
||||
import { BuildsCallbacks } from "@spt-aki/callbacks/BuildsCallbacks";
|
||||
@ -71,18 +70,18 @@ import { BotWeaponGenerator } from "@spt-aki/generators/BotWeaponGenerator";
|
||||
import { FenceBaseAssortGenerator } from "@spt-aki/generators/FenceBaseAssortGenerator";
|
||||
import { LocationGenerator } from "@spt-aki/generators/LocationGenerator";
|
||||
import { LootGenerator } from "@spt-aki/generators/LootGenerator";
|
||||
import { PMCLootGenerator } from "@spt-aki/generators/PMCLootGenerator";
|
||||
import { PlayerScavGenerator } from "@spt-aki/generators/PlayerScavGenerator";
|
||||
import { PMCLootGenerator } from "@spt-aki/generators/PMCLootGenerator";
|
||||
import { RagfairAssortGenerator } from "@spt-aki/generators/RagfairAssortGenerator";
|
||||
import { RagfairOfferGenerator } from "@spt-aki/generators/RagfairOfferGenerator";
|
||||
import { RepeatableQuestGenerator } from "@spt-aki/generators/RepeatableQuestGenerator";
|
||||
import { RepeatableQuestRewardGenerator } from "@spt-aki/generators/RepeatableQuestRewardGenerator";
|
||||
import { ScavCaseRewardGenerator } from "@spt-aki/generators/ScavCaseRewardGenerator";
|
||||
import { WeatherGenerator } from "@spt-aki/generators/WeatherGenerator";
|
||||
import { BarrelInventoryMagGen } from "@spt-aki/generators/weapongen/implementations/BarrelInventoryMagGen";
|
||||
import { ExternalInventoryMagGen } from "@spt-aki/generators/weapongen/implementations/ExternalInventoryMagGen";
|
||||
import { InternalMagazineInventoryMagGen } from "@spt-aki/generators/weapongen/implementations/InternalMagazineInventoryMagGen";
|
||||
import { UbglExternalMagGen } from "@spt-aki/generators/weapongen/implementations/UbglExternalMagGen";
|
||||
import { WeatherGenerator } from "@spt-aki/generators/WeatherGenerator";
|
||||
import { AssortHelper } from "@spt-aki/helpers/AssortHelper";
|
||||
import { BotDifficultyHelper } from "@spt-aki/helpers/BotDifficultyHelper";
|
||||
import { BotGeneratorHelper } from "@spt-aki/helpers/BotGeneratorHelper";
|
||||
@ -133,10 +132,6 @@ import { PostAkiModLoader } from "@spt-aki/loaders/PostAkiModLoader";
|
||||
import { PostDBModLoader } from "@spt-aki/loaders/PostDBModLoader";
|
||||
import { PreAkiModLoader } from "@spt-aki/loaders/PreAkiModLoader";
|
||||
import { IAsyncQueue } from "@spt-aki/models/spt/utils/IAsyncQueue";
|
||||
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
|
||||
import { HttpRouter } from "@spt-aki/routers/HttpRouter";
|
||||
import { ImageRouter } from "@spt-aki/routers/ImageRouter";
|
||||
import { ItemEventRouter } from "@spt-aki/routers/ItemEventRouter";
|
||||
import { BotDynamicRouter } from "@spt-aki/routers/dynamic/BotDynamicRouter";
|
||||
import { BundleDynamicRouter } from "@spt-aki/routers/dynamic/BundleDynamicRouter";
|
||||
import { CustomizationDynamicRouter } from "@spt-aki/routers/dynamic/CustomizationDynamicRouter";
|
||||
@ -146,6 +141,9 @@ import { InraidDynamicRouter } from "@spt-aki/routers/dynamic/InraidDynamicRoute
|
||||
import { LocationDynamicRouter } from "@spt-aki/routers/dynamic/LocationDynamicRouter";
|
||||
import { NotifierDynamicRouter } from "@spt-aki/routers/dynamic/NotifierDynamicRouter";
|
||||
import { TraderDynamicRouter } from "@spt-aki/routers/dynamic/TraderDynamicRouter";
|
||||
import { EventOutputHolder } from "@spt-aki/routers/EventOutputHolder";
|
||||
import { HttpRouter } from "@spt-aki/routers/HttpRouter";
|
||||
import { ImageRouter } from "@spt-aki/routers/ImageRouter";
|
||||
import { CustomizationItemEventRouter } from "@spt-aki/routers/item_events/CustomizationItemEventRouter";
|
||||
import { HealthItemEventRouter } from "@spt-aki/routers/item_events/HealthItemEventRouter";
|
||||
import { HideoutItemEventRouter } from "@spt-aki/routers/item_events/HideoutItemEventRouter";
|
||||
@ -157,6 +155,7 @@ import { RagfairItemEventRouter } from "@spt-aki/routers/item_events/RagfairItem
|
||||
import { RepairItemEventRouter } from "@spt-aki/routers/item_events/RepairItemEventRouter";
|
||||
import { TradeItemEventRouter } from "@spt-aki/routers/item_events/TradeItemEventRouter";
|
||||
import { WishlistItemEventRouter } from "@spt-aki/routers/item_events/WishlistItemEventRouter";
|
||||
import { ItemEventRouter } from "@spt-aki/routers/ItemEventRouter";
|
||||
import { HealthSaveLoadRouter } from "@spt-aki/routers/save_load/HealthSaveLoadRouter";
|
||||
import { InraidSaveLoadRouter } from "@spt-aki/routers/save_load/InraidSaveLoadRouter";
|
||||
import { InsuranceSaveLoadRouter } from "@spt-aki/routers/save_load/InsuranceSaveLoadRouter";
|
||||
@ -188,16 +187,18 @@ import { TraderStaticRouter } from "@spt-aki/routers/static/TraderStaticRouter";
|
||||
import { WeatherStaticRouter } from "@spt-aki/routers/static/WeatherStaticRouter";
|
||||
import { ConfigServer } from "@spt-aki/servers/ConfigServer";
|
||||
import { DatabaseServer } from "@spt-aki/servers/DatabaseServer";
|
||||
import { AkiHttpListener } from "@spt-aki/servers/http/AkiHttpListener";
|
||||
import { HttpServer } from "@spt-aki/servers/HttpServer";
|
||||
import { RagfairServer } from "@spt-aki/servers/RagfairServer";
|
||||
import { SaveServer } from "@spt-aki/servers/SaveServer";
|
||||
import { WebSocketServer } from "@spt-aki/servers/WebSocketServer";
|
||||
import { AkiHttpListener } from "@spt-aki/servers/http/AkiHttpListener";
|
||||
import { BotEquipmentFilterService } from "@spt-aki/services/BotEquipmentFilterService";
|
||||
import { BotEquipmentModPoolService } from "@spt-aki/services/BotEquipmentModPoolService";
|
||||
import { BotGenerationCacheService } from "@spt-aki/services/BotGenerationCacheService";
|
||||
import { BotLootCacheService } from "@spt-aki/services/BotLootCacheService";
|
||||
import { BotWeaponModLimitService } from "@spt-aki/services/BotWeaponModLimitService";
|
||||
import { BundleHashCacheService } from "@spt-aki/services/cache/BundleHashCacheService";
|
||||
import { ModHashCacheService } from "@spt-aki/services/cache/ModHashCacheService";
|
||||
import { CustomLocationWaveService } from "@spt-aki/services/CustomLocationWaveService";
|
||||
import { FenceService } from "@spt-aki/services/FenceService";
|
||||
import { GiftService } from "@spt-aki/services/GiftService";
|
||||
@ -209,6 +210,13 @@ import { LocalisationService } from "@spt-aki/services/LocalisationService";
|
||||
import { MailSendService } from "@spt-aki/services/MailSendService";
|
||||
import { MatchBotDetailsCacheService } from "@spt-aki/services/MatchBotDetailsCacheService";
|
||||
import { MatchLocationService } from "@spt-aki/services/MatchLocationService";
|
||||
import { CustomItemService } from "@spt-aki/services/mod/CustomItemService";
|
||||
import { DynamicRouterModService } from "@spt-aki/services/mod/dynamicRouter/DynamicRouterModService";
|
||||
import { HttpListenerModService } from "@spt-aki/services/mod/httpListener/HttpListenerModService";
|
||||
import { ImageRouteService } from "@spt-aki/services/mod/image/ImageRouteService";
|
||||
import { OnLoadModService } from "@spt-aki/services/mod/onLoad/OnLoadModService";
|
||||
import { OnUpdateModService } from "@spt-aki/services/mod/onUpdate/OnUpdateModService";
|
||||
import { StaticRouterModService } from "@spt-aki/services/mod/staticRouter/StaticRouterModService";
|
||||
import { ModCompilerService } from "@spt-aki/services/ModCompilerService";
|
||||
import { NotificationService } from "@spt-aki/services/NotificationService";
|
||||
import { OpenZoneService } from "@spt-aki/services/OpenZoneService";
|
||||
@ -230,15 +238,6 @@ import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService";
|
||||
import { TraderAssortService } from "@spt-aki/services/TraderAssortService";
|
||||
import { TraderPurchasePersisterService } from "@spt-aki/services/TraderPurchasePersisterService";
|
||||
import { TraderServicesService } from "@spt-aki/services/TraderServicesService";
|
||||
import { BundleHashCacheService } from "@spt-aki/services/cache/BundleHashCacheService";
|
||||
import { ModHashCacheService } from "@spt-aki/services/cache/ModHashCacheService";
|
||||
import { CustomItemService } from "@spt-aki/services/mod/CustomItemService";
|
||||
import { DynamicRouterModService } from "@spt-aki/services/mod/dynamicRouter/DynamicRouterModService";
|
||||
import { HttpListenerModService } from "@spt-aki/services/mod/httpListener/HttpListenerModService";
|
||||
import { ImageRouteService } from "@spt-aki/services/mod/image/ImageRouteService";
|
||||
import { OnLoadModService } from "@spt-aki/services/mod/onLoad/OnLoadModService";
|
||||
import { OnUpdateModService } from "@spt-aki/services/mod/onUpdate/OnUpdateModService";
|
||||
import { StaticRouterModService } from "@spt-aki/services/mod/staticRouter/StaticRouterModService";
|
||||
import { App } from "@spt-aki/utils/App";
|
||||
import { AsyncQueue } from "@spt-aki/utils/AsyncQueue";
|
||||
import { CompareUtil } from "@spt-aki/utils/CompareUtil";
|
||||
@ -249,14 +248,14 @@ import { HttpFileUtil } from "@spt-aki/utils/HttpFileUtil";
|
||||
import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil";
|
||||
import { ImporterUtil } from "@spt-aki/utils/ImporterUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { WinstonMainLogger } from "@spt-aki/utils/logging/WinstonMainLogger";
|
||||
import { WinstonRequestLogger } from "@spt-aki/utils/logging/WinstonRequestLogger";
|
||||
import { MathUtil } from "@spt-aki/utils/MathUtil";
|
||||
import { ObjectId } from "@spt-aki/utils/ObjectId";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
import { VFS } from "@spt-aki/utils/VFS";
|
||||
import { Watermark, WatermarkLocale } from "@spt-aki/utils/Watermark";
|
||||
import { WinstonMainLogger } from "@spt-aki/utils/logging/WinstonMainLogger";
|
||||
import { WinstonRequestLogger } from "@spt-aki/utils/logging/WinstonRequestLogger";
|
||||
|
||||
/**
|
||||
* Handle the registration of classes to be used by the Dependency Injection code
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface OnLoad
|
||||
{
|
||||
onLoad(): Promise<void>;
|
||||
getRoute(): string;
|
||||
onLoad(): Promise<void>
|
||||
getRoute(): string
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface OnUpdate
|
||||
{
|
||||
onUpdate(timeSinceLastRun: number): Promise<boolean>;
|
||||
getRoute(): string;
|
||||
onUpdate(timeSinceLastRun: number): Promise<boolean>
|
||||
getRoute(): string
|
||||
}
|
||||
|
@ -29,9 +29,9 @@ export class Router
|
||||
{
|
||||
if (partialMatch)
|
||||
{
|
||||
return this.getInternalHandledRoutes().filter((r) => r.dynamic).some((r) => url.includes(r.route));
|
||||
return this.getInternalHandledRoutes().filter(r => r.dynamic).some(r => url.includes(r.route));
|
||||
}
|
||||
return this.getInternalHandledRoutes().filter((r) => !r.dynamic).some((r) => r.route === url);
|
||||
return this.getInternalHandledRoutes().filter(r => !r.dynamic).some(r => r.route === url);
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,12 +44,12 @@ export class StaticRouter extends Router
|
||||
|
||||
public async handleStatic(url: string, info: any, sessionID: string, output: string): Promise<any>
|
||||
{
|
||||
return this.routes.find((route) => route.url === url).action(url, info, sessionID, output);
|
||||
return this.routes.find(route => route.url === url).action(url, info, sessionID, output);
|
||||
}
|
||||
|
||||
public override getHandledRoutes(): HandledRoute[]
|
||||
{
|
||||
return this.routes.map((route) => new HandledRoute(route.url, false));
|
||||
return this.routes.map(route => new HandledRoute(route.url, false));
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,12 +62,12 @@ export class DynamicRouter extends Router
|
||||
|
||||
public async handleDynamic(url: string, info: any, sessionID: string, output: string): Promise<any>
|
||||
{
|
||||
return this.routes.find((r) => url.includes(r.url)).action(url, info, sessionID, output);
|
||||
return this.routes.find(r => url.includes(r.url)).action(url, info, sessionID, output);
|
||||
}
|
||||
|
||||
public override getHandledRoutes(): HandledRoute[]
|
||||
{
|
||||
return this.routes.map((route) => new HandledRoute(route.url, true));
|
||||
return this.routes.map(route => new HandledRoute(route.url, true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotGeneratorHelper } from "@spt-aki/helpers/BotGeneratorHelper";
|
||||
import { BotHelper } from "@spt-aki/helpers/BotHelper";
|
||||
import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper";
|
||||
@ -234,8 +233,8 @@ export class BotEquipmentModGenerator
|
||||
}
|
||||
|
||||
// Get the front/back/side weights based on bots level
|
||||
const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find((armorWeight) =>
|
||||
settings.botLevel >= armorWeight.levelRange.min && settings.botLevel <= armorWeight.levelRange.max
|
||||
const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find(armorWeight =>
|
||||
settings.botLevel >= armorWeight.levelRange.min && settings.botLevel <= armorWeight.levelRange.max,
|
||||
);
|
||||
if (!plateSlotWeights)
|
||||
{
|
||||
@ -261,17 +260,17 @@ export class BotEquipmentModGenerator
|
||||
const chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue<string>(plateWeights);
|
||||
|
||||
// Convert the array of ids into database items
|
||||
const platesFromDb = existingPlateTplPool.map((plateTpl) => this.itemHelper.getItem(plateTpl)[1]);
|
||||
const platesFromDb = existingPlateTplPool.map(plateTpl => this.itemHelper.getItem(plateTpl)[1]);
|
||||
|
||||
// Filter plates to the chosen level based on its armorClass property
|
||||
const filteredPlates = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel);
|
||||
const filteredPlates = platesFromDb.filter(item => item._props.armorClass === chosenArmorPlateLevel);
|
||||
if (filteredPlates.length === 0)
|
||||
{
|
||||
this.logger.debug(
|
||||
`Plate filter was too restrictive for armor: ${armorItem._id}, unable to find plates of level: ${chosenArmorPlateLevel}. Using mod items default plate`,
|
||||
);
|
||||
|
||||
const relatedItemDbModSlot = armorItem._props.Slots.find((slot) => slot._name.toLowerCase() === modSlot);
|
||||
const relatedItemDbModSlot = armorItem._props.Slots.find(slot => slot._name.toLowerCase() === modSlot);
|
||||
const defaultPlate = relatedItemDbModSlot._props.filters[0].Plate;
|
||||
if (!defaultPlate)
|
||||
{
|
||||
@ -281,8 +280,8 @@ export class BotEquipmentModGenerator
|
||||
const defaultPreset = this.presetHelper.getDefaultPreset(armorItem._id);
|
||||
if (defaultPreset)
|
||||
{
|
||||
const relatedPresetSlot = defaultPreset._items.find((item) =>
|
||||
item.slotId?.toLowerCase() === modSlot
|
||||
const relatedPresetSlot = defaultPreset._items.find(item =>
|
||||
item.slotId?.toLowerCase() === modSlot,
|
||||
);
|
||||
if (relatedPresetSlot)
|
||||
{
|
||||
@ -306,7 +305,7 @@ export class BotEquipmentModGenerator
|
||||
|
||||
// Only return the items ids
|
||||
result.result = Result.SUCCESS;
|
||||
result.plateModTpls = filteredPlates.map((item) => item._id);
|
||||
result.plateModTpls = filteredPlates.map(item => item._id);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -346,8 +345,8 @@ export class BotEquipmentModGenerator
|
||||
const compatibleModsPool = modPool[parentTemplate._id];
|
||||
|
||||
if (
|
||||
!((parentTemplate._props.Slots.length || parentTemplate._props.Cartridges?.length)
|
||||
|| parentTemplate._props.Chambers?.length)
|
||||
!(parentTemplate._props.Slots.length || parentTemplate._props.Cartridges?.length
|
||||
|| parentTemplate._props.Chambers?.length)
|
||||
)
|
||||
{
|
||||
this.logger.error(
|
||||
@ -468,10 +467,10 @@ export class BotEquipmentModGenerator
|
||||
// Handguard mod can take a sub handguard mod + weapon has no UBGL (takes same slot)
|
||||
// Force spawn chance to be 100% to ensure it gets added
|
||||
if (
|
||||
modSlot === "mod_handguard" && modToAddTemplate._props.Slots.find((slot) =>
|
||||
slot._name === "mod_handguard"
|
||||
modSlot === "mod_handguard" && modToAddTemplate._props.Slots.find(slot =>
|
||||
slot._name === "mod_handguard",
|
||||
)
|
||||
&& !weapon.find((item) => item.slotId === "mod_launcher")
|
||||
&& !weapon.find(item => item.slotId === "mod_launcher")
|
||||
)
|
||||
{
|
||||
// Needed for handguards with lower
|
||||
@ -481,9 +480,9 @@ export class BotEquipmentModGenerator
|
||||
// If stock mod can take a sub stock mod, force spawn chance to be 100% to ensure sub-stock gets added
|
||||
// Or if mod_stock is configured to be forced on
|
||||
if (
|
||||
modSlot === "mod_stock" && (modToAddTemplate._props.Slots.find((slot) =>
|
||||
slot._name.includes("mod_stock") || botEquipConfig.forceStock
|
||||
))
|
||||
modSlot === "mod_stock" && modToAddTemplate._props.Slots.find(slot =>
|
||||
slot._name.includes("mod_stock") || botEquipConfig.forceStock,
|
||||
)
|
||||
)
|
||||
{
|
||||
// Stock mod can take additional stocks, could be a locking device, force 100% chance
|
||||
@ -700,11 +699,11 @@ export class BotEquipmentModGenerator
|
||||
case "patron_in_weapon":
|
||||
case "patron_in_weapon_000":
|
||||
case "patron_in_weapon_001":
|
||||
return parentTemplate._props.Chambers.find((chamber) => chamber._name.includes(modSlotLower));
|
||||
return parentTemplate._props.Chambers.find(chamber => chamber._name.includes(modSlotLower));
|
||||
case "cartridges":
|
||||
return parentTemplate._props.Cartridges.find((c) => c._name.toLowerCase() === modSlotLower);
|
||||
return parentTemplate._props.Cartridges.find(c => c._name.toLowerCase() === modSlotLower);
|
||||
default:
|
||||
return parentTemplate._props.Slots.find((s) => s._name.toLowerCase() === modSlotLower);
|
||||
return parentTemplate._props.Slots.find(s => s._name.toLowerCase() === modSlotLower);
|
||||
}
|
||||
}
|
||||
|
||||
@ -762,7 +761,7 @@ export class BotEquipmentModGenerator
|
||||
): [boolean, ITemplateItem]
|
||||
{
|
||||
/** Slot mod will fill */
|
||||
const parentSlot = parentTemplate._props.Slots.find((i) => i._name === modSlot);
|
||||
const parentSlot = parentTemplate._props.Slots.find(i => i._name === modSlot);
|
||||
const weaponTemplate = this.itemHelper.getItem(weapon[0]._tpl)[1];
|
||||
|
||||
// It's ammo, use predefined ammo parameter
|
||||
@ -950,8 +949,8 @@ export class BotEquipmentModGenerator
|
||||
if (modSpawnResult === ModSpawn.DEFAULT_MOD)
|
||||
{
|
||||
const matchingPreset = this.getMatchingPreset(weaponTemplate, parentTemplate._id);
|
||||
const matchingMod = matchingPreset._items.find((item) =>
|
||||
item?.slotId?.toLowerCase() === modSlot.toLowerCase()
|
||||
const matchingMod = matchingPreset._items.find(item =>
|
||||
item?.slotId?.toLowerCase() === modSlot.toLowerCase(),
|
||||
);
|
||||
|
||||
// Only filter mods down to single default item if it already exists in existing itemModPool, OR the default item has no children
|
||||
@ -967,8 +966,8 @@ export class BotEquipmentModGenerator
|
||||
}
|
||||
|
||||
// Check the filter of the slot to ensure a chosen mod fits
|
||||
const parentSlotCompatibleItems = parentTemplate._props.Slots?.find((slot) =>
|
||||
slot._name.toLowerCase() === modSlot.toLowerCase()
|
||||
const parentSlotCompatibleItems = parentTemplate._props.Slots?.find(slot =>
|
||||
slot._name.toLowerCase() === modSlot.toLowerCase(),
|
||||
)._props.filters[0].Filter;
|
||||
|
||||
// Mod isnt in existing pool, only add if it has no children and matches parent filter
|
||||
@ -1176,7 +1175,7 @@ export class BotEquipmentModGenerator
|
||||
botEquipBlacklist: EquipmentFilterDetails,
|
||||
): void
|
||||
{
|
||||
const desiredSlotObject = modTemplate._props.Slots.find((slot) => slot._name.includes(desiredSlotName));
|
||||
const desiredSlotObject = modTemplate._props.Slots.find(slot => slot._name.includes(desiredSlotName));
|
||||
if (desiredSlotObject)
|
||||
{
|
||||
const supportedSubMods = desiredSlotObject._props.filters[0].Filter;
|
||||
@ -1262,7 +1261,7 @@ export class BotEquipmentModGenerator
|
||||
const blacklist = this.itemFilterService.getBlacklistedItems().concat(
|
||||
botEquipBlacklist.equipment[modSlot] || [],
|
||||
);
|
||||
result = allowedMods.filter((tpl) => !blacklist.includes(tpl));
|
||||
result = allowedMods.filter(tpl => !blacklist.includes(tpl));
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1288,7 +1287,7 @@ export class BotEquipmentModGenerator
|
||||
weaponName: parentTemplate._name,
|
||||
}),
|
||||
);
|
||||
const camoraSlots = parentTemplate._props.Slots.filter((slot) => slot._name.startsWith("camora"));
|
||||
const camoraSlots = parentTemplate._props.Slots.filter(slot => slot._name.startsWith("camora"));
|
||||
|
||||
// Attempt to generate camora slots for item
|
||||
modPool[parentTemplate._id] = {};
|
||||
@ -1422,17 +1421,17 @@ export class BotEquipmentModGenerator
|
||||
{
|
||||
// Check to see if mount has a scope slot (only include primary slot, ignore the rest like the backup sight slots)
|
||||
// Should only find 1 as there's currently no items with a mod_scope AND a mod_scope_000
|
||||
const scopeSlot = itemDetails._props.Slots.filter((slot) =>
|
||||
["mod_scope", "mod_scope_000"].includes(slot._name)
|
||||
const scopeSlot = itemDetails._props.Slots.filter(slot =>
|
||||
["mod_scope", "mod_scope_000"].includes(slot._name),
|
||||
);
|
||||
|
||||
// Mods scope slot found must allow ALL whitelisted scope types OR be a mount
|
||||
if (
|
||||
scopeSlot?.every((slot) =>
|
||||
slot._props.filters[0].Filter.every((tpl) =>
|
||||
scopeSlot?.every(slot =>
|
||||
slot._props.filters[0].Filter.every(tpl =>
|
||||
this.itemHelper.isOfBaseclasses(tpl, whitelistedSightTypes)
|
||||
|| this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT)
|
||||
)
|
||||
|| this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT),
|
||||
),
|
||||
)
|
||||
)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotInventoryGenerator } from "@spt-aki/generators/BotInventoryGenerator";
|
||||
import { BotLevelGenerator } from "@spt-aki/generators/BotLevelGenerator";
|
||||
import { BotDifficultyHelper } from "@spt-aki/helpers/BotDifficultyHelper";
|
||||
@ -111,7 +110,7 @@ export class BotGenerator
|
||||
|
||||
// Get raw json data for bot (Cloned)
|
||||
const botJsonTemplateClone = this.jsonUtil.clone(
|
||||
this.botHelper.getBotTemplate((botGenerationDetails.isPmc) ? bot.Info.Side : botGenerationDetails.role),
|
||||
this.botHelper.getBotTemplate(botGenerationDetails.isPmc ? bot.Info.Side : botGenerationDetails.role),
|
||||
);
|
||||
|
||||
bot = this.generateBot(sessionId, bot, botJsonTemplateClone, botGenerationDetails);
|
||||
@ -446,7 +445,7 @@ export class BotGenerator
|
||||
}
|
||||
|
||||
return skillToAdd;
|
||||
}).filter((x) => x !== null);
|
||||
}).filter(x => x !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -546,7 +545,7 @@ export class BotGenerator
|
||||
Nickname: bot.Info.Nickname,
|
||||
Side: bot.Info.Side,
|
||||
Level: bot.Info.Level,
|
||||
Time: (new Date().toISOString()),
|
||||
Time: new Date().toISOString(),
|
||||
Status: "Killed by ",
|
||||
KillerAccountId: "Unknown",
|
||||
KillerProfileId: "Unknown",
|
||||
@ -557,7 +556,7 @@ export class BotGenerator
|
||||
|
||||
const inventoryItem: Item = {
|
||||
_id: this.hashUtil.generate(),
|
||||
_tpl: ((bot.Info.Side === "Usec") ? BaseClasses.DOG_TAG_USEC : BaseClasses.DOG_TAG_BEAR),
|
||||
_tpl: bot.Info.Side === "Usec" ? BaseClasses.DOG_TAG_USEC : BaseClasses.DOG_TAG_BEAR,
|
||||
parentId: bot.Inventory.equipment,
|
||||
slotId: "Dogtag",
|
||||
location: undefined,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotEquipmentModGenerator } from "@spt-aki/generators/BotEquipmentModGenerator";
|
||||
import { BotLootGenerator } from "@spt-aki/generators/BotLootGenerator";
|
||||
import { BotWeaponGenerator } from "@spt-aki/generators/BotWeaponGenerator";
|
||||
@ -308,12 +307,11 @@ export class BotInventoryGenerator
|
||||
*/
|
||||
protected generateEquipment(settings: IGenerateEquipmentProperties): boolean
|
||||
{
|
||||
const spawnChance =
|
||||
([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[]).includes(
|
||||
settings.rootEquipmentSlot,
|
||||
)
|
||||
? 100
|
||||
: settings.spawnChances.equipment[settings.rootEquipmentSlot];
|
||||
const spawnChance = ([EquipmentSlots.POCKETS, EquipmentSlots.SECURED_CONTAINER] as string[])
|
||||
.includes(settings.rootEquipmentSlot)
|
||||
? 100
|
||||
: settings.spawnChances.equipment[settings.rootEquipmentSlot];
|
||||
|
||||
if (typeof spawnChance === "undefined")
|
||||
{
|
||||
this.logger.warning(
|
||||
@ -444,7 +442,7 @@ export class BotInventoryGenerator
|
||||
for (const modSlot of Object.keys(modPool ?? []))
|
||||
{
|
||||
const blacklistedMods = equipmentBlacklist[0]?.equipment[modSlot] || [];
|
||||
const filteredMods = modPool[modSlot].filter((x) => !blacklistedMods.includes(x));
|
||||
const filteredMods = modPool[modSlot].filter(x => !blacklistedMods.includes(x));
|
||||
|
||||
if (filteredMods.length > 0)
|
||||
{
|
||||
@ -503,7 +501,7 @@ export class BotInventoryGenerator
|
||||
* @param equipmentChances Chances bot has certain equipment
|
||||
* @returns What slots bot should have weapons generated for
|
||||
*/
|
||||
protected getDesiredWeaponsForBot(equipmentChances: Chances): { slot: EquipmentSlots; shouldSpawn: boolean; }[]
|
||||
protected getDesiredWeaponsForBot(equipmentChances: Chances): { slot: EquipmentSlots, shouldSpawn: boolean }[]
|
||||
{
|
||||
const shouldSpawnPrimary = this.randomUtil.getChance100(equipmentChances.equipment.FirstPrimaryWeapon);
|
||||
return [{ slot: EquipmentSlots.FIRST_PRIMARY_WEAPON, shouldSpawn: shouldSpawnPrimary }, {
|
||||
@ -532,7 +530,7 @@ export class BotInventoryGenerator
|
||||
*/
|
||||
protected addWeaponAndMagazinesToInventory(
|
||||
sessionId: string,
|
||||
weaponSlot: { slot: EquipmentSlots; shouldSpawn: boolean; },
|
||||
weaponSlot: { slot: EquipmentSlots, shouldSpawn: boolean },
|
||||
templateInventory: Inventory,
|
||||
botInventory: PmcInventory,
|
||||
equipmentChances: Chances,
|
||||
@ -567,18 +565,18 @@ export class BotInventoryGenerator
|
||||
export interface IGenerateEquipmentProperties
|
||||
{
|
||||
/** Root Slot being generated */
|
||||
rootEquipmentSlot: string;
|
||||
rootEquipmentSlot: string
|
||||
/** Equipment pool for root slot being generated */
|
||||
rootEquipmentPool: Record<string, number>;
|
||||
modPool: Mods;
|
||||
rootEquipmentPool: Record<string, number>
|
||||
modPool: Mods
|
||||
/** Dictionary of mod items and their chance to spawn for this bot type */
|
||||
spawnChances: Chances;
|
||||
spawnChances: Chances
|
||||
/** Role being generated for */
|
||||
botRole: string;
|
||||
botRole: string
|
||||
/** Level of bot being generated */
|
||||
botLevel: number;
|
||||
inventory: PmcInventory;
|
||||
botEquipmentConfig: EquipmentFilters;
|
||||
botLevel: number
|
||||
inventory: PmcInventory
|
||||
botEquipmentConfig: EquipmentFilters
|
||||
/** Settings from bot.json to adjust how item is generated */
|
||||
randomisationDetails: RandomisationDetails;
|
||||
randomisationDetails: RandomisationDetails
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { MinMax } from "@spt-aki/models/common/MinMax";
|
||||
import { IRandomisedBotLevelResult } from "@spt-aki/models/eft/bot/IRandomisedBotLevelResult";
|
||||
import { IBotBase } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
@ -66,7 +65,7 @@ export class BotLevelGenerator
|
||||
maxLevel: number,
|
||||
): number
|
||||
{
|
||||
const maxPossibleLevel = (botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride)
|
||||
const maxPossibleLevel = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
|
||||
? Math.min(botGenerationDetails.locationSpecificPmcLevelOverride.max, maxLevel) // Was a PMC and they have a level override
|
||||
: Math.min(levelDetails.max, maxLevel); // Not pmc with override or non-pmc
|
||||
|
||||
@ -92,7 +91,7 @@ export class BotLevelGenerator
|
||||
maxlevel: number,
|
||||
): number
|
||||
{
|
||||
const minPossibleLevel = (botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride)
|
||||
const minPossibleLevel = botGenerationDetails.isPmc && botGenerationDetails.locationSpecificPmcLevelOverride
|
||||
? Math.min(
|
||||
Math.max(levelDetails.min, botGenerationDetails.locationSpecificPmcLevelOverride.min), // Biggest between json min and the botgen min
|
||||
maxlevel, // Fallback if value above is crazy (default is 79)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotWeaponGenerator } from "@spt-aki/generators/BotWeaponGenerator";
|
||||
import { BotGeneratorHelper } from "@spt-aki/helpers/BotGeneratorHelper";
|
||||
import { BotHelper } from "@spt-aki/helpers/BotHelper";
|
||||
@ -292,7 +291,7 @@ export class BotLootGenerator
|
||||
// Secure
|
||||
|
||||
// only add if not a pmc or is pmc and flag is true
|
||||
if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig))
|
||||
if (!isPmc || isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig)
|
||||
{
|
||||
this.addLootFromPool(
|
||||
this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate),
|
||||
@ -317,12 +316,12 @@ export class BotLootGenerator
|
||||
{
|
||||
const result = [EquipmentSlots.POCKETS];
|
||||
|
||||
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.TACTICAL_VEST))
|
||||
if (botInventory.items.find(item => item.slotId === EquipmentSlots.TACTICAL_VEST))
|
||||
{
|
||||
result.push(EquipmentSlots.TACTICAL_VEST);
|
||||
}
|
||||
|
||||
if (botInventory.items.find((item) => item.slotId === EquipmentSlots.BACKPACK))
|
||||
if (botInventory.items.find(item => item.slotId === EquipmentSlots.BACKPACK))
|
||||
{
|
||||
result.push(EquipmentSlots.BACKPACK);
|
||||
}
|
||||
@ -476,7 +475,7 @@ export class BotLootGenerator
|
||||
);
|
||||
}
|
||||
|
||||
itemWithChildrenToAdd.push(...itemsToAdd.flatMap((moneyStack) => moneyStack));
|
||||
itemWithChildrenToAdd.push(...itemsToAdd.flatMap(moneyStack => moneyStack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectAll, injectable } from "tsyringe";
|
||||
|
||||
import { BotEquipmentModGenerator } from "@spt-aki/generators/BotEquipmentModGenerator";
|
||||
import { IInventoryMagGen } from "@spt-aki/generators/weapongen/IInventoryMagGen";
|
||||
import { InventoryMagGen } from "@spt-aki/generators/weapongen/InventoryMagGen";
|
||||
@ -200,7 +199,7 @@ export class BotWeaponGenerator
|
||||
}
|
||||
|
||||
// Fill existing magazines to full and sync ammo type
|
||||
for (const magazine of weaponWithModsArray.filter((item) => item.slotId === this.modMagazineSlotId))
|
||||
for (const magazine of weaponWithModsArray.filter(item => item.slotId === this.modMagazineSlotId))
|
||||
{
|
||||
this.fillExistingMagazines(weaponWithModsArray, magazine, ammoTpl);
|
||||
}
|
||||
@ -212,12 +211,12 @@ export class BotWeaponGenerator
|
||||
)
|
||||
{
|
||||
// Guns have variety of possible Chamber ids, patron_in_weapon/patron_in_weapon_000/patron_in_weapon_001
|
||||
const chamberSlotNames = weaponItemTemplate._props.Chambers.map((x) => x._name);
|
||||
const chamberSlotNames = weaponItemTemplate._props.Chambers.map(x => x._name);
|
||||
this.addCartridgeToChamber(weaponWithModsArray, ammoTpl, chamberSlotNames);
|
||||
}
|
||||
|
||||
// Fill UBGL if found
|
||||
const ubglMod = weaponWithModsArray.find((x) => x.slotId === "mod_launcher");
|
||||
const ubglMod = weaponWithModsArray.find(x => x.slotId === "mod_launcher");
|
||||
let ubglAmmoTpl: string = undefined;
|
||||
if (ubglMod)
|
||||
{
|
||||
@ -246,7 +245,7 @@ export class BotWeaponGenerator
|
||||
{
|
||||
for (const slotId of chamberSlotIds)
|
||||
{
|
||||
const existingItemWithSlot = weaponWithModsArray.find((x) => x.slotId === slotId);
|
||||
const existingItemWithSlot = weaponWithModsArray.find(x => x.slotId === slotId);
|
||||
if (!existingItemWithSlot)
|
||||
{
|
||||
// Not found, add new slot to weapon
|
||||
@ -367,11 +366,11 @@ export class BotWeaponGenerator
|
||||
}
|
||||
|
||||
// Iterate over required slots in db item, check mod exists for that slot
|
||||
for (const modSlotTemplate of modTemplate._props.Slots.filter((slot) => slot._required))
|
||||
for (const modSlotTemplate of modTemplate._props.Slots.filter(slot => slot._required))
|
||||
{
|
||||
const slotName = modSlotTemplate._name;
|
||||
const weaponSlotItem = weaponItemArray.find((weaponItem) =>
|
||||
weaponItem.parentId === mod._id && weaponItem.slotId === slotName
|
||||
const weaponSlotItem = weaponItemArray.find(weaponItem =>
|
||||
weaponItem.parentId === mod._id && weaponItem.slotId === slotName,
|
||||
);
|
||||
if (!weaponSlotItem)
|
||||
{
|
||||
@ -442,7 +441,7 @@ export class BotWeaponGenerator
|
||||
ammoTemplate,
|
||||
inventory,
|
||||
);
|
||||
this.inventoryMagGenComponents.find((v) => v.canHandleInventoryMagGen(inventoryMagGenModel)).process(
|
||||
this.inventoryMagGenComponents.find(v => v.canHandleInventoryMagGen(inventoryMagGenModel)).process(
|
||||
inventoryMagGenModel,
|
||||
);
|
||||
|
||||
@ -468,13 +467,13 @@ export class BotWeaponGenerator
|
||||
): void
|
||||
{
|
||||
// Find ubgl mod item + get details of it from db
|
||||
const ubglMod = weaponMods.find((x) => x.slotId === "mod_launcher");
|
||||
const ubglMod = weaponMods.find(x => x.slotId === "mod_launcher");
|
||||
const ubglDbTemplate = this.itemHelper.getItem(ubglMod._tpl)[1];
|
||||
|
||||
// Define min/max of how many grenades bot will have
|
||||
const ubglMinMax: GenerationData = {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
weights: { "1": 1, "2": 1 },
|
||||
weights: { 1: 1, 2: 1 },
|
||||
whitelist: {},
|
||||
};
|
||||
|
||||
@ -489,7 +488,7 @@ export class BotWeaponGenerator
|
||||
ubglAmmoDbTemplate,
|
||||
inventory,
|
||||
);
|
||||
this.inventoryMagGenComponents.find((v) => v.canHandleInventoryMagGen(ubglAmmoGenModel)).process(
|
||||
this.inventoryMagGenComponents.find(v => v.canHandleInventoryMagGen(ubglAmmoGenModel)).process(
|
||||
ubglAmmoGenModel,
|
||||
);
|
||||
|
||||
@ -537,7 +536,7 @@ export class BotWeaponGenerator
|
||||
botRole: string,
|
||||
): string
|
||||
{
|
||||
const magazine = weaponMods.find((m) => m.slotId === this.modMagazineSlotId);
|
||||
const magazine = weaponMods.find(m => m.slotId === this.modMagazineSlotId);
|
||||
if (!magazine)
|
||||
{
|
||||
// Edge case - magazineless chamber loaded weapons dont have magazines, e.g. mp18
|
||||
@ -737,8 +736,8 @@ export class BotWeaponGenerator
|
||||
magazineTemplate: ITemplateItem,
|
||||
): void
|
||||
{
|
||||
const magazineCartridgeChildItem = weaponWithMods.find((m) =>
|
||||
m.parentId === magazine._id && m.slotId === "cartridges"
|
||||
const magazineCartridgeChildItem = weaponWithMods.find(m =>
|
||||
m.parentId === magazine._id && m.slotId === "cartridges",
|
||||
);
|
||||
if (magazineCartridgeChildItem)
|
||||
{
|
||||
@ -767,7 +766,7 @@ export class BotWeaponGenerator
|
||||
// for CylinderMagazine we exchange the ammo in the "camoras".
|
||||
// This might not be necessary since we already filled the camoras with a random whitelisted and compatible ammo type,
|
||||
// but I'm not sure whether this is also used elsewhere
|
||||
const camoras = weaponMods.filter((x) => x.parentId === magazineId && x.slotId.startsWith("camora"));
|
||||
const camoras = weaponMods.filter(x => x.parentId === magazineId && x.slotId.startsWith("camora"));
|
||||
for (const camora of camoras)
|
||||
{
|
||||
camora._tpl = ammoTpl;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
@ -50,7 +49,7 @@ export class FenceBaseAssortGenerator
|
||||
const blockedSeasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems();
|
||||
const baseFenceAssort = this.databaseServer.getTables().traders[Traders.FENCE].assort;
|
||||
|
||||
for (const rootItemDb of this.itemHelper.getItems().filter((item) => this.isValidFenceItem(item)))
|
||||
for (const rootItemDb of this.itemHelper.getItems().filter(item => this.isValidFenceItem(item)))
|
||||
{
|
||||
// Skip blacklisted items
|
||||
if (this.itemFilterService.isItemBlacklisted(rootItemDb._id))
|
||||
@ -144,7 +143,7 @@ export class FenceBaseAssortGenerator
|
||||
for (const defaultPreset of defaultPresets)
|
||||
{
|
||||
// Skip presets we've already added
|
||||
if (baseFenceAssort.items.some((item) => item.upd && item.upd.sptPresetId === defaultPreset._id))
|
||||
if (baseFenceAssort.items.some(item => item.upd && item.upd.sptPresetId === defaultPreset._id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -252,7 +251,7 @@ export class FenceBaseAssortGenerator
|
||||
}
|
||||
|
||||
// Check for and add required soft inserts to armors
|
||||
const requiredSlots = itemDbDetails._props.Slots.filter((slot) => slot._required);
|
||||
const requiredSlots = itemDbDetails._props.Slots.filter(slot => slot._required);
|
||||
const hasRequiredSlots = requiredSlots.length > 0;
|
||||
if (hasRequiredSlots)
|
||||
{
|
||||
@ -284,8 +283,8 @@ export class FenceBaseAssortGenerator
|
||||
}
|
||||
|
||||
// Check for and add plate items
|
||||
const plateSlots = itemDbDetails._props.Slots.filter((slot) =>
|
||||
this.itemHelper.isRemovablePlateSlot(slot._name)
|
||||
const plateSlots = itemDbDetails._props.Slots.filter(slot =>
|
||||
this.itemHelper.isRemovablePlateSlot(slot._name),
|
||||
);
|
||||
if (plateSlots.length > 0)
|
||||
{
|
||||
|
@ -1,7 +1,7 @@
|
||||
export interface IFilterPlateModsForSlotByLevelResult
|
||||
{
|
||||
result: Result;
|
||||
plateModTpls: string[];
|
||||
result: Result
|
||||
plateModTpls: string[]
|
||||
}
|
||||
|
||||
export enum Result
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ContainerHelper } from "@spt-aki/helpers/ContainerHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
@ -31,17 +30,17 @@ import { ProbabilityObject, ProbabilityObjectArray, RandomUtil } from "@spt-aki/
|
||||
|
||||
export interface IContainerItem
|
||||
{
|
||||
items: Item[];
|
||||
width: number;
|
||||
height: number;
|
||||
items: Item[]
|
||||
width: number
|
||||
height: number
|
||||
}
|
||||
|
||||
export interface IContainerGroupCount
|
||||
{
|
||||
/** Containers this group has + probabilty to spawn */
|
||||
containerIdsWithProbability: Record<string, number>;
|
||||
containerIdsWithProbability: Record<string, number>
|
||||
/** How many containers the map should spawn with this group id */
|
||||
chosenCount: number;
|
||||
chosenCount: number
|
||||
}
|
||||
|
||||
@injectable()
|
||||
@ -136,7 +135,7 @@ export class LocationGenerator
|
||||
// Randomisation is turned off globally or just turned off for this map
|
||||
if (
|
||||
!(this.locationConfig.containerRandomisationSettings.enabled
|
||||
&& this.locationConfig.containerRandomisationSettings.maps[locationId])
|
||||
&& this.locationConfig.containerRandomisationSettings.maps[locationId])
|
||||
)
|
||||
{
|
||||
this.logger.debug(
|
||||
@ -219,8 +218,8 @@ export class LocationGenerator
|
||||
for (const chosenContainerId of chosenContainerIds)
|
||||
{
|
||||
// Look up container object from full list of containers on map
|
||||
const containerObject = staticRandomisableContainersOnMap.find((staticContainer) =>
|
||||
staticContainer.template.Id === chosenContainerId
|
||||
const containerObject = staticRandomisableContainersOnMap.find(staticContainer =>
|
||||
staticContainer.template.Id === chosenContainerId,
|
||||
);
|
||||
if (!containerObject)
|
||||
{
|
||||
@ -263,11 +262,11 @@ export class LocationGenerator
|
||||
*/
|
||||
protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[]
|
||||
{
|
||||
return staticContainers.filter((staticContainer) =>
|
||||
return staticContainers.filter(staticContainer =>
|
||||
staticContainer.probability !== 1 && !staticContainer.template.IsAlwaysSpawn
|
||||
&& !this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes(
|
||||
staticContainer.template.Items[0]._tpl,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -278,11 +277,11 @@ export class LocationGenerator
|
||||
*/
|
||||
protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[]
|
||||
{
|
||||
return staticContainersOnMap.filter((staticContainer) =>
|
||||
return staticContainersOnMap.filter(staticContainer =>
|
||||
staticContainer.probability === 1 || staticContainer.template.IsAlwaysSpawn
|
||||
|| this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes(
|
||||
staticContainer.template.Items[0]._tpl,
|
||||
)
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -339,11 +338,11 @@ export class LocationGenerator
|
||||
chosenCount: this.randomUtil.getInt(
|
||||
Math.round(
|
||||
groupData.minContainers
|
||||
* this.locationConfig.containerRandomisationSettings.containerGroupMinSizeMultiplier,
|
||||
* this.locationConfig.containerRandomisationSettings.containerGroupMinSizeMultiplier,
|
||||
),
|
||||
Math.round(
|
||||
groupData.maxContainers
|
||||
* this.locationConfig.containerRandomisationSettings.containerGroupMaxSizeMultiplier,
|
||||
* this.locationConfig.containerRandomisationSettings.containerGroupMaxSizeMultiplier,
|
||||
),
|
||||
),
|
||||
};
|
||||
@ -413,9 +412,9 @@ export class LocationGenerator
|
||||
const containerLootPool = this.getPossibleLootItemsForContainer(containerTpl, staticLootDist);
|
||||
|
||||
// Some containers need to have items forced into it (quest keys etc)
|
||||
const tplsForced = staticForced.filter((forcedStaticProp) =>
|
||||
forcedStaticProp.containerId === containerClone.template.Id
|
||||
).map((x) => x.itemTpl);
|
||||
const tplsForced = staticForced.filter(forcedStaticProp =>
|
||||
forcedStaticProp.containerId === containerClone.template.Id,
|
||||
).map(x => x.itemTpl);
|
||||
|
||||
// Draw random loot
|
||||
// Money spawn more than once in container
|
||||
@ -428,7 +427,7 @@ export class LocationGenerator
|
||||
itemCountToAdd,
|
||||
this.locationConfig.allowDuplicateItemsInStaticContainers,
|
||||
locklist,
|
||||
).filter((tpl) => !tplsForced.includes(tpl));
|
||||
).filter(tpl => !tplsForced.includes(tpl));
|
||||
|
||||
// Add forced loot to chosen item pool
|
||||
const tplsToAddToContainer = tplsForced.concat(chosenTpls);
|
||||
@ -598,7 +597,7 @@ export class LocationGenerator
|
||||
|
||||
// Build the list of forced loot from both `spawnpointsForced` and any point marked `IsAlwaysSpawn`
|
||||
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpointsForced);
|
||||
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpoints.filter((point) => point.template.IsAlwaysSpawn));
|
||||
dynamicForcedSpawnPoints.push(...dynamicLootDist.spawnpoints.filter(point => point.template.IsAlwaysSpawn));
|
||||
|
||||
// Add forced loot
|
||||
this.addForcedLoot(loot, dynamicForcedSpawnPoints, locationName);
|
||||
@ -608,10 +607,10 @@ export class LocationGenerator
|
||||
// Draw from random distribution
|
||||
const desiredSpawnpointCount = Math.round(
|
||||
this.getLooseLootMultiplerForLocation(locationName)
|
||||
* this.randomUtil.getNormallyDistributedRandomNumber(
|
||||
dynamicLootDist.spawnpointCount.mean,
|
||||
dynamicLootDist.spawnpointCount.std,
|
||||
),
|
||||
* this.randomUtil.getNormallyDistributedRandomNumber(
|
||||
dynamicLootDist.spawnpointCount.mean,
|
||||
dynamicLootDist.spawnpointCount.std,
|
||||
),
|
||||
);
|
||||
|
||||
// Positions not in forced but have 100% chance to spawn
|
||||
@ -661,11 +660,11 @@ export class LocationGenerator
|
||||
|
||||
// Filter out duplicate locationIds
|
||||
chosenSpawnpoints = [
|
||||
...new Map(chosenSpawnpoints.map((spawnPoint) => [spawnPoint.locationId, spawnPoint])).values(),
|
||||
...new Map(chosenSpawnpoints.map(spawnPoint => [spawnPoint.locationId, spawnPoint])).values(),
|
||||
];
|
||||
|
||||
// Do we have enough items in pool to fulfill requirement
|
||||
const tooManySpawnPointsRequested = (desiredSpawnpointCount - chosenSpawnpoints.length) > 0;
|
||||
const tooManySpawnPointsRequested = desiredSpawnpointCount - chosenSpawnpoints.length > 0;
|
||||
if (tooManySpawnPointsRequested)
|
||||
{
|
||||
this.logger.debug(
|
||||
@ -705,7 +704,7 @@ export class LocationGenerator
|
||||
{
|
||||
if (
|
||||
!seasonalEventActive && seasonalItemTplBlacklist.includes(
|
||||
spawnPoint.template.Items.find((item) => item._id === itemDist.composedKey.key)._tpl,
|
||||
spawnPoint.template.Items.find(item => item._id === itemDist.composedKey.key)._tpl,
|
||||
)
|
||||
)
|
||||
{
|
||||
@ -756,8 +755,8 @@ export class LocationGenerator
|
||||
for (const itemTpl of lootToForceSingleAmountOnMap)
|
||||
{
|
||||
// Get all spawn positions for item tpl in forced loot array
|
||||
const items = forcedSpawnPoints.filter((forcedSpawnPoint) =>
|
||||
forcedSpawnPoint.template.Items[0]._tpl === itemTpl
|
||||
const items = forcedSpawnPoints.filter(forcedSpawnPoint =>
|
||||
forcedSpawnPoint.template.Items[0]._tpl === itemTpl,
|
||||
);
|
||||
if (!items || items.length === 0)
|
||||
{
|
||||
@ -781,7 +780,7 @@ export class LocationGenerator
|
||||
// Choose 1 out of all found spawn positions for spawn id and add to loot array
|
||||
for (const spawnPointLocationId of spawnpointArray.draw(1, false))
|
||||
{
|
||||
const itemToAdd = items.find((item) => item.locationId === spawnPointLocationId);
|
||||
const itemToAdd = items.find(item => item.locationId === spawnPointLocationId);
|
||||
const lootItem = itemToAdd.template;
|
||||
lootItem.Root = this.objectId.generate();
|
||||
lootItem.Items[0]._id = lootItem.Root;
|
||||
@ -817,8 +816,8 @@ export class LocationGenerator
|
||||
locationTemplateToAdd.Items[0]._id = locationTemplateToAdd.Root;
|
||||
|
||||
// Push forced location into array as long as it doesnt exist already
|
||||
const existingLocation = lootLocationTemplates.find((spawnPoint) =>
|
||||
spawnPoint.Id === locationTemplateToAdd.Id
|
||||
const existingLocation = lootLocationTemplates.find(spawnPoint =>
|
||||
spawnPoint.Id === locationTemplateToAdd.Id,
|
||||
);
|
||||
if (!existingLocation)
|
||||
{
|
||||
@ -846,7 +845,7 @@ export class LocationGenerator
|
||||
staticAmmoDist: Record<string, IStaticAmmoDetails[]>,
|
||||
): IContainerItem
|
||||
{
|
||||
const chosenItem = spawnPoint.template.Items.find((item) => item._id === chosenComposedKey);
|
||||
const chosenItem = spawnPoint.template.Items.find(item => item._id === chosenComposedKey);
|
||||
const chosenTpl = chosenItem._tpl;
|
||||
const itemTemplate = this.itemHelper.getItem(chosenTpl)[1];
|
||||
|
||||
@ -946,10 +945,10 @@ export class LocationGenerator
|
||||
{
|
||||
if (this.itemHelper.isOfBaseclass(chosenTpl, BaseClasses.WEAPON))
|
||||
{
|
||||
return items.find((v) => v._tpl === chosenTpl && v.parentId === undefined);
|
||||
return items.find(v => v._tpl === chosenTpl && v.parentId === undefined);
|
||||
}
|
||||
|
||||
return items.find((item) => item._tpl === chosenTpl);
|
||||
return items.find(item => item._tpl === chosenTpl);
|
||||
}
|
||||
|
||||
// TODO: rewrite, BIG yikes
|
||||
@ -1053,7 +1052,7 @@ export class LocationGenerator
|
||||
// it can handle revolver ammo (it's not restructured to be used here yet.)
|
||||
// General: Make a WeaponController for Ragfair preset stuff and the generating weapons and ammo stuff from
|
||||
// BotGenerator
|
||||
const magazine = items.filter((item) => item.slotId === "mod_magazine")[0];
|
||||
const magazine = items.filter(item => item.slotId === "mod_magazine")[0];
|
||||
// some weapon presets come without magazine; only fill the mag if it exists
|
||||
if (magazine)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { InventoryHelper } from "@spt-aki/helpers/InventoryHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
@ -21,7 +20,7 @@ import { HashUtil } from "@spt-aki/utils/HashUtil";
|
||||
import { JsonUtil } from "@spt-aki/utils/JsonUtil";
|
||||
import { RandomUtil } from "@spt-aki/utils/RandomUtil";
|
||||
|
||||
type ItemLimit = { current: number; max: number; };
|
||||
type ItemLimit = { current: number, max: number };
|
||||
|
||||
@injectable()
|
||||
export class LootGenerator
|
||||
@ -74,8 +73,8 @@ export class LootGenerator
|
||||
if (desiredWeaponCrateCount > 0)
|
||||
{
|
||||
// Get list of all sealed containers from db
|
||||
const sealedWeaponContainerPool = Object.values(tables.templates.items).filter((x) =>
|
||||
x._name.includes("event_container_airdrop")
|
||||
const sealedWeaponContainerPool = Object.values(tables.templates.items).filter(x =>
|
||||
x._name.includes("event_container_airdrop"),
|
||||
);
|
||||
|
||||
for (let index = 0; index < desiredWeaponCrateCount; index++)
|
||||
@ -92,11 +91,11 @@ export class LootGenerator
|
||||
}
|
||||
|
||||
// Get items from items.json that have a type of item + not in global blacklist + basetype is in whitelist
|
||||
const items = Object.entries(tables.templates.items).filter((x) =>
|
||||
const items = Object.entries(tables.templates.items).filter(x =>
|
||||
!itemBlacklist.has(x[1]._id)
|
||||
&& x[1]._type.toLowerCase() === "item"
|
||||
&& !x[1]._props.QuestItem
|
||||
&& options.itemTypeWhitelist.includes(x[1]._parent)
|
||||
&& options.itemTypeWhitelist.includes(x[1]._parent),
|
||||
);
|
||||
|
||||
if (items.length > 0)
|
||||
@ -122,8 +121,8 @@ export class LootGenerator
|
||||
);
|
||||
if (randomisedWeaponPresetCount > 0)
|
||||
{
|
||||
const weaponDefaultPresets = globalDefaultPresets.filter((preset) =>
|
||||
this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON)
|
||||
const weaponDefaultPresets = globalDefaultPresets.filter(preset =>
|
||||
this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON),
|
||||
);
|
||||
|
||||
if (weaponDefaultPresets.length > 0)
|
||||
@ -153,11 +152,11 @@ export class LootGenerator
|
||||
);
|
||||
if (randomisedArmorPresetCount > 0)
|
||||
{
|
||||
const armorDefaultPresets = globalDefaultPresets.filter((preset) =>
|
||||
this.itemHelper.armorItemCanHoldMods(preset._encyclopedia)
|
||||
const armorDefaultPresets = globalDefaultPresets.filter(preset =>
|
||||
this.itemHelper.armorItemCanHoldMods(preset._encyclopedia),
|
||||
);
|
||||
const levelFilteredArmorPresets = armorDefaultPresets.filter((armor) =>
|
||||
this.armorIsDesiredProtectionLevel(armor, options)
|
||||
const levelFilteredArmorPresets = armorDefaultPresets.filter(armor =>
|
||||
this.armorIsDesiredProtectionLevel(armor, options),
|
||||
);
|
||||
|
||||
// Add some armors to rewards
|
||||
@ -192,21 +191,21 @@ export class LootGenerator
|
||||
*/
|
||||
protected armorIsDesiredProtectionLevel(armor: IPreset, options: LootRequest): boolean
|
||||
{
|
||||
const frontPlate = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "front_plate");
|
||||
const frontPlate = armor._items.find(mod => mod?.slotId?.toLowerCase() === "front_plate");
|
||||
if (frontPlate)
|
||||
{
|
||||
const plateDb = this.itemHelper.getItem(frontPlate._tpl);
|
||||
return options.armorLevelWhitelist.includes(Number.parseInt(plateDb[1]._props.armorClass as any));
|
||||
}
|
||||
|
||||
const helmetTop = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "helmet_top");
|
||||
const helmetTop = armor._items.find(mod => mod?.slotId?.toLowerCase() === "helmet_top");
|
||||
if (helmetTop)
|
||||
{
|
||||
const plateDb = this.itemHelper.getItem(helmetTop._tpl);
|
||||
return options.armorLevelWhitelist.includes(Number.parseInt(plateDb[1]._props.armorClass as any));
|
||||
}
|
||||
|
||||
const softArmorFront = armor._items.find((mod) => mod?.slotId?.toLowerCase() === "soft_armor_front");
|
||||
const softArmorFront = armor._items.find(mod => mod?.slotId?.toLowerCase() === "soft_armor_front");
|
||||
if (softArmorFront)
|
||||
{
|
||||
const plateDb = this.itemHelper.getItem(softArmorFront._tpl);
|
||||
@ -242,7 +241,7 @@ export class LootGenerator
|
||||
*/
|
||||
protected findAndAddRandomItemToLoot(
|
||||
items: [string, ITemplateItem][],
|
||||
itemTypeCounts: Record<string, { current: number; max: number; }>,
|
||||
itemTypeCounts: Record<string, { current: number, max: number }>,
|
||||
options: LootRequest,
|
||||
result: LootItem[],
|
||||
): boolean
|
||||
@ -317,7 +316,7 @@ export class LootGenerator
|
||||
*/
|
||||
protected findAndAddRandomPresetToLoot(
|
||||
presetPool: IPreset[],
|
||||
itemTypeCounts: Record<string, { current: number; max: number; }>,
|
||||
itemTypeCounts: Record<string, { current: number, max: number }>,
|
||||
itemBlacklist: string[],
|
||||
result: LootItem[],
|
||||
): boolean
|
||||
@ -408,7 +407,7 @@ export class LootGenerator
|
||||
}
|
||||
|
||||
// Get weapon preset - default or choose a random one from globals.json preset pool
|
||||
let chosenWeaponPreset = (containerSettings.defaultPresetsOnly)
|
||||
let chosenWeaponPreset = containerSettings.defaultPresetsOnly
|
||||
? this.presetHelper.getDefaultPreset(chosenWeaponTpl)
|
||||
: this.randomUtil.getArrayValue(this.presetHelper.getPresets(chosenWeaponTpl));
|
||||
|
||||
@ -473,7 +472,7 @@ export class LootGenerator
|
||||
|
||||
// Need to find boxes that matches weapons caliber
|
||||
const weaponCaliber = weaponDetailsDb._props.ammoCaliber;
|
||||
const ammoBoxesMatchingCaliber = ammoBoxesDetails.filter((x) => x._props.ammoCaliber === weaponCaliber);
|
||||
const ammoBoxesMatchingCaliber = ammoBoxesDetails.filter(x => x._props.ammoCaliber === weaponCaliber);
|
||||
if (ammoBoxesMatchingCaliber.length === 0)
|
||||
{
|
||||
this.logger.debug(`No ammo box with caliber ${weaponCaliber} found, skipping`);
|
||||
@ -493,12 +492,12 @@ export class LootGenerator
|
||||
}
|
||||
|
||||
// Get all items of the desired type + not quest items + not globally blacklisted
|
||||
const rewardItemPool = Object.values(this.databaseServer.getTables().templates.items).filter((x) =>
|
||||
const rewardItemPool = Object.values(this.databaseServer.getTables().templates.items).filter(x =>
|
||||
x._parent === rewardTypeId
|
||||
&& x._type.toLowerCase() === "item"
|
||||
&& !this.itemFilterService.isItemBlacklisted(x._id)
|
||||
&& (!(containerSettings.allowBossItems || this.itemFilterService.isBossItem(x._id)))
|
||||
&& !x._props.QuestItem
|
||||
&& !(containerSettings.allowBossItems || this.itemFilterService.isBossItem(x._id))
|
||||
&& !x._props.QuestItem,
|
||||
);
|
||||
|
||||
if (rewardItemPool.length === 0)
|
||||
@ -547,8 +546,8 @@ export class LootGenerator
|
||||
}
|
||||
|
||||
// Get items that fulfil reward type criteria from items that fit on gun
|
||||
const relatedItems = linkedItemsToWeapon.filter((x) =>
|
||||
x._parent === rewardTypeId && !this.itemFilterService.isItemBlacklisted(x._id)
|
||||
const relatedItems = linkedItemsToWeapon.filter(x =>
|
||||
x._parent === rewardTypeId && !this.itemFilterService.isItemBlacklisted(x._id),
|
||||
);
|
||||
if (!relatedItems || relatedItems.length === 0)
|
||||
{
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||
import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem";
|
||||
@ -48,8 +47,8 @@ export class PMCLootGenerator
|
||||
if (Object.keys(this.pocketLootPool).length === 0)
|
||||
{
|
||||
const items = this.databaseServer.getTables().templates.items;
|
||||
const pmcPriceOverrides =
|
||||
this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
const pmcPriceOverrides
|
||||
= this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
.Pockets;
|
||||
|
||||
const allowedItemTypes = this.pmcConfig.pocketLoot.whitelist;
|
||||
@ -59,13 +58,13 @@ export class PMCLootGenerator
|
||||
// Blacklist inactive seasonal items
|
||||
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
|
||||
|
||||
const itemsToAdd = Object.values(items).filter((item) =>
|
||||
const itemsToAdd = Object.values(items).filter(item =>
|
||||
allowedItemTypes.includes(item._parent)
|
||||
&& this.itemHelper.isValidItem(item._id)
|
||||
&& !pmcItemBlacklist.includes(item._id)
|
||||
&& !itemBlacklist.includes(item._id)
|
||||
&& item._props.Width === 1
|
||||
&& item._props.Height === 1
|
||||
&& item._props.Height === 1,
|
||||
);
|
||||
|
||||
for (const itemToAdd of itemsToAdd)
|
||||
@ -88,7 +87,7 @@ export class PMCLootGenerator
|
||||
{
|
||||
// Invert price so cheapest has a larger weight
|
||||
// Times by highest price so most expensive item has weight of 1
|
||||
this.pocketLootPool[key] = Math.round((1 / this.pocketLootPool[key]) * highestPrice);
|
||||
this.pocketLootPool[key] = Math.round(1 / this.pocketLootPool[key] * highestPrice);
|
||||
}
|
||||
|
||||
this.weightedRandomHelper.reduceWeightValues(this.pocketLootPool);
|
||||
@ -107,8 +106,8 @@ export class PMCLootGenerator
|
||||
if (Object.keys(this.vestLootPool).length === 0)
|
||||
{
|
||||
const items = this.databaseServer.getTables().templates.items;
|
||||
const pmcPriceOverrides =
|
||||
this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
const pmcPriceOverrides
|
||||
= this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
.TacticalVest;
|
||||
|
||||
const allowedItemTypes = this.pmcConfig.vestLoot.whitelist;
|
||||
@ -118,12 +117,12 @@ export class PMCLootGenerator
|
||||
// Blacklist seasonal items
|
||||
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
|
||||
|
||||
const itemsToAdd = Object.values(items).filter((item) =>
|
||||
const itemsToAdd = Object.values(items).filter(item =>
|
||||
allowedItemTypes.includes(item._parent)
|
||||
&& this.itemHelper.isValidItem(item._id)
|
||||
&& !pmcItemBlacklist.includes(item._id)
|
||||
&& !itemBlacklist.includes(item._id)
|
||||
&& this.itemFitsInto2By2Slot(item)
|
||||
&& this.itemFitsInto2By2Slot(item),
|
||||
);
|
||||
|
||||
for (const itemToAdd of itemsToAdd)
|
||||
@ -146,7 +145,7 @@ export class PMCLootGenerator
|
||||
{
|
||||
// Invert price so cheapest has a larger weight
|
||||
// Times by highest price so most expensive item has weight of 1
|
||||
this.vestLootPool[key] = Math.round((1 / this.vestLootPool[key]) * highestPrice);
|
||||
this.vestLootPool[key] = Math.round(1 / this.vestLootPool[key] * highestPrice);
|
||||
}
|
||||
|
||||
this.weightedRandomHelper.reduceWeightValues(this.vestLootPool);
|
||||
@ -176,8 +175,8 @@ export class PMCLootGenerator
|
||||
if (Object.keys(this.backpackLootPool).length === 0)
|
||||
{
|
||||
const items = this.databaseServer.getTables().templates.items;
|
||||
const pmcPriceOverrides =
|
||||
this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
const pmcPriceOverrides
|
||||
= this.databaseServer.getTables().bots.types[botRole === "sptBear" ? "bear" : "usec"].inventory.items
|
||||
.Backpack;
|
||||
|
||||
const allowedItemTypes = this.pmcConfig.backpackLoot.whitelist;
|
||||
@ -187,11 +186,11 @@ export class PMCLootGenerator
|
||||
// Blacklist seasonal items
|
||||
itemBlacklist.push(...this.seasonalEventService.getInactiveSeasonalEventItems());
|
||||
|
||||
const itemsToAdd = Object.values(items).filter((item) =>
|
||||
const itemsToAdd = Object.values(items).filter(item =>
|
||||
allowedItemTypes.includes(item._parent)
|
||||
&& this.itemHelper.isValidItem(item._id)
|
||||
&& !pmcItemBlacklist.includes(item._id)
|
||||
&& !itemBlacklist.includes(item._id)
|
||||
&& !itemBlacklist.includes(item._id),
|
||||
);
|
||||
|
||||
for (const itemToAdd of itemsToAdd)
|
||||
@ -214,7 +213,7 @@ export class PMCLootGenerator
|
||||
{
|
||||
// Invert price so cheapest has a larger weight
|
||||
// Times by highest price so most expensive item has weight of 1
|
||||
this.backpackLootPool[key] = Math.round((1 / this.backpackLootPool[key]) * highestPrice);
|
||||
this.backpackLootPool[key] = Math.round(1 / this.backpackLootPool[key] * highestPrice);
|
||||
}
|
||||
|
||||
this.weightedRandomHelper.reduceWeightValues(this.backpackLootPool);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { BotGenerator } from "@spt-aki/generators/BotGenerator";
|
||||
import { BotGeneratorHelper } from "@spt-aki/helpers/BotGeneratorHelper";
|
||||
import { BotHelper } from "@spt-aki/helpers/BotHelper";
|
||||
@ -310,7 +309,7 @@ export class PlayerScavGenerator
|
||||
protected getScavLevel(scavProfile: IPmcData): number
|
||||
{
|
||||
// Info can be null on initial account creation
|
||||
if (!(scavProfile.Info?.Level))
|
||||
if (!scavProfile.Info?.Level)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -321,7 +320,7 @@ export class PlayerScavGenerator
|
||||
protected getScavExperience(scavProfile: IPmcData): number
|
||||
{
|
||||
// Info can be null on initial account creation
|
||||
if (!(scavProfile.Info?.Experience))
|
||||
if (!scavProfile.Info?.Experience)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -364,7 +363,7 @@ export class PlayerScavGenerator
|
||||
scavLockDuration = 10;
|
||||
}
|
||||
|
||||
scavData.Info.SavageLockTime = (Date.now() / 1000) + scavLockDuration;
|
||||
scavData.Info.SavageLockTime = Date.now() / 1000 + scavLockDuration;
|
||||
|
||||
return scavData;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { IPreset } from "@spt-aki/models/eft/common/IGlobals";
|
||||
@ -75,7 +74,7 @@ export class RagfairAssortGenerator
|
||||
const results: Item[][] = [];
|
||||
|
||||
/** Get cloned items from db */
|
||||
const dbItemsClone = this.itemHelper.getItems().filter((item) => item._type !== "Node");
|
||||
const dbItemsClone = this.itemHelper.getItems().filter(item => item._type !== "Node");
|
||||
|
||||
/** Store processed preset tpls so we dont add them when procesing non-preset items */
|
||||
const processedArmorItems: string[] = [];
|
||||
@ -136,7 +135,7 @@ export class RagfairAssortGenerator
|
||||
*/
|
||||
protected getPresetsToAdd(): IPreset[]
|
||||
{
|
||||
return (this.ragfairConfig.dynamic.showDefaultPresetsOnly)
|
||||
return this.ragfairConfig.dynamic.showDefaultPresetsOnly
|
||||
? Object.values(this.presetHelper.getDefaultPresets())
|
||||
: this.presetHelper.getAllPresets();
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RagfairAssortGenerator } from "@spt-aki/generators/RagfairAssortGenerator";
|
||||
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
@ -37,7 +36,7 @@ import { TimeUtil } from "@spt-aki/utils/TimeUtil";
|
||||
export class RagfairOfferGenerator
|
||||
{
|
||||
protected ragfairConfig: IRagfairConfig;
|
||||
protected allowedFleaPriceItemsForBarter: { tpl: string; price: number; }[];
|
||||
protected allowedFleaPriceItemsForBarter: { tpl: string, price: number }[];
|
||||
|
||||
/** Internal counter to ensure each offer created has a unique value for its intId property */
|
||||
protected offerCounter = 0;
|
||||
@ -136,7 +135,7 @@ export class RagfairOfferGenerator
|
||||
}
|
||||
}
|
||||
|
||||
const itemCount = items.filter((x) => x.slotId === "hideout").length;
|
||||
const itemCount = items.filter(x => x.slotId === "hideout").length;
|
||||
const roublePrice = Math.round(this.convertOfferRequirementsIntoRoubles(offerRequirements));
|
||||
|
||||
const offer: IRagfairOffer = {
|
||||
@ -144,7 +143,7 @@ export class RagfairOfferGenerator
|
||||
intId: this.offerCounter,
|
||||
user: {
|
||||
id: this.getTraderId(userID),
|
||||
memberType: (userID === "ragfair")
|
||||
memberType: userID === "ragfair"
|
||||
? MemberCategory.DEFAULT
|
||||
: this.ragfairServerHelper.getMemberType(userID),
|
||||
nickname: this.ragfairServerHelper.getNickname(userID),
|
||||
@ -297,8 +296,8 @@ export class RagfairOfferGenerator
|
||||
if (this.ragfairServerHelper.isPlayer(userID))
|
||||
{
|
||||
// Player offer = current time + offerDurationTimeInHour;
|
||||
const offerDurationTimeHours =
|
||||
this.databaseServer.getTables().globals.config.RagFair.offerDurationTimeInHour;
|
||||
const offerDurationTimeHours
|
||||
= this.databaseServer.getTables().globals.config.RagFair.offerDurationTimeInHour;
|
||||
return this.timeUtil.getTimestamp() + Math.round(offerDurationTimeHours * TimeUtil.ONE_HOUR_AS_SECONDS);
|
||||
}
|
||||
|
||||
@ -311,10 +310,10 @@ export class RagfairOfferGenerator
|
||||
// Generated fake-player offer
|
||||
return Math.round(
|
||||
time
|
||||
+ this.randomUtil.getInt(
|
||||
this.ragfairConfig.dynamic.endTimeSeconds.min,
|
||||
this.ragfairConfig.dynamic.endTimeSeconds.max,
|
||||
),
|
||||
+ this.randomUtil.getInt(
|
||||
this.ragfairConfig.dynamic.endTimeSeconds.min,
|
||||
this.ragfairConfig.dynamic.endTimeSeconds.max,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -411,8 +410,8 @@ export class RagfairOfferGenerator
|
||||
return false;
|
||||
}
|
||||
|
||||
const plateSlots = presetWithChildren.filter((item) =>
|
||||
this.itemHelper.getRemovablePlateSlotIds().includes(item.slotId?.toLowerCase())
|
||||
const plateSlots = presetWithChildren.filter(item =>
|
||||
this.itemHelper.getRemovablePlateSlotIds().includes(item.slotId?.toLowerCase()),
|
||||
);
|
||||
if (plateSlots.length === 0)
|
||||
{
|
||||
@ -461,12 +460,12 @@ export class RagfairOfferGenerator
|
||||
|
||||
const isBarterOffer = this.randomUtil.getChance100(this.ragfairConfig.dynamic.barter.chancePercent);
|
||||
const isPackOffer = this.randomUtil.getChance100(this.ragfairConfig.dynamic.pack.chancePercent)
|
||||
&& !isBarterOffer
|
||||
&& itemWithChildren.length === 1
|
||||
&& this.itemHelper.isOfBaseclasses(
|
||||
itemWithChildren[0]._tpl,
|
||||
this.ragfairConfig.dynamic.pack.itemTypeWhitelist,
|
||||
);
|
||||
&& !isBarterOffer
|
||||
&& itemWithChildren.length === 1
|
||||
&& this.itemHelper.isOfBaseclasses(
|
||||
itemWithChildren[0]._tpl,
|
||||
this.ragfairConfig.dynamic.pack.itemTypeWhitelist,
|
||||
);
|
||||
|
||||
const randomUserId = this.hashUtil.generate();
|
||||
|
||||
@ -478,8 +477,8 @@ export class RagfairOfferGenerator
|
||||
const shouldRemovePlates = this.randomUtil.getChance100(armorConfig.removeRemovablePlateChance);
|
||||
if (shouldRemovePlates && this.itemHelper.armorItemHasRemovablePlateSlots(itemWithChildren[0]._tpl))
|
||||
{
|
||||
const offerItemPlatesToRemove = itemWithChildren.filter((item) =>
|
||||
armorConfig.plateSlotIdToRemovePool.includes(item.slotId?.toLowerCase())
|
||||
const offerItemPlatesToRemove = itemWithChildren.filter(item =>
|
||||
armorConfig.plateSlotIdToRemovePool.includes(item.slotId?.toLowerCase()),
|
||||
);
|
||||
|
||||
for (const plateItem of offerItemPlatesToRemove)
|
||||
@ -684,8 +683,8 @@ export class RagfairOfferGenerator
|
||||
this.randomiseArmorDurabilityValues(itemWithMods, currentMultiplier, maxMultiplier);
|
||||
|
||||
// Add hits to visor
|
||||
const visorMod = itemWithMods.find((item) =>
|
||||
item.parentId === BaseClasses.ARMORED_EQUIPMENT && item.slotId === "mod_equipment_000"
|
||||
const visorMod = itemWithMods.find(item =>
|
||||
item.parentId === BaseClasses.ARMORED_EQUIPMENT && item.slotId === "mod_equipment_000",
|
||||
);
|
||||
if (this.randomUtil.getChance100(25) && visorMod)
|
||||
{
|
||||
@ -717,7 +716,7 @@ export class RagfairOfferGenerator
|
||||
{
|
||||
// randomize key uses
|
||||
rootItem.upd.Key.NumberOfUsages = Math.round(itemDetails._props.MaximumNumberOfUsage * (1 - maxMultiplier))
|
||||
|| 0;
|
||||
|| 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -789,12 +788,12 @@ export class RagfairOfferGenerator
|
||||
for (const armorItem of armorWithMods)
|
||||
{
|
||||
const itemDbDetails = this.itemHelper.getItem(armorItem._tpl)[1];
|
||||
if ((Number.parseInt(<string>itemDbDetails._props.armorClass)) > 1)
|
||||
if (Number.parseInt(<string>itemDbDetails._props.armorClass) > 1)
|
||||
{
|
||||
this.itemHelper.addUpdObjectToItem(armorItem);
|
||||
|
||||
const lowestMaxDurability = this.randomUtil.getFloat(maxMultiplier, 1)
|
||||
* itemDbDetails._props.MaxDurability;
|
||||
* itemDbDetails._props.MaxDurability;
|
||||
const chosenMaxDurability = Math.round(
|
||||
this.randomUtil.getFloat(lowestMaxDurability, itemDbDetails._props.MaxDurability),
|
||||
);
|
||||
@ -888,9 +887,9 @@ export class RagfairOfferGenerator
|
||||
const fleaPrices = this.getFleaPricesAsArray();
|
||||
|
||||
// Filter possible barters to items that match the price range + not itself
|
||||
const filtered = fleaPrices.filter((x) =>
|
||||
const filtered = fleaPrices.filter(x =>
|
||||
x.price >= desiredItemCost - offerCostVariance && x.price <= desiredItemCost + offerCostVariance
|
||||
&& x.tpl !== offerItems[0]._tpl
|
||||
&& x.tpl !== offerItems[0]._tpl,
|
||||
);
|
||||
|
||||
// No items on flea have a matching price, fall back to currency
|
||||
@ -909,7 +908,7 @@ export class RagfairOfferGenerator
|
||||
* Get an array of flea prices + item tpl, cached in generator class inside `allowedFleaPriceItemsForBarter`
|
||||
* @returns array with tpl/price values
|
||||
*/
|
||||
protected getFleaPricesAsArray(): { tpl: string; price: number; }[]
|
||||
protected getFleaPricesAsArray(): { tpl: string, price: number }[]
|
||||
{
|
||||
// Generate if needed
|
||||
if (!this.allowedFleaPriceItemsForBarter)
|
||||
@ -918,10 +917,10 @@ export class RagfairOfferGenerator
|
||||
const fleaArray = Object.entries(fleaPrices).map(([tpl, price]) => ({ tpl: tpl, price: price }));
|
||||
|
||||
// Only get item prices for items that also exist in items.json
|
||||
const filteredItems = fleaArray.filter((x) => this.itemHelper.getItem(x.tpl)[0]);
|
||||
const filteredItems = fleaArray.filter(x => this.itemHelper.getItem(x.tpl)[0]);
|
||||
|
||||
this.allowedFleaPriceItemsForBarter = filteredItems.filter((x) =>
|
||||
!this.itemHelper.isOfBaseclasses(x.tpl, this.ragfairConfig.dynamic.barter.itemTypeBlacklist)
|
||||
this.allowedFleaPriceItemsForBarter = filteredItems.filter(x =>
|
||||
!this.itemHelper.isOfBaseclasses(x.tpl, this.ragfairConfig.dynamic.barter.itemTypeBlacklist),
|
||||
);
|
||||
}
|
||||
|
||||
@ -943,7 +942,7 @@ export class RagfairOfferGenerator
|
||||
{
|
||||
const currency = this.ragfairServerHelper.getDynamicOfferCurrency();
|
||||
const price = this.ragfairPriceService.getDynamicOfferPriceForOffer(offerWithChildren, currency, isPackOffer)
|
||||
* multipler;
|
||||
* multipler;
|
||||
|
||||
return [{ count: price, _tpl: currency }];
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { RepeatableQuestRewardGenerator } from "@spt-aki/generators/RepeatableQuestRewardGenerator";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { RepeatableQuestHelper } from "@spt-aki/helpers/RepeatableQuestHelper";
|
||||
@ -42,7 +41,7 @@ export class RepeatableQuestGenerator
|
||||
@inject("ObjectId") protected objectId: ObjectId,
|
||||
@inject("RepeatableQuestHelper") protected repeatableQuestHelper: RepeatableQuestHelper,
|
||||
@inject("RepeatableQuestRewardGenerator") protected repeatableQuestRewardGenerator:
|
||||
RepeatableQuestRewardGenerator,
|
||||
RepeatableQuestRewardGenerator,
|
||||
@inject("ConfigServer") protected configServer: ConfigServer,
|
||||
)
|
||||
{
|
||||
@ -68,11 +67,11 @@ export class RepeatableQuestGenerator
|
||||
const questType = this.randomUtil.drawRandomFromList<string>(questTypePool.types)[0];
|
||||
|
||||
// get traders from whitelist and filter by quest type availability
|
||||
let traders = repeatableConfig.traderWhitelist.filter((x) => x.questTypes.includes(questType)).map((x) =>
|
||||
x.traderId
|
||||
let traders = repeatableConfig.traderWhitelist.filter(x => x.questTypes.includes(questType)).map(x =>
|
||||
x.traderId,
|
||||
);
|
||||
// filter out locked traders
|
||||
traders = traders.filter((x) => pmcTraderInfo[x].unlocked);
|
||||
traders = traders.filter(x => pmcTraderInfo[x].unlocked);
|
||||
const traderId = this.randomUtil.drawRandomFromList(traders)[0];
|
||||
|
||||
switch (questType)
|
||||
@ -159,15 +158,15 @@ export class RepeatableQuestGenerator
|
||||
return Math.sqrt(Math.sqrt(target) + bodyPart + dist + weaponRequirement) * kill;
|
||||
}
|
||||
|
||||
targetsConfig = targetsConfig.filter((x) =>
|
||||
Object.keys(questTypePool.pool.Elimination.targets).includes(x.key)
|
||||
targetsConfig = targetsConfig.filter(x =>
|
||||
Object.keys(questTypePool.pool.Elimination.targets).includes(x.key),
|
||||
);
|
||||
if (targetsConfig.length === 0 || targetsConfig.every((x) => x.data.isBoss))
|
||||
if (targetsConfig.length === 0 || targetsConfig.every(x => x.data.isBoss))
|
||||
{
|
||||
// There are no more targets left for elimination; delete it as a possible quest type
|
||||
// also if only bosses are left we need to leave otherwise it's a guaranteed boss elimination
|
||||
// -> then it would not be a quest with low probability anymore
|
||||
questTypePool.types = questTypePool.types.filter((t) => t !== "Elimination");
|
||||
questTypePool.types = questTypePool.types.filter(t => t !== "Elimination");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -189,12 +188,12 @@ export class RepeatableQuestGenerator
|
||||
}
|
||||
else
|
||||
{
|
||||
locations = locations.filter((l) => l !== "any");
|
||||
locations = locations.filter(l => l !== "any");
|
||||
if (locations.length > 0)
|
||||
{
|
||||
locationKey = this.randomUtil.drawRandomFromList<string>(locations)[0];
|
||||
questTypePool.pool.Elimination.targets[targetKey].locations = locations.filter((l) =>
|
||||
l !== locationKey
|
||||
questTypePool.pool.Elimination.targets[targetKey].locations = locations.filter(l =>
|
||||
l !== locationKey,
|
||||
);
|
||||
if (questTypePool.pool.Elimination.targets[targetKey].locations.length === 0)
|
||||
{
|
||||
@ -239,18 +238,18 @@ export class RepeatableQuestGenerator
|
||||
if (targetsConfig.data(targetKey).isBoss)
|
||||
{
|
||||
// Get all boss spawn information
|
||||
const bossSpawns = Object.values(this.databaseServer.getTables().locations).filter((x) =>
|
||||
"base" in x && "Id" in x.base
|
||||
).map((x) => ({ Id: x.base.Id, BossSpawn: x.base.BossLocationSpawn }));
|
||||
const bossSpawns = Object.values(this.databaseServer.getTables().locations).filter(x =>
|
||||
"base" in x && "Id" in x.base,
|
||||
).map(x => ({ Id: x.base.Id, BossSpawn: x.base.BossLocationSpawn }));
|
||||
// filter for the current boss to spawn on map
|
||||
const thisBossSpawns = bossSpawns.map((x) => ({
|
||||
const thisBossSpawns = bossSpawns.map(x => ({
|
||||
Id: x.Id,
|
||||
BossSpawn: x.BossSpawn.filter((e) => e.BossName === targetKey),
|
||||
})).filter((x) => x.BossSpawn.length > 0);
|
||||
BossSpawn: x.BossSpawn.filter(e => e.BossName === targetKey),
|
||||
})).filter(x => x.BossSpawn.length > 0);
|
||||
// remove blacklisted locations
|
||||
const allowedSpawns = thisBossSpawns.filter((x) => !eliminationConfig.distLocationBlacklist.includes(x.Id));
|
||||
const allowedSpawns = thisBossSpawns.filter(x => !eliminationConfig.distLocationBlacklist.includes(x.Id));
|
||||
// if the boss spawns on nom-blacklisted locations and the current location is allowed we can generate a distance kill requirement
|
||||
isDistanceRequirementAllowed = isDistanceRequirementAllowed && (allowedSpawns.length > 0);
|
||||
isDistanceRequirementAllowed = isDistanceRequirementAllowed && allowedSpawns.length > 0;
|
||||
}
|
||||
|
||||
if (eliminationConfig.distProb > Math.random() && isDistanceRequirementAllowed)
|
||||
@ -258,7 +257,7 @@ export class RepeatableQuestGenerator
|
||||
// Random distance with lower values more likely; simple distribution for starters...
|
||||
distance = Math.floor(
|
||||
Math.abs(Math.random() - Math.random()) * (1 + eliminationConfig.maxDist - eliminationConfig.minDist)
|
||||
+ eliminationConfig.minDist,
|
||||
+ eliminationConfig.minDist,
|
||||
);
|
||||
distance = Math.ceil(distance / 5) * 5;
|
||||
distanceDifficulty = maxDistDifficulty * distance / eliminationConfig.maxDist;
|
||||
@ -270,14 +269,14 @@ export class RepeatableQuestGenerator
|
||||
// Filter out close range weapons from far distance requirement
|
||||
if (distance > 50)
|
||||
{
|
||||
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) =>
|
||||
["Shotgun", "Pistol"].includes(category.key)
|
||||
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter(category =>
|
||||
["Shotgun", "Pistol"].includes(category.key),
|
||||
);
|
||||
}
|
||||
else if (distance < 20)
|
||||
{ // Filter out far range weapons from close distance requirement
|
||||
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter((category) =>
|
||||
["MarksmanRifle", "DMR"].includes(category.key)
|
||||
weaponCategoryRequirementConfig = weaponCategoryRequirementConfig.filter(category =>
|
||||
["MarksmanRifle", "DMR"].includes(category.key),
|
||||
);
|
||||
}
|
||||
|
||||
@ -310,7 +309,7 @@ export class RepeatableQuestGenerator
|
||||
bodyPartDifficulty / maxBodyPartsDifficulty,
|
||||
distanceDifficulty / maxDistDifficulty,
|
||||
killDifficulty / maxKillDifficulty,
|
||||
(allowedWeaponsCategory || allowedWeapon) ? 1 : 0,
|
||||
allowedWeaponsCategory || allowedWeapon ? 1 : 0,
|
||||
);
|
||||
|
||||
// Aforementioned issue makes it a bit crazy since now all easier quests give significantly lower rewards than Completion / Exploration
|
||||
@ -498,27 +497,27 @@ export class RepeatableQuestGenerator
|
||||
this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig) * this.randomUtil.getFloat(0.5, 1),
|
||||
);
|
||||
roublesBudget = Math.max(roublesBudget, 5000);
|
||||
let itemSelection = possibleItemsToRetrievePool.filter((x) =>
|
||||
this.itemHelper.getItemPrice(x[0]) < roublesBudget
|
||||
let itemSelection = possibleItemsToRetrievePool.filter(x =>
|
||||
this.itemHelper.getItemPrice(x[0]) < roublesBudget,
|
||||
);
|
||||
|
||||
// We also have the option to use whitelist and/or blacklist which is defined in repeatableQuests.json as
|
||||
// [{"minPlayerLevel": 1, "itemIds": ["id1",...]}, {"minPlayerLevel": 15, "itemIds": ["id3",...]}]
|
||||
if (repeatableConfig.questConfig.Completion.useWhitelist)
|
||||
{
|
||||
const itemWhitelist =
|
||||
this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsWhitelist;
|
||||
const itemWhitelist
|
||||
= this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsWhitelist;
|
||||
|
||||
// Filter and concatenate the arrays according to current player level
|
||||
const itemIdsWhitelisted = itemWhitelist.filter((p) => p.minPlayerLevel <= pmcLevel).reduce(
|
||||
const itemIdsWhitelisted = itemWhitelist.filter(p => p.minPlayerLevel <= pmcLevel).reduce(
|
||||
(a, p) => a.concat(p.itemIds),
|
||||
[],
|
||||
);
|
||||
itemSelection = itemSelection.filter((x) =>
|
||||
{
|
||||
// Whitelist can contain item tpls and item base type ids
|
||||
return (itemIdsWhitelisted.some((v) => this.itemHelper.isOfBaseclass(x[0], v))
|
||||
|| itemIdsWhitelisted.includes(x[0]));
|
||||
return itemIdsWhitelisted.some(v => this.itemHelper.isOfBaseclass(x[0], v))
|
||||
|| itemIdsWhitelisted.includes(x[0]);
|
||||
});
|
||||
// check if items are missing
|
||||
// const flatList = itemSelection.reduce((a, il) => a.concat(il[0]), []);
|
||||
@ -527,19 +526,19 @@ export class RepeatableQuestGenerator
|
||||
|
||||
if (repeatableConfig.questConfig.Completion.useBlacklist)
|
||||
{
|
||||
const itemBlacklist =
|
||||
this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsBlacklist;
|
||||
const itemBlacklist
|
||||
= this.databaseServer.getTables().templates.repeatableQuests.data.Completion.itemsBlacklist;
|
||||
|
||||
// we filter and concatenate the arrays according to current player level
|
||||
const itemIdsBlacklisted = itemBlacklist.filter((p) => p.minPlayerLevel <= pmcLevel).reduce(
|
||||
const itemIdsBlacklisted = itemBlacklist.filter(p => p.minPlayerLevel <= pmcLevel).reduce(
|
||||
(a, p) => a.concat(p.itemIds),
|
||||
[],
|
||||
);
|
||||
|
||||
itemSelection = itemSelection.filter((x) =>
|
||||
{
|
||||
return itemIdsBlacklisted.every((v) => !this.itemHelper.isOfBaseclass(x[0], v))
|
||||
|| !itemIdsBlacklisted.includes(x[0]);
|
||||
return itemIdsBlacklisted.every(v => !this.itemHelper.isOfBaseclass(x[0], v))
|
||||
|| !itemIdsBlacklisted.includes(x[0]);
|
||||
});
|
||||
}
|
||||
|
||||
@ -602,7 +601,7 @@ export class RepeatableQuestGenerator
|
||||
if (roublesBudget > 0)
|
||||
{
|
||||
// reduce the list possible items to fulfill the new budget constraint
|
||||
itemSelection = itemSelection.filter((x) => this.itemHelper.getItemPrice(x[0]) < roublesBudget);
|
||||
itemSelection = itemSelection.filter(x => this.itemHelper.getItemPrice(x[0]) < roublesBudget);
|
||||
if (itemSelection.length === 0)
|
||||
{
|
||||
break;
|
||||
@ -687,13 +686,13 @@ export class RepeatableQuestGenerator
|
||||
): IRepeatableQuest
|
||||
{
|
||||
const explorationConfig = repeatableConfig.questConfig.Exploration;
|
||||
const requiresSpecificExtract =
|
||||
Math.random() < repeatableConfig.questConfig.Exploration.specificExits.probability;
|
||||
const requiresSpecificExtract
|
||||
= Math.random() < repeatableConfig.questConfig.Exploration.specificExits.probability;
|
||||
|
||||
if (Object.keys(questTypePool.pool.Exploration.locations).length === 0)
|
||||
{
|
||||
// there are no more locations left for exploration; delete it as a possible quest type
|
||||
questTypePool.types = questTypePool.types.filter((t) => t !== "Exploration");
|
||||
questTypePool.types = questTypePool.types.filter(t => t !== "Exploration");
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -738,15 +737,13 @@ export class RepeatableQuestGenerator
|
||||
const mapExits = this.getLocationExitsForSide(locationKey, repeatableConfig.side);
|
||||
|
||||
// Only get exits that have a greater than 0% chance to spawn
|
||||
const exitPool = mapExits.filter((exit) => exit.Chance > 0);
|
||||
const exitPool = mapExits.filter(exit => exit.Chance > 0);
|
||||
|
||||
// Exclude exits with a requirement to leave (e.g. car extracts)
|
||||
const possibleExits = exitPool.filter((
|
||||
exit,
|
||||
) => (!("PassageRequirement" in exit)
|
||||
|| repeatableConfig.questConfig.Exploration.specificExits.passageRequirementWhitelist.includes(
|
||||
exit.PassageRequirement,
|
||||
))
|
||||
const possibleExits = exitPool.filter(exit => !("PassageRequirement" in exit)
|
||||
|| repeatableConfig.questConfig.Exploration.specificExits.passageRequirementWhitelist.includes(
|
||||
exit.PassageRequirement,
|
||||
),
|
||||
);
|
||||
|
||||
if (possibleExits.length === 0)
|
||||
@ -791,7 +788,7 @@ export class RepeatableQuestGenerator
|
||||
const mapExtracts = this.databaseServer.getTables().locations[locationKey.toLocaleLowerCase()]
|
||||
.allExtracts as Exit[];
|
||||
|
||||
return mapExtracts.filter((exit) => exit.Side === playerSide);
|
||||
return mapExtracts.filter(exit => exit.Side === playerSide);
|
||||
}
|
||||
|
||||
protected generatePickupQuest(
|
||||
@ -814,18 +811,18 @@ export class RepeatableQuestGenerator
|
||||
// const locationKey: string = this.randomUtil.drawRandomFromDict(questTypePool.pool.Pickup.locations)[0];
|
||||
// const locationTarget = questTypePool.pool.Pickup.locations[locationKey];
|
||||
|
||||
const findCondition = quest.conditions.AvailableForFinish.find((x) => x.conditionType === "FindItem");
|
||||
const findCondition = quest.conditions.AvailableForFinish.find(x => x.conditionType === "FindItem");
|
||||
findCondition.target = [itemTypeToFetchWithCount.itemType];
|
||||
findCondition.value = itemCountToFetch;
|
||||
|
||||
const counterCreatorCondition = quest.conditions.AvailableForFinish.find((x) =>
|
||||
x.conditionType === "CounterCreator"
|
||||
const counterCreatorCondition = quest.conditions.AvailableForFinish.find(x =>
|
||||
x.conditionType === "CounterCreator",
|
||||
);
|
||||
// const locationCondition = counterCreatorCondition._props.counter.conditions.find(x => x._parent === "Location");
|
||||
// (locationCondition._props as ILocationConditionProps).target = [...locationTarget];
|
||||
|
||||
const equipmentCondition = counterCreatorCondition.counter.conditions.find((x) =>
|
||||
x.conditionType === "Equipment"
|
||||
const equipmentCondition = counterCreatorCondition.counter.conditions.find(x =>
|
||||
x.conditionType === "Equipment",
|
||||
);
|
||||
equipmentCondition.equipmentInclusive = [[itemTypeToFetchWithCount.itemType]];
|
||||
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper";
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
@ -96,20 +95,20 @@ export class RepeatableQuestRewardGenerator
|
||||
// rewards are generated based on pmcLevel, difficulty and a random spread
|
||||
const rewardXP = Math.floor(
|
||||
effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, xpConfig)
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
);
|
||||
const rewardRoubles = Math.floor(
|
||||
effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, roublesConfig)
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
);
|
||||
const rewardNumItems = this.randomUtil.randInt(
|
||||
1,
|
||||
Math.round(this.mathUtil.interp1(pmcLevel, levelsConfig, itemsConfig)) + 1,
|
||||
);
|
||||
const rewardReputation =
|
||||
Math.round(
|
||||
const rewardReputation
|
||||
= Math.round(
|
||||
100 * effectiveDifficulty * this.mathUtil.interp1(pmcLevel, levelsConfig, reputationConfig)
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
* this.randomUtil.getFloat(1 - rewardSpreadConfig, 1 + rewardSpreadConfig),
|
||||
) / 100;
|
||||
const skillRewardChance = this.mathUtil.interp1(pmcLevel, levelsConfig, skillRewardChanceConfig);
|
||||
const skillPointReward = this.mathUtil.interp1(pmcLevel, levelsConfig, skillPointRewardConfig);
|
||||
@ -135,7 +134,7 @@ export class RepeatableQuestRewardGenerator
|
||||
this.addMoneyReward(traderId, rewards, rewardRoubles, rewardIndex);
|
||||
rewardIndex++;
|
||||
|
||||
const traderWhitelistDetails = repeatableConfig.traderWhitelist.find((x) => x.traderId === traderId);
|
||||
const traderWhitelistDetails = repeatableConfig.traderWhitelist.find(x => x.traderId === traderId);
|
||||
if (
|
||||
traderWhitelistDetails.rewardCanBeWeapon
|
||||
&& this.randomUtil.getChance100(traderWhitelistDetails.weaponRewardChancePercent)
|
||||
@ -151,7 +150,7 @@ export class RepeatableQuestRewardGenerator
|
||||
while (defaultPresetPool.hasValues())
|
||||
{
|
||||
const randomPreset = defaultPresetPool.getRandomValue();
|
||||
const tpls = randomPreset._items.map((item) => item._tpl);
|
||||
const tpls = randomPreset._items.map(item => item._tpl);
|
||||
const presetPrice = this.itemHelper.getItemAndChildrenPrice(tpls);
|
||||
if (presetPrice <= roublesBudget)
|
||||
{
|
||||
@ -309,13 +308,13 @@ export class RepeatableQuestRewardGenerator
|
||||
protected canIncreaseRewardItemStackSize(item: ITemplateItem, maxRoublePriceToStack: number): boolean
|
||||
{
|
||||
return this.presetHelper.getDefaultPresetOrItemPrice(item._id) < maxRoublePriceToStack
|
||||
&& !this.itemHelper.isOfBaseclasses(item._id, [
|
||||
BaseClasses.WEAPON,
|
||||
BaseClasses.ARMORED_EQUIPMENT,
|
||||
BaseClasses.AMMO,
|
||||
])
|
||||
&& !this.itemHelper.itemRequiresSoftInserts(item._id)
|
||||
&& this.randomUtil.getChance100(25);
|
||||
&& !this.itemHelper.isOfBaseclasses(item._id, [
|
||||
BaseClasses.WEAPON,
|
||||
BaseClasses.ARMORED_EQUIPMENT,
|
||||
BaseClasses.AMMO,
|
||||
])
|
||||
&& !this.itemHelper.itemRequiresSoftInserts(item._id)
|
||||
&& this.randomUtil.getChance100(25);
|
||||
}
|
||||
|
||||
protected calculateAmmoStackSizeThatFitsBudget(
|
||||
@ -355,7 +354,7 @@ export class RepeatableQuestRewardGenerator
|
||||
const rewardableItemPool = this.getRewardableItems(repeatableConfig, traderId);
|
||||
const minPrice = Math.min(25000, 0.5 * roublesBudget);
|
||||
|
||||
let rewardableItemPoolWithinBudget = rewardableItemPool.map((x) => x[1]);
|
||||
let rewardableItemPoolWithinBudget = rewardableItemPool.map(x => x[1]);
|
||||
rewardableItemPoolWithinBudget = this.filterRewardPoolWithinBudget(
|
||||
rewardableItemPoolWithinBudget,
|
||||
roublesBudget,
|
||||
@ -370,9 +369,9 @@ export class RepeatableQuestRewardGenerator
|
||||
}),
|
||||
);
|
||||
// In case we don't find any items in the price range
|
||||
rewardableItemPoolWithinBudget = rewardableItemPool.filter((x) =>
|
||||
this.itemHelper.getItemPrice(x[0]) < roublesBudget
|
||||
).map((x) => x[1]);
|
||||
rewardableItemPoolWithinBudget = rewardableItemPool.filter(x =>
|
||||
this.itemHelper.getItemPrice(x[0]) < roublesBudget,
|
||||
).map(x => x[1]);
|
||||
}
|
||||
|
||||
return rewardableItemPoolWithinBudget;
|
||||
@ -393,7 +392,7 @@ export class RepeatableQuestRewardGenerator
|
||||
|
||||
if (preset)
|
||||
{
|
||||
const rootItem = preset.find((x) => x._tpl === tpl);
|
||||
const rootItem = preset.find(x => x._tpl === tpl);
|
||||
rewardItem.items = this.itemHelper.reparentItemAndChildren(rootItem, preset);
|
||||
rewardItem.target = rootItem._id; // Target property and root items id must match
|
||||
}
|
||||
@ -436,8 +435,8 @@ export class RepeatableQuestRewardGenerator
|
||||
return false;
|
||||
}
|
||||
|
||||
const traderWhitelist = repeatableQuestConfig.traderWhitelist.find((trader) =>
|
||||
trader.traderId === traderId
|
||||
const traderWhitelist = repeatableQuestConfig.traderWhitelist.find(trader =>
|
||||
trader.traderId === traderId,
|
||||
);
|
||||
return this.isValidRewardItem(tpl, repeatableQuestConfig, traderWhitelist?.rewardBaseWhitelist);
|
||||
},
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ItemHelper } from "@spt-aki/helpers/ItemHelper";
|
||||
import { PresetHelper } from "@spt-aki/helpers/PresetHelper";
|
||||
import { Product } from "@spt-aki/models/eft/common/tables/IBotBase";
|
||||
@ -61,7 +60,7 @@ export class ScavCaseRewardGenerator
|
||||
this.cacheDbItems();
|
||||
|
||||
// Get scavcase details from hideout/scavcase.json
|
||||
const scavCaseDetails = this.databaseServer.getTables().hideout.scavcase.find((r) => r._id === recipeId);
|
||||
const scavCaseDetails = this.databaseServer.getTables().hideout.scavcase.find(r => r._id === recipeId);
|
||||
const rewardItemCounts = this.getScavCaseRewardCountsAndPrices(scavCaseDetails);
|
||||
|
||||
// Get items that fit the price criteria as set by the scavCase config
|
||||
@ -122,7 +121,7 @@ export class ScavCaseRewardGenerator
|
||||
|
||||
// Skip item if item id is on blacklist
|
||||
if (
|
||||
(item._type !== "Item")
|
||||
item._type !== "Item"
|
||||
|| this.scavCaseConfig.rewardItemBlacklist.includes(item._id)
|
||||
|| this.itemFilterService.isItemBlacklisted(item._id)
|
||||
)
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { inject, injectable } from "tsyringe";
|
||||
|
||||
import { ApplicationContext } from "@spt-aki/context/ApplicationContext";
|
||||
import { ContextVariableType } from "@spt-aki/context/ContextVariableType";
|
||||
import { WeightedRandomHelper } from "@spt-aki/helpers/WeightedRandomHelper";
|
||||
@ -78,10 +77,10 @@ export class WeatherGenerator
|
||||
public getInRaidTime(): Date
|
||||
{
|
||||
// tarkov time = (real time * 7 % 24 hr) + 3 hour
|
||||
const russiaOffset = (this.timeUtil.getHoursAsSeconds(3)) * 1000;
|
||||
const russiaOffset = this.timeUtil.getHoursAsSeconds(3) * 1000;
|
||||
return new Date(
|
||||
(russiaOffset + (new Date().getTime() * this.weatherConfig.acceleration))
|
||||
% (this.timeUtil.getHoursAsSeconds(24) * 1000),
|
||||
(russiaOffset + new Date().getTime() * this.weatherConfig.acceleration)
|
||||
% (this.timeUtil.getHoursAsSeconds(24) * 1000),
|
||||
);
|
||||
}
|
||||
|
||||
@ -109,7 +108,7 @@ export class WeatherGenerator
|
||||
wind_direction: this.getWeightedWindDirection(),
|
||||
wind_gustiness: this.getRandomFloat("windGustiness"),
|
||||
rain: rain,
|
||||
rain_intensity: (rain > 1) ? this.getRandomFloat("rainIntensity") : 0,
|
||||
rain_intensity: rain > 1 ? this.getRandomFloat("rainIntensity") : 0,
|
||||
fog: this.getWeightedFog(),
|
||||
temp: this.getRandomFloat("temp"),
|
||||
pressure: this.getRandomFloat("pressure"),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user