diff --git a/.gitea/workflows/run-lint.yaml b/.gitea/workflows/run-lint.yaml new file mode 100644 index 00000000..4870b564 --- /dev/null +++ b/.gitea/workflows/run-lint.yaml @@ -0,0 +1,58 @@ +name: Run Code Linter + +on: + push: + branches: '*' + pull_request: + branches: '*' + +jobs: + biome: + 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: Run Linter + id: run-tests + run: | + cd /workspace/SPT-AKI/Build/server/project + npm run lint + shell: bash + + - 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 "Consistency is professionalism.™" + shell: bash diff --git a/.gitea/workflows/run-style.yaml b/.gitea/workflows/run-style.yaml new file mode 100644 index 00000000..cdc20708 --- /dev/null +++ b/.gitea/workflows/run-style.yaml @@ -0,0 +1,59 @@ +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 diff --git a/.gitea/workflows/run-test.yaml b/.gitea/workflows/run-test.yaml new file mode 100644 index 00000000..196672a8 --- /dev/null +++ b/.gitea/workflows/run-test.yaml @@ -0,0 +1,73 @@ +name: Run Tests + +on: + push: + branches: '*' + pull_request: + branches: '*' + +jobs: + vitest: + runs-on: ubuntu-latest + if: > # Conditional to limit runs: checks if it's NOT a push to a branch with an open PR + github.event_name == 'push' || + github.event.pull_request.head.repo.full_name != github.repository + container: + image: refringe/spt-build-node:1.0.7 + steps: + - name: Clone + run: | + # For pull request events, checkout using GITHUB_SHA + # For push events, checkout using GITHUB_REF_NAME + if [[ $GITHUB_EVENT_NAME == "pull_request" ]]; then + REF=${GITHUB_SHA} + else + REF=${GITHUB_REF_NAME} + fi + + rm -rf /workspace/SPT-AKI/Server/current + git clone https://dev.sp-tarkov.com/${{ github.repository }}.git /workspace/SPT-AKI/Server/current + + cd /workspace/SPT-AKI/Server/current + git fetch + git checkout $REF + env: + GITHUB_SHA: ${{ github.sha }} + GITHUB_REF_NAME: ${{ github.ref_name }} + GITHUB_EVENT_NAME: ${{ github.event_name }} + shell: bash + + - name: Pull LFS Files + run: | + cd /workspace/SPT-AKI/Server/current && ls -lah + 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/Server/current/project/node_modules + key: npm-dependencies-${{ hashFiles('/workspace/SPT-AKI/Server/current/project/package.json') }} + + - name: Install NPM Dependencies + if: steps.cache-npm-dependencies.outputs.cache-hit != 'true' + run: | + cd /workspace/SPT-AKI/Server/current/project + rm -rf /workspace/SPT-AKI/Server/current/project/node_modules + npm install + shell: bash + + - name: Run Tests + id: run-tests + run: | + cd /workspace/SPT-AKI/Server/current/project + npm run test + shell: bash + + - name: Fix Instructions + if: failure() && steps.run-tests.outcome == 'failure' + run: | + echo -e "Automated tests have failed. This could point to an issue with the committed code, or an updated test that has yet to be updated. Please look into resolving these test failures. The testing suite has a GUI to aid in writing tests. You can launch this by running the following command from within the 'project' directory.\n\nnpm run test:ui\n" + echo -e "A test written today is a bug prevented tomorrow.™" + shell: bash diff --git a/FEATURES.md b/FEATURES.md new file mode 100644 index 00000000..17ca7702 --- /dev/null +++ b/FEATURES.md @@ -0,0 +1,319 @@ +# Features + +## Table of Contents +- [Profiles](#Profiles) + - [Progression](#progression) + - [Starting Profile Types](#starting-profile-types) +- [Bots](#bots) + - [AI Types](#ai-types) + - [Generation](#generation) +- [Inventory](#inventory) +- [Traders](#traders) +- [Flea market](#flea-market) +- [Quests](#quests) +- [Hideout](#hideout) +- [Weapon Building](#weapon-building) +- [Raids](#raids) +- [Messages](#messages) +- [Events](#events) +- [Modding](#modding) + +## Profiles + +### Progression + +The player profile is stored as a JSON file, allowing for changes to persist across server restarts. The profile contains the following information for both your PMC and Scav player characters: + +- Task Conditions +- Account Bonuses +- Model Selection +- Health +- Energy, Hydration, & Temperature +- Hideout Build & Production Status +- Items (Inventory, Insured, Quest, Wishlist) +- Inventory +- Quest Progress +- Flea Market Rating & Current Offers +- Common and Mastering Skills +- Various Raid Stats +- Trader Status and Loyalty Levels +- Extract Counts +- Achievements + +### Starting Profile Types + +The following profile types are available to start with when creating an account in the Launcher: + +- Standard Profiles: + - Standard + - Left Behind + - Prepare To Escape + - Edge Of Darkness +- Custom profiles + - SPT Easy Start + - Lots of money, quality of life skills to level 20, and player to level 69. + - SPT Zero to Hero + - No money, skills, trader reputation, or items. Start with a knife. + - SPT Developer + - Developer testing profile, player to level 69, max skills, and max trader reputation. + - USEC will have all quests ready to start. + - BEAR will have all quests ready to hand in. + +## Bots + +### AI Types + +Bot data is emulated to mimic live bots as closely as possible. This includes the following bot types: + +- Scavs + - Regular Scav (*assault*) + - Sniper Scav (*marksman*) + - Tagged & Cursed (*cursedAssault*) +- Bosses + - Reshalla (*bossBully*) + - Guard (*followerBully*) + - Glukhar (*bossGluhar*) + - Assault Guard (*followerGluharAssault*) + - Scout Guard (*followerGluharScout*) + - Security Guard (*followerGluharSecurity*) + - Sniper Guard (*followerGluharSnipe*) + - Killa (*bossKilla*) + - Shturman (*bossKojainy*) + - Guard (*followerKojaniy*) + - Sanitar (*bossSanitar*) + - Guard (*followerSanitar*) + - Tagilla (*bossTagilla*) + - Knight (*bossKnight*) + - Big Pipe (*followerBigPipe*) + - Bird Eye (*followerBirdEye*) + - Zryachiy (*bossZryachiy*) + - Guard (*followerzryachiy*) + - Kaban (*bossBoar*) + - Sniper Guard (*bossBoarSniper*) + - Guard (*followerBoar*) +- Cultists + - Priest (*sectantPriest*) + - Warrior (*sectantWarrior*) +- Raiders (*pmcBot*) +- Rogues (*exUsec*) +- Santa (*gifter*) - *partially implemented* + +*PMCs are generated with a random type from a sub-set of the above list.* + +*Some bot types are only available on some maps.* + +### Generation + +Bots are generated with the following characteristics: + +- All Bots: + - Weapons - *Weighted, semi-randomly selected* + - Ammunition - *Weighted, semi-randomly selected* + - Gear - *Weighted, semi-randomly selected* + - Headgear Attachments - *Weighted, semi-randomly selected* +- PMC Bots + - AI Type - *Randomly chosen from sub-set of possible bot types* + - Dogtags - *Random level & name* + - Chance of name being the name of a contributor to the project + - Voices - *Randomly chosen Bear/USEC voices for each faction* + +Other bot generation systems/features include: + +- Loot item blacklist & whitelist +- Loot items can be configured to be limited to a certain number based on bot type +- Level-relative gear for PMCs from levels 1-15 and 15+ + - Level 1-15 bots have lower-tier items + - Level 15+ bots have access to almost anything +- Randomised gear and weapon durability based on bot type and level + +## Inventory + +The inventory system includes the following features: + +- Move, Split, and Delete Item Stacks +- Add, Modify, and Remove Item Tags +- Armor and Weapon Repair Kits +- Auto-sort Inventory +- Out-of-raid Healing, Eating, & Drinking +- Special Player Slots + +## Traders + +The trader system includes the following features: + +- Buy and sell items from each trader +- Listed items are refreshed on a timer based on the trader +- Purchase limits per refresh period +- Tracks currency spent through each trader +- Loyalty levels +- Reputation +- Item repair from Prapor, Skier, and Mechanic +- Unlock and purchase clothing from Ragman +- Insurance from Therapist and Prapor + - Chance for items to be returned, higher chance for more expensive trader + - Chance parts will be stripped from returned weapons based on value +- Post-raid Therapist Healing +- Fence Item Assortment + - Lists random items for sale + - Emulated system of 'churn' for items sold by Fence + +## Flea market + +The flea market system has been build to simulate the live flea market as closely as possible. It includes the following features: + +- Simulated Player Offers + - Generated with random names, ratings, and expiry times + - Variable offer prices based on live item prices (~20% above and below) + - Weapon presets as offers + - Barter offers + - Listed in multiple currencies (Rouble, Euro, and Dollar) + - Dynamically adjust flea prices that drift below trader price +- Buy Items +- Sell Items + - Generates listing fee + - Increase flea rating by selling items + - Decrease flea rating by failing to sell items + - Items purchased by simulated players + - Offer price effects chance that item will be purchased +- Filtering + - By specific item + - By link to item + - Text search by name + - By currency + - By price range + - By condition range + - By Traders, Players, or Both + - To include barter offers (or not) +- Sorting by + - Rating + - Name + - Price + - Expiry + +## Quests + +The quest system includes the following features: + +- Accurate Quest List - *roughly 90% implemented* +- Trader Quests - *Accept, Turn-in Items, and Complete* +- Daily Quests - *Accept, Replace, Turn-in Items, Complete* + - Simulates Daily and Weekly Quests + - Quest Replacement Fee +- Scav Quests +- Trader items unlock through completion of quests +- Receive messages from traders after interacting with a quest +- Item rewards passed through messages + +## Hideout + +The hideout has the following features implemented: + +- Areas + - Air Filter + - Filter Degradation + - Boosts Skill Levelling + - Bitcoin Farm + - Generation Speed Dependent on Number of Graphics Cards + - Booze Generator + - Crafts Moonshine + - Generator + - Fuel Degradation + - Heating + - Energy Regeneration + - Negative Effects Removal + - Illumination + - Intel Centre + - ~~Unlocks Fence's Scav Quests~~ *not implemented - workaround: unlocks at level 5* + - ~~Reduces Insurance Return Time~~ *not implemented* + - Quest Currency Reward Boost + - Lavatory + - Library + - Medstation + - Nutrition Unit + - Rest Space + - Scav Case + - Custom Reward System + - Security + - Shooting Range + - Solar Power + - Stash + - Upgrades grant larger stash sizes + - Vents + - Water Collector + - Workbench + - Unlocks the ability to repair items + - Christmas Tree +- Item Crafting + - Items are marked found-in-raid on completion + - Continues to track crafting progress even when server is not running + +## Weapon Building + +The weapon building system has been fully implemented: + +- Create Weapon Presets +- Saving Presets +- Load Presets + +## Raids + +The in-raid systems included are as follows: + +- Maps + - Customs + - Factory Day + - Factory Night + - Ground Zero + - Interchange + - Laboratory + - Lighthouse + - Reserve + - Shoreline + - Streets + - Woods +- Loot + - Loot spawning has been generated using over 100,000 EFT offline loot runs. + - Static Loot (in containers) + - Each container type can contain items appropriate to that container type found in offline EFT. + - Loose Loot (on map) + - Randomised loose items found on map in offline EFT. +- Airdrops + - Randomised Spawn Chance + - Request with Red Flare + - Crate Types: + - Weapons & Armour + - Food & Medical + - Barter Goods + - Mixed - *mixture of any of the above items* + - Supported Maps: + - Customs + - Interchange + - Lighthouse + - Reserve + - Shoreline + - Streets + - Woods +- Persisted Raid Damage - *extracting with injury will persist injury out of raid* +- Scav Raids - *raid time and items are reduced to simulate entering a raid late* + +## Messages + +A messaging system has been implemented to allow for the following functionality: + +- Receive messages (with item attachments) from traders or "system" +- Pin/unpin senders within the message list +- Receive all (or individual) attachments +- Send messages to "Commando" friend to execute server commands + +## Events + +The following events have been implemented and have a set time period for when they will be active: + +- Snow +- Halloween +- Christmas + +## Modding + +- The Server project has been built to allow for extensive modifications to nearly any aspect and system used. +- [Example mods](https://dev.sp-tarkov.com/chomp/ModExamples) are provided that cover the most common modding methods. diff --git a/README.md b/README.md index 42469df8..de26217d 100644 --- a/README.md +++ b/README.md @@ -1,352 +1,122 @@ -# Server +# Single Player Tarkov - Server Project -Modding framework for Escape From Tarkov +This is the Server project for the Single Player Tarkov mod for Escape From Tarkov. It can be run locally to replicate responses to the modified Escape From Tarkov client. -[![Build Status](https://drone.sp-tarkov.com/api/badges/SPT-AKI/Server/status.svg?ref=refs/heads/development)](https://drone.sp-tarkov.com/SPT-AKI/Server) -[![Quality Gate Status](https://sonar.sp-tarkov.com/api/project_badges/measure?project=AKI&metric=alert_status&token=d3b87ff5fac591c1f49a57d4a2883c92bfe6a77f)](https://sonar.sp-tarkov.com/dashboard?id=AKI) +# Table of Contents -## Privacy -SPT is an open source project. Your commit credentials as author of a commit will be visible by anyone. Please make sure you understand this before submitting a PR. -Feel free to use a "fake" username and email on your commits by using the following commands: -```bash -git config --local user.name "USERNAME" -git config --local user.email "USERNAME@SOMETHING.com" -``` +- [Features](#features) +- [Installation](#installation) + - [Requirements](#requirements) + - [Initial Setup](#initial-setup) +- [Development](#development) + - [Commands](#commands) + - [Debugging](#debugging) + - [Mod Debugging](#mod-debugging) +- [Contributing](#contributing) + - [Branches](#branchs) + - [Pull Request Guidelines](#pull-request-guidelines) + - [Tests](#tests) +- [License](#license) -## Requirements +## Features -- NodeJS (with npm) -- Visual Studio Code -- git [LFS](https://git-lfs.github.com/) +For a full list of features, please see [FEATURES.md](FEATURES.md). -## Observations +## Installation -- The server was tested to work with **NodeJS v20.11.1**, if you are using a different version and experiencing difficulties change it before looking for support -- If you are updating a branch you've had for some time, run `npm ci` before running any tasks. This will run the clean and install target from npm. -- You can debug your mods using the server, just copy your mod files into the `user/mods` folder and put breakpoints on the **JS** files. **DO NOT** contact the dev team for support on this. +### Requirements -## Pulling -- Run `git lfs fetch` and `git lfs pull` to acquire loot files +This project has been built in [Visual Studio Code](https://code.visualstudio.com/) (VSC) using [Node.js](https://nodejs.org/). We recommend using [NVM](https://github.com/coreybutler/nvm-windows) to manage installation and switching Node versions. If you do not wish to use NVM, you will need to install the version of Node.js listed within the `.nvmrc` file manually. -## Setup +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: -1. Visual Studio Code > File > Open Workspace... > `project\Server.code-workspace` -2. Visual Studio Code > Terminal > Run Task... > npm > npm: Install +- [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 -## Build -This is for preparing for a release, not to run locally. +### Initial Setup -**Mode** | **Location** --------- | ----------------------------------------------------------------- -release | Visual Studio Code > Terminal > Run Build Task... > build:release -debug | Visual Studio Code > Terminal > Run Build Task... > build:debug +To prepare the project for development you will need to: -## Test / Run locally +1. Run `git clone https://dev.sp-tarkov.com/SPT-AKI/Server.git server` to clone the repository. +2. Run `git lfs pull` to download LFS files locally. +2. Open the `project/mod.code-workspace` file in Visual Studio Code (VSC). +3. Run `nvm use 20.11.1` in the VSC terminal. +4. Run `npm install` in the VSC terminal. -Visual Studio Code > Run > Start Debugging +## Development -# Features +### Commands -## Progression -Player profile is stored in SPT folder as a JSON file, allowing for changes to persist -- Scav: - - Stats increase by doing scav raids - - Skills increase by doing scav raids - - Scav reputation system (Karma) - - Scavs hostile below certain level - - Scav run cooldown adjustment - - Scav follow chance adjustment - - Scav case - - ~~Completion time adjustment~~ NOT IMPLEMENTED - - ~~Equipment chance adjustment~~ NOT IMPLEMENTED - - Bosses hostile below certain level - - ~~Exfil price adjustment~~ NOT IMPLEMENTED - - Improved gear with higher rep - - Increase rep by exiting through car extracts -- PMC: - - Stats increase by doing PMC raids - - Skills increase by doing PMC raids - - Hydration/food - - Increase out of raid - - Post-raid levels are persisted to profile - - Raid stat tracking - - Raid count - - Survived count - - KIA count - - MIA count - - AWOL count - - Kills count +The following commands are available after the initial setup. Run them with `npm run `. -## Bots +| 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. | - - Emulated bots: - - assault (scav) - - bossBully (Reshalla) - - bossGluhar - - bossKilla - - bossKnight - - bossKojainy (Shturman) - - bossSanitar - - bossTagilla - - bossZryachiy - - bossBoar (Kaban) - - bossBoarSniper - - curedAssault - - exUsec (Rogue) - - followerBigPipe - - Grenade launcher - - followerBirdEye - - followerBoar - - followerBully - - followerGluharAssault - - followerGluharScout - - followerGluharSecurity - - followerGluharSnipe - - followerKojaniy - - followerSanitar - - followerzryachiy - - gifter (Santa) - - Gives gifts (partially implemented) - - marksman - - pmcBot (Raider) - - sectantPriest (Cultist) - - sectantWarrior (Cultist) -- Gear - - Semi-randomised gear chosen with weighting system - - Randomised durability of gear -- Ammo - - Ammo weighting system to mimic live -- Loot - - Semi-randomised loot - - Item type spawn limit system -- Per-map AI types +### Debugging -## PMCs -- Simulated PMC players - - Custom weapons - - Semi-randomly generated with weighting system - - Semi-randomly chosen ammo with weighting system - - Custom gear - - Semi-randomly generated with weighting system - - Custom headgear - - Randomised attachments with percentage based chance to appear - - Face shields - - Flashlights - - Randomised AI brains - - Chooses random AI behaviour from pool of possible bot types (e.g. raider/rogue/killa) - - Dogtags - - Random level - - Random name - - Voices - - Bear/usec voices for each faction - - Loot item blacklist/whitelist - - Highly configurable in config - - Level-relative gear for PMCs from levels 1-15 and 15+ - - 1-15 bots have lower-tier items - - 15+ bots have access to anything +To debug the project in Visual Studio Code, you can select the `Run` tab and then select the `Start Debugging` option (or the `F5` shortcut). This will start the server in debug mode, attaching a debugger to code execution, allowing you to set breakpoints and step through the code as it runs. -## Inventory - - Move/split/delete stacks - - Tags (add/modify/remove) - - Armor/weapon kit item repair - - Auto-sort - - Out of raid healing - - Out of raid eating - - Special slots (compass etc) +### Mod Debugging -## Traders -- Buy/Sell -- Listed items are refreshed every hour -- purchase limits per refresh period -- Track sold rouble count -- Loyalty levels -- Build reputation -- Item repair - - Calculate randomised durability level based on item type/values -- Alternate clothing from Ragman - - Buy/unlock new clothing -- Insurance - - chance for items to be returned - higher chance for more expensive trader - - Chance parts will be stripped from returned weapons -- Fence - - Lists random items for sale - - Emulated system of 'churn' for items sold by fence - - every 4 minutes 20% of fences' items are replaced - - Configurable through config +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. -## Flea market -- Buy and sell items -- Prices pulled from live data -- Listing tax fee -- Offer filtering -- Offer search -- Filter by item -- Linked search -- Simulated player offers - - Generated with random names/ratings/expiry times - - Variable prices based on live price (20% above/below) - - Weapon presets as offers - - Bartering offers - - Listed currency - - Rouble - - Euro - - Dollar -- Rating - - Increase flea rating by selling items - - Decrease flea rating by failing to sell items - - Will be purchased by simulated players - - Greater chance listed item will be purchased the lower it is listed for -- Adjust flea prices that are massively below trader buy price -- Receive purchased item through mail from seller -- Sorting by - - Rating - - Price - - Name -- Configurable using config +## Contributing -## Quests -- ~~Accurate quest list~~ INCOMPLETE (85% complete) -- Trader quests - - Accept/Complete -- Daily Quests - - Simulated system of daily quests - - Replace daily quest - - Replace quest with new one - - Charged fee - - Scav daily quests - - Types - - Elimination - - Exit location - - Find -- Trader item unlocks through completion of quests -- Receive mail from traders after accepting/completing/failing a quest -- Item rewards given through mail +We're really excited that you're interested in contributing! Before submitting your contribution, please consider the following: -## Hideout -- Areas supported - - Air filter - - Air filter degradation speed calculation - - Skill levelling boost + 40% - - Bitcoin farm - - Coin generation speed calculation - - Booze generator - - Create moonshine - - Generator - - Fuel usage calculation - - Heating - - Energy regen rate - - Negative effects removal rate x2 - - Illumination - - Intel centre - - ~~Unlocks scav tasks from fence~~ NOT IMPLEMENTED - unlocks at level 5 - - ~~Reduces insurance return time by 20%~~ NOT IMPLEMENTED - - Quest money reward boost - - Lavatory - - Library - - Medstation - - Nutrition unit - - Rest space - - Scav case - - Custom reward system - - Configurable in config - - Security - - Shooting range - - Solar power - - Stash - - Gives bonus storage space - - Vents - - Water collector - - Workbench - - Christmas tree -- Item crafting - - Found in raid on completion - - Crafts when server not running +### Branchs -## Weapon building -- Create weapon presets -- Saving of presets +- __master__ + The default branch used for the latest stable release. This branch is protected and typically is only merges with release branches. +- __3.9.0-DEV__ + Development for the next minor release of SPT. Minor releases target the latest version of EFT. Late in the minor release cycle the EFT version is frozen for stability to prepare for release. Larger changes to the project structure may be included in minor releases. +- __3.8.1-DEV__ + Development for the next hotfix release of SPT. Hotfix releases include bug fixes and minor features that do not effect the coding structure of the project. Special care is taken to not break server mod stability. These always target the same version of EFT as the last minor release. -## Raids -- Supported maps - - Customs - - Factory day - - Factory night - - Reserve - - Woods - - Lighthouse - - Laboratory - - Shoreline - - Streets -- Loot - - Generated from over 30,000 loot runs on live, spawn chances calculated from all runs to give fairly accurate depiction of live loot. - - Static loot (containers) - - Each container type can contain items appropriate to that type - - Loose loot - - Randomised loose items found on map -- Airdrops - - Randomised chance of spawning - - Fire red flare to request an airdrop - - Drops 'themed' crates: - - Weapons / armor - - Only weapons and armor - - Food / medical - - Only food and medical items - - Barter goods - - Only barter goods - - Mixed - - A mixture of any of the above items - - Drops lootable crate in: - - Customs - - Reserve - - Woods - - Lighthouse - - Shoreline - - Streets - - Can be adjusted via config file -- Raid damage - - Exiting a raid with injury to player character will be persisted out of raid -- Post-raid therapist healing -- Scav Raids - - Adjusted time when running raids as scav - - Simulated loot being taken by other players the later into the raid player starts +### Pull Request Guidelines -## Messages -- Receive from traders -- Pin/unpin senders -- Accept all attachments -- Accept individual mail attachment +- __Keep Them Small__ + If you're fixing a bug, try to keep the changes to the bug fix only. If you're adding a feature, try to keep the changes to the feature only. This will make it easier to review and merge your changes. +- __Perform a Self-Review__ + Before submitting your changes, review your own code. This will help you catch any mistakes you may have made. +- __Remove Noise__ + Remove any unnecessary changes to white space, code style formatting, or some text change that has no impact related to the intention of the PR. +- __Create a Meaningful Title__ + When creating a PR, make sure the title is meaningful and describes the changes you've made. +- __Write Detailed Commit Messages__ + Bring out your table manners, speak the Queen's English and be on your best behaviour. -## Modding -- Extensive system that allows for the modification of nearly any aspect of SPT -- Example mods covering a good slice of modding capabilities +### Style Guide -## Misc -- Profiles - - Standard/Left Behind/Prepare To Escape/Edge Of Darkness - - Custom profiles - - SPT Easy start - - Lots of money / some QoL skills level 20 / level 69 - - SPT Zero to hero - - No money, skills, trader rep or items, only a knife - - SPT Developer - - Testing profile, level 69, most skills maxed, max trader rep - - USEC have all quests ready to start - - BEAR have all quests ready to hand in -- Note system - - Add - - Edit - - Delete -- Extensive config system - - Alter how SPT works -- Holiday themes in hideout on appropriate days - - Halloween - - Christmas +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. -## Code -- TypeScript - - Majority of EFT request/response classes passed from client to server have been mapped -- Unit Tests - - Supports tests via vitest -- Dependency injection -- Config files accessible from `Aki_Data\Server\configs` / `project\assets\configs` +### Tests + +We have a number of tests that are run automatically when you submit a pull request. You can run these tests locally by running `npm run test`. If you're adding a new feature or fixing a bug, please conceder adding tests to cover your changes so that we can ensure they don't break in the future. + +## License + +This project is licensed under the NCSA Open Source License. See the [LICENSE](LICENSE.md) file for details. diff --git a/project/.vscode/extensions.json b/project/.vscode/extensions.json new file mode 100644 index 00000000..49f98cc2 --- /dev/null +++ b/project/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "EditorConfig.EditorConfig", + "dprint.dprint", + "dbaeumer.vscode-eslint", + "biomejs.biome", + "vitest.explorer", + "refringe.spt-id-highlighter" + ] +} diff --git a/project/Server.code-workspace b/project/Server.code-workspace index 1758f080..5ab13e4e 100644 --- a/project/Server.code-workspace +++ b/project/Server.code-workspace @@ -4,14 +4,6 @@ "path": "." } ], - "extensions": { - "recommendations": [ - "EditorConfig.EditorConfig", - "dprint.dprint", - "dbaeumer.vscode-eslint", - "biomejs.biome" - ] - }, "settings": { "window.title": "SPT-AKI Server", "editor.formatOnSave": true, diff --git a/project/assets/configs/bot.json b/project/assets/configs/bot.json index 909d210d..30009cd6 100644 --- a/project/assets/configs/bot.json +++ b/project/assets/configs/bot.json @@ -317,33 +317,45 @@ "exusec": { "60098ad7c2240c0fe85c570a": 2 }, - "bossbully": {}, - "bossgluhar": {}, + "bossbully": { + "5448ba0b4bdc2d02308b456c": 1 + }, + "bossgluhar": { + "5c94bbff86f7747ee735c08f": 1 + }, "bosskilla": {}, "bosskojaniy": { "5d08d21286f774736e7c94c3": 1, "5c94bbff86f7747ee735c08f": 1 }, - "bosssanitar": {}, + "bosssanitar": { + "5efde6b4f5448336730dbd61": 1, + "5eff09cd30a7dc22fd1ddfed": 1 + }, "bosstagilla": {}, "bossknight": {}, "bosszryachiy": {}, "bosskolontay": {}, "bosstest": {}, "followerbully": { - "5448e8d64bdc2dce718b4568": 2 + "5448e8d64bdc2dce718b4568": 1, + "5448ba0b4bdc2d02308b456c": 1 }, "followergluharassault": { - "5c0fa877d174af02a012e1cf": 1 + "5c0fa877d174af02a012e1cf": 1, + "5c94bbff86f7747ee735c08f": 0 }, "followergluharscout": { - "5c0fa877d174af02a012e1cf": 1 + "5c0fa877d174af02a012e1cf": 1, + "5c94bbff86f7747ee735c08f": 0 }, "followergluharsecurity": { - "5c0fa877d174af02a012e1cf": 1 + "5c0fa877d174af02a012e1cf": 1, + "5c94bbff86f7747ee735c08f": 0 }, "followergluharsnipe": { - "5c0fa877d174af02a012e1cf": 1 + "5c0fa877d174af02a012e1cf": 1, + "5c94bbff86f7747ee735c08f": 0 }, "followerkojaniy": { "5448e8d64bdc2dce718b4568": 2 @@ -354,14 +366,31 @@ "followerbigpipe": {}, "followerzryachiy": {}, "followertest": {}, - "followerboar": {}, - "followerboarclose1": {}, - "followerboarclose2": {}, + "followerboar": { + "5448e8d04bdc2ddf718b4569": 1, + "544fb37f4bdc2dee738b4567": 1, + "5448e8d64bdc2dce718b4568": 1, + "5c94bbff86f7747ee735c08f": 1 + }, + "followerboarclose1": { + "5448e8d04bdc2ddf718b4569": 1, + "5448e8d64bdc2dce718b4568": 1, + "5c94bbff86f7747ee735c08f": 1 + }, + "followerboarclose2": { + "5448e8d04bdc2ddf718b4569": 1, + "5448e8d64bdc2dce718b4568": 1, + "5c94bbff86f7747ee735c08f": 1 + }, "followerkolontayassault": { - "544fb62a4bdc2dfb738b4568": 2 + "5448e8d04bdc2ddf718b4569": 2, + "5c94bbff86f7747ee735c08f": 1, + "5448e8d64bdc2dce718b4568": 2 }, "followerkolontaysecurity": { - "544fb62a4bdc2dfb738b4568": 2 + "5448e8d04bdc2ddf718b4569": 2, + "5c94bbff86f7747ee735c08f": 1, + "5448e8d64bdc2dce718b4568": 2 }, "sectantpriest": {}, "sectantwarrior": {}, @@ -369,8 +398,12 @@ "pmcbot": { "60098ad7c2240c0fe85c570a": 2 }, - "arenafighterevent": {}, - "arenafighter": {}, + "arenafighterevent": { + "5734758f24597738025ee253": 1 + }, + "arenafighter": { + "5734758f24597738025ee253": 1 + }, "crazyassaultevent": {}, "assaultgroup": {}, "gifter": {}, @@ -648,7 +681,8 @@ "nvgIsActiveChanceNightPercent": 90, "lightIsActiveDayChancePercent": 25, "lightIsActiveNightChancePercent": 85, - "laserIsActiveChancePercent": 85 + "laserIsActiveChancePercent": 85, + "forceStock": true }, "followerboar": { "nvgIsActiveChanceDayPercent": 20, @@ -756,6 +790,7 @@ "lightIsActiveDayChancePercent": 35, "lightIsActiveNightChancePercent": 95, "laserIsActiveChancePercent": 95, + "forceStock": true, "weaponModLimits": { "scopeLimit": 1, "lightLaserLimit": 1 @@ -768,6 +803,7 @@ "lightIsActiveDayChancePercent": 35, "lightIsActiveNightChancePercent": 95, "laserIsActiveChancePercent": 95, + "forceStock": true, "weaponModLimits": { "scopeLimit": 1, "lightLaserLimit": 1 @@ -977,7 +1013,8 @@ "mod_equipment_000": 3, "mod_equipment_001": 3, "mod_equipment_002": 3, - "mod_nvg": 3 + "mod_nvg": 3, + "mod_mount": 1 }, "weaponMods": { "mod_barrel": 5, @@ -1618,18 +1655,18 @@ "5bffdc370db834001d23eca8": 100, "54491bb74bdc2d09088b4567": 100 } - }, - "clothing": { - "add": {}, - "edit": { - "body": { - "5cc0858d14c02e000c6bea66": 20, - "5cde95d97d6c8b647a3769b0": 20 - }, - "feet": { - "5cc085bb14c02e000e67a5c5": 20, - "5cde95ef7d6c8b04713c4f2d": 20 - } + } + }, + "clothing": { + "add": {}, + "edit": { + "body": { + "5cc0858d14c02e000c6bea66": 20, + "5cde95d97d6c8b647a3769b0": 20 + }, + "feet": { + "5cc085bb14c02e000e67a5c5": 20, + "5cde95ef7d6c8b04713c4f2d": 20 } } } @@ -1738,6 +1775,7 @@ } }, "equipment": { + "add": {}, "edit": { "ArmorVest": { "5c0e5bab86f77461f55ed1f3": 135, @@ -1804,6 +1842,7 @@ "max": 50 }, "equipment": { + "add": {}, "edit": { "FirstPrimaryWeapon": { "5c501a4d2e221602b412b540": 2 @@ -1911,6 +1950,7 @@ } }, "equipment": { + "add": {}, "edit": { "FirstPrimaryWeapon": { "65290f395ae2ae97b80fdf2d": 8, @@ -2601,15 +2641,15 @@ "20000": 13, "15000": 28, "10000": 51, - "5000": 100 + "5000": 200 }, "5696686a4bdc2da3298b456a": { - "50": 10, + "50": 20, "100": 5, "250": 1 }, "569668774bdc2da2298b4568": { - "50": 10, + "50": 20, "100": 5, "250": 1 } diff --git a/project/assets/configs/core.json b/project/assets/configs/core.json index cac90ca3..776c0474 100644 --- a/project/assets/configs/core.json +++ b/project/assets/configs/core.json @@ -1,10 +1,11 @@ { - "akiVersion": "3.8.0", + "akiVersion": "3.8.1", "projectName": "SPT-AKI", "compatibleTarkovVersion": "0.14.1.29197", "serverName": "SPT Server", "profileSaveIntervalSeconds": 15, "sptFriendNickname": "SPT", + "allowProfileWipe": true, "bsgLogging": { "verbosity": 6, "sendToServer": false diff --git a/project/assets/configs/gifts.json b/project/assets/configs/gifts.json index d5518189..d5f3629b 100644 --- a/project/assets/configs/gifts.json +++ b/project/assets/configs/gifts.json @@ -3663,6 +3663,23 @@ "associatedEvent": "Promo", "collectionTimeHours": 72, "messageText": "Thank you for purchasing of the first book in EFT series by A, Kontorovich. We are glad to give you this theme package with ingame items." + }, + "UNHEARD": { + "items": [ + { + "_id": "a89275c1b18254ef7432a6d9", + "_tpl": "5696686a4bdc2da3298b456a", + "slotId": "main", + "upd": { + "StackObjectsCount": 250 + }, + "parentId": "64b996c9d0de4697180359b6" + } + ], + "sender": "System", + "messageText": "Have a nice 20 minute adventure in the blatant plagiarist game. In and out", + "collectionTimeHours": 72, + "associatedEvent": "Promo" } } } \ No newline at end of file diff --git a/project/assets/configs/hideout.json b/project/assets/configs/hideout.json index b5e229f9..b28f446e 100644 --- a/project/assets/configs/hideout.json +++ b/project/assets/configs/hideout.json @@ -1,9 +1,12 @@ { "runIntervalSeconds": 10, "hoursForSkillCrafting": 28800, - "runIntervalValues": { + "runIntervalValues": { "inRaid": 60, "outOfRaid": 10 }, - "expCraftAmount": 10 + "expCraftAmount": 10, + "overrideCraftTimeSeconds": -1, + "overrideBuildTimeSeconds": -1, + "updateProfileHideoutWhenActiveWithinMinutes": 90 } \ No newline at end of file diff --git a/project/assets/configs/http.json b/project/assets/configs/http.json index 97892786..a6defa80 100644 --- a/project/assets/configs/http.json +++ b/project/assets/configs/http.json @@ -1,6 +1,8 @@ { "ip": "127.0.0.1", "port": 6969, + "backendIp": "127.0.0.1", + "backendPort": 6969, "webSocketPingDelayMs": 90000, "logRequests": true, "serverImagePathOverride": {} diff --git a/project/assets/configs/inraid.json b/project/assets/configs/inraid.json index 5bbe48cc..97085b3d 100644 --- a/project/assets/configs/inraid.json +++ b/project/assets/configs/inraid.json @@ -11,8 +11,7 @@ "randomTime": false }, "save": { - "loot": true, - "durability": true + "loot": true }, "carExtracts": [ "Dorms V-Ex", diff --git a/project/assets/configs/inventory.json b/project/assets/configs/inventory.json index 2228a2ee..114a8fab 100644 --- a/project/assets/configs/inventory.json +++ b/project/assets/configs/inventory.json @@ -120,7 +120,6 @@ "5ac66d2e5acfc43b321d4b53": 1, "5ac66d725acfc43b321d4b60": 1, "5ac66d9b5acfc4001633997a": 1, - "62e7c4fba689e8c9c50dfc38": 1, "63171672192e68c5460cebc5": 1, "5c488a752e221602b412af63": 1, "5dcbd56fdbd3d91b3e5468d5": 1, @@ -133,7 +132,6 @@ "5beed0f50db834001c062b12": 1, "5cc82d76e24e8d00134b4b83": 1, "5fc3e272f8b6a877a729eac5": 1, - "5fb6548dd1409e5ca04b54f9": 0, "5aafa857e5b5b00018480968": 1, "5bfea6e90db834001b7347f3": 1, "5cadfbf7ae92152ac412eeef": 1, @@ -144,7 +142,19 @@ "62e14904c2699c0ec93adc47": 1, "5c46fbd72e2216398b5a8c9c": 1, "5df8ce05b11454561e39243b": 1, - "5df24cf80dee1b22f862e9bc": 1 + "5df24cf80dee1b22f862e9bc": 1, + "5f2a9575926fd9352339381f": 1, + "6410733d5dd49d77bd07847e": 1, + "5ac66cb05acfc40198510a10": 1, + "5ac66d015acfc400180ae6e4": 1, + "57c44b372459772d2b39b8ce": 1, + "65290f395ae2ae97b80fdf2d": 1, + "5fb64bc92b1b027b1f50bcf2": 1, + "5fc3f2d5900b1d5091531e57": 1, + "5a367e5dc4a282000e49738f": 1, + "65268d8ecb944ff1e90ea385": 1, + "5e848cc2988a8701445df1e8": 1, + "5a7828548dc32e5a9c28b516": 1 }, "defaultPresetsOnly": true, "foundInRaid": true, @@ -230,6 +240,11 @@ "type": "medical", "min": 2, "max": 7 + }, + "5447e1d04bdc2dff2f8b4567": { + "type": "knife", + "min": 0, + "max": 0 } }, "ammoBoxWhitelist": [ @@ -240,13 +255,19 @@ "6489851fc827d4637f01791b", "6489854673c462723909a14e", "648985c074a806211e4fb682", - "6489875745f9ca4ba51c4808", + "6579847c5a0e5879d12f2873", "648987d673c462723909a151", "648986bbc827d4637f01791e", "64898583d5b4df6140000a1d", - "64898602f09d032aa9399d56", + "5c1262a286f7743f8a69aab2", "6489870774a806211e4fb685", - "6489879db5a2df1c815a04ef" + "6489879db5a2df1c815a04ef", + "657023f81419851aef03e6f1", + "657023decfc010a0f50069ec", + "65702546cfc010a0f5006a1f", + "5737250c2459776125652acc", + "657024b8bfc87b3a34093232", + "65702474bfc87b3a34093226" ], "allowBossItems": false }, @@ -254,4 +275,4 @@ "skillGainMultiplers": { "Strength": 1 } -} \ No newline at end of file +} diff --git a/project/assets/configs/item.json b/project/assets/configs/item.json index 40845135..584aa85a 100644 --- a/project/assets/configs/item.json +++ b/project/assets/configs/item.json @@ -50,6 +50,7 @@ "5580239d4bdc2de7118b4583" ], "rewardItemBlacklist": [ + "58ac60eb86f77401897560ff", "5e997f0b86f7741ac73993e2", "5b44abe986f774283e2e3512", "5e99711486f7744bfc4af328", diff --git a/project/assets/configs/location.json b/project/assets/configs/location.json index 2c64b10f..640a7d50 100644 --- a/project/assets/configs/location.json +++ b/project/assets/configs/location.json @@ -1144,9 +1144,9 @@ }, "minFillLooseMagazinePercent": 50, "minFillStaticMagazinePercent": 50, - "makeWishingTreeAlwaysGiveGift": true, "allowDuplicateItemsInStaticContainers": true, "magazineLootHasAmmoChancePercent": 50, + "staticMagazineLootHasAmmoChancePercent": 0, "looseLootBlacklist": {}, "scavRaidTimeSettings": { "settings": { @@ -1293,13 +1293,12 @@ "minStaticLootPercent": 60, "reducedChancePercent": 95, "reductionPercentWeights": { - "20": 2, + "20": 3, "30": 4, - "40": 4, + "40": 5, "50": 4, "60": 4, - "70": 1, - "80": 1 + "70": 1 }, "adjustWaves": true }, diff --git a/project/assets/configs/pmc.json b/project/assets/configs/pmc.json index 3bb2f0d0..7d882731 100644 --- a/project/assets/configs/pmc.json +++ b/project/assets/configs/pmc.json @@ -704,5 +704,6 @@ ], "forceHealingItemsIntoSecure": true, "addPrefixToSameNamePMCAsPlayerChance": 40, - "allPMCsHavePlayerNameWithRandomPrefixChance": 1 + "allPMCsHavePlayerNameWithRandomPrefixChance": 1, + "addSecureContainerLootFromBotConfig": false } \ No newline at end of file diff --git a/project/assets/configs/trader.json b/project/assets/configs/trader.json index 2144725a..7a2e57ec 100644 --- a/project/assets/configs/trader.json +++ b/project/assets/configs/trader.json @@ -157,7 +157,7 @@ "543be6564bdc2df4348b4568": 0, "5448ecbe4bdc2d60728b4568": 0, "5671435f4bdc2d96058b4569": 0, - "543be5cb4bdc2deb348b4568": 3, + "543be5cb4bdc2deb348b4568": 5, "5448e53e4bdc2d60728b4567": 7 }, "preventDuplicateOffersOfCategory": [ @@ -319,6 +319,7 @@ "left_side_plate": 75, "right_side_plate": 75 }, + "ammoMaxPenLimit": 20, "blacklistSeasonalItems": true, "blacklist": [ "5c164d2286f774194c5e69fa", @@ -342,7 +343,8 @@ "5a341c4086f77401f2541505", "5422acb9af1c889c16000029", "64d0b40fbe2eed70e254e2d4", - "5fc22d7c187fea44d52eda44" + "5fc22d7c187fea44d52eda44", + "646372518610c40fc20204e8" ], "coopExtractGift": { "sendGift": true, @@ -351,7 +353,11 @@ "5da89b3a86f7742f9026cb83 0" ], "giftExpiryHours": 168, - "presetCount": { + "weaponPresetCount": { + "min": 0, + "max": 0 + }, + "armorPresetCount": { "min": 0, "max": 0 }, @@ -423,4 +429,4 @@ }, "btrDeliveryExpireHours": 240 } -} \ No newline at end of file +} diff --git a/project/assets/database/bots/types/arenafighter.json b/project/assets/database/bots/types/arenafighter.json index 85929b09..b192c202 100644 --- a/project/assets/database/bots/types/arenafighter.json +++ b/project/assets/database/bots/types/arenafighter.json @@ -1,20 +1,20 @@ { "appearance": { "body": { - "5d5e7e7586f77427997cfb7f": 1, - "5d5e7e8386f774393602d6fa": 1, - "5df8a10486f77412672a1e3a": 1, - "5e4bb3ee86f77406975c934e": 1, - "5e9da1d086f774054a667134": 1, - "5fd1eb3fbe3b7107d66cb645": 1 + "5d5e7e7586f77427997cfb7f": 9, + "5d5e7e8386f774393602d6fa": 4, + "5df8a10486f77412672a1e3a": 10, + "5e4bb3ee86f77406975c934e": 4, + "5e9da1d086f774054a667134": 8, + "5fd1eb3fbe3b7107d66cb645": 9 }, "feet": { - "5cc2e5d014c02e15d53d9c03": 1, - "5d28af7886f77429275dba25": 1, - "5d5e7f4986f7746956659f8a": 1, - "5f5e410c6bdad616ad46d60b": 1, - "5f5e41366760b4138443b343": 1, - "5f5e41576760b4138443b344": 1 + "5cc2e5d014c02e15d53d9c03": 8, + "5d28af7886f77429275dba25": 9, + "5d5e7f4986f7746956659f8a": 8, + "5f5e410c6bdad616ad46d60b": 4, + "5f5e41366760b4138443b343": 10, + "5f5e41576760b4138443b344": 5 }, "hands": { "5cc2e68f14c02e28b47de290": 1, @@ -38,13 +38,13 @@ "chances": { "equipment": { "ArmBand": 0, - "ArmorVest": 67, + "ArmorVest": 65, "Backpack": 72, - "Earpiece": 56, + "Earpiece": 61, "Eyewear": 97, - "FaceCover": 70, + "FaceCover": 75, "FirstPrimaryWeapon": 100, - "Headwear": 94, + "Headwear": 95, "Holster": 100, "Pockets": 100, "Scabbard": 0, @@ -52,25 +52,30 @@ "SecuredContainer": 100, "TacticalVest": 100 }, - "mods": { + "equipmentMods": { "back_plate": 100, "front_plate": 100, - "left_side_plate": 25, - "mod_charge": 100, - "mod_equipment": 0, - "mod_equipment_000": 11, + "left_side_plate": 0, + "mod_equipment": 11, + "mod_equipment_000": 0, "mod_equipment_001": 0, "mod_equipment_002": 0, + "mod_mount": 0, + "mod_nvg": 0, + "right_side_plate": 0 + }, + "weaponMods": { + "mod_charge": 100, "mod_flashlight": 100, "mod_foregrip": 84, "mod_handguard": 100, "mod_launcher": 0, "mod_magazine": 100, "mod_mount": 45, - "mod_mount_000": 35, - "mod_mount_001": 25, + "mod_mount_000": 34, + "mod_mount_001": 21, "mod_mount_002": 53, - "mod_mount_003": 62, + "mod_mount_003": 55, "mod_mount_004": 40, "mod_muzzle": 61, "mod_muzzle_000": 100, @@ -79,18 +84,17 @@ "mod_pistol_grip": 0, "mod_reciever": 100, "mod_scope": 77, - "mod_sight_front": 82, - "mod_sight_rear": 83, - "mod_stock": 72, + "mod_sight_front": 85, + "mod_sight_rear": 84, + "mod_stock": 75, "mod_stock_000": 100, "mod_stock_002": 0, - "mod_tactical": 14, - "mod_tactical_000": 9, - "mod_tactical_001": 20, + "mod_tactical": 13, + "mod_tactical_000": 7, + "mod_tactical_001": 14, "mod_tactical_002": 0, "mod_tactical_003": 100, - "mod_tactical_2": 0, - "right_side_plate": 25 + "mod_tactical_2": 0 } }, "difficulty": { @@ -2069,33 +2073,116 @@ ], "generation": { "items": { + "backpackLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 0 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 10, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { - "max": 1, - "min": 0 + "weights": { + "0": 1, + "1": 2, + "2": 0 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] }, "grenades": { - "max": 5, - "min": 0 + "weights": { + "0": 1, + "1": 2, + "2": 3, + "3": 1, + "4": 0, + "5": 0 + }, + "whitelist": [] }, "healing": { - "max": 2, - "min": 1 - }, - "looseLoot": { - "max": 4, - "min": 1 + "weights": { + "0": 1, + "1": 2, + "2": 1 + }, + "whitelist": [] }, "magazines": { - "max": 4, - "min": 2 + "weights": { + "0": 0, + "1": 0, + "2": 1, + "3": 3, + "4": 1 + }, + "whitelist": [] + }, + "pocketLoot": { + "weights": { + "0": 1, + "1": 4, + "2": 4, + "3": 1, + "4": 1 + }, + "whitelist": [] }, "specialItems": { - "max": 0, - "min": 0 + "weights": { + "0": 1, + "1": 0 + }, + "whitelist": [] }, "stims": { - "max": 1, - "min": 0 + "weights": { + "0": 2, + "1": 1, + "2": 0 + }, + "whitelist": [] + }, + "vestLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 0, + "5": 0, + "6": 0 + }, + "whitelist": [] } } }, @@ -2161,9 +2248,9 @@ "56dff2ced2720bb4668b4567": 1 }, "Caliber556x45NATO": { - "54527a984bdc2d4e668b4567": 1, - "54527ac44bdc2d36668b4567": 1, - "59e6920f86f77411d82aa167": 1 + "54527a984bdc2d4e668b4567": 6, + "54527ac44bdc2d36668b4567": 5, + "59e6920f86f77411d82aa167": 2 }, "Caliber57x28": { "5cc80f38e4a949001152b560": 1 @@ -2175,22 +2262,22 @@ "59e0d99486f7744a32234762": 1 }, "Caliber762x51": { - "58dd3ad986f77403051cba8f": 1, - "5a6086ea4f39f99cd479502f": 1, - "5a608bf24f39f98ffc77720e": 1, + "58dd3ad986f77403051cba8f": 2, + "5a6086ea4f39f99cd479502f": 3, + "5a608bf24f39f98ffc77720e": 2, "5e023e53d4353e3302577c4c": 1 }, "Caliber9x18PM": { "573719762459775a626ccbc1": 1 }, "Caliber9x19PARA": { - "56d59d3ad2720bdb418b4577": 1, - "5c925fa22e221601da359b7b": 1, - "5efb0da7a29a85116f6ea05f": 1 + "56d59d3ad2720bdb418b4577": 53, + "5c925fa22e221601da359b7b": 16, + "5efb0da7a29a85116f6ea05f": 4 }, "Caliber9x21": { - "5a26abfac4a28232980eabff": 1, - "5a26ac0ec4a28200741e1e18": 1 + "5a26abfac4a28232980eabff": 3, + "5a26ac0ec4a28200741e1e18": 8 }, "Caliber9x39": { "5c0d668f86f7747ccb7f13b2": 1 @@ -2199,108 +2286,108 @@ "equipment": { "ArmBand": {}, "ArmorVest": { - "5648a7494bdc2d9d488b4583": 1, - "5ab8e79e86f7742d8b372e78": 1, - "5b44d22286f774172b0c9de8": 1, - "5c0e51be86f774598e797894": 1, + "5648a7494bdc2d9d488b4583": 4, + "5ab8e79e86f7742d8b372e78": 2, + "5b44d22286f774172b0c9de8": 3, + "5c0e51be86f774598e797894": 4, "5c0e53c886f7747fa54205c7": 1, - "5c0e57ba86f7747fa141986d": 1, - "5c0e5bab86f77461f55ed1f3": 1, + "5c0e57ba86f7747fa141986d": 4, + "5c0e5bab86f77461f55ed1f3": 3, "5c0e625a86f7742d77340f62": 1, "5c0e655586f774045612eeb2": 1, - "5ca2151486f774244a3b8d30": 1, + "5ca2151486f774244a3b8d30": 2, "5fd4c474dd870108a754b241": 1, - "609e8540d5c319764c2bc2e9": 1, + "609e8540d5c319764c2bc2e9": 2, "63737f448b28897f2802b874": 1 }, "Backpack": { - "545cdae64bdc2d39198b4568": 1, - "5ca20d5986f774331e7c9602": 1, - "5f5e467b0bc58666c37e7821": 1, + "545cdae64bdc2d39198b4568": 2, + "5ca20d5986f774331e7c9602": 2, + "5f5e467b0bc58666c37e7821": 3, "6034d103ca006d2dca39b3f0": 1, - "6038d614d10cbf667352dd44": 1, - "60a272cc93ef783291411d8e": 1, - "60a2828e8689911a226117f9": 1, - "618cfae774bb2d036a049e7c": 1, - "619cf0335771dd3c390269ae": 1, - "62a1b7fbc30cfa1d366af586": 1 + "6038d614d10cbf667352dd44": 4, + "60a272cc93ef783291411d8e": 2, + "60a2828e8689911a226117f9": 7, + "618cfae774bb2d036a049e7c": 5, + "619cf0335771dd3c390269ae": 3, + "62a1b7fbc30cfa1d366af586": 3 }, "Earpiece": { - "5645bcc04bdc2d363b8b4572": 1, - "5aa2ba71e5b5b000137b758f": 1, - "5b432b965acfc47a8774094e": 1, - "5e4d34ca86f774264f758330": 1, - "6033fa48ffd42c541047f728": 1 + "5645bcc04bdc2d363b8b4572": 5, + "5aa2ba71e5b5b000137b758f": 5, + "5b432b965acfc47a8774094e": 5, + "5e4d34ca86f774264f758330": 5, + "6033fa48ffd42c541047f728": 7 }, "Eyewear": { - "557ff21e4bdc2d89578b4586": 1, - "59e770b986f7742cbd762754": 1, - "5b432be65acfc433000ed01f": 1, - "603409c80ca681766b6a0fb2": 1, - "61c18d83b00456371a66814b": 1 + "557ff21e4bdc2d89578b4586": 12, + "59e770b986f7742cbd762754": 13, + "5b432be65acfc433000ed01f": 10, + "603409c80ca681766b6a0fb2": 4, + "61c18d83b00456371a66814b": 4 }, "FaceCover": { - "572b7fa524597762b747ce82": 1, - "5ab8f39486f7745cd93a1cca": 1, - "5ab8f4ff86f77431c60d91ba": 1, - "5b432f3d5acfc4704b4a1dfb": 1, - "5fd8d28367cb5e077335170f": 1, + "572b7fa524597762b747ce82": 2, + "5ab8f39486f7745cd93a1cca": 3, + "5ab8f4ff86f77431c60d91ba": 6, + "5b432f3d5acfc4704b4a1dfb": 19, + "5fd8d28367cb5e077335170f": 2, "60363c0c92ec1c31037959f5": 1 }, "FirstPrimaryWeapon": { - "5447a9cd4bdc2dbd208b4567": 1, - "576165642459773c7a400233": 1, - "57c44b372459772d2b39b8ce": 1, + "5447a9cd4bdc2dbd208b4567": 2, + "576165642459773c7a400233": 3, + "57c44b372459772d2b39b8ce": 2, "587e02ff24597743df3deaeb": 1, "59984ab886f7743e98271174": 1, - "5a367e5dc4a282000e49738f": 1, + "5a367e5dc4a282000e49738f": 3, "5a7828548dc32e5a9c28b516": 1, - "5aafa857e5b5b00018480968": 1, - "5ac4cd105acfc40016339859": 1, - "5ac66cb05acfc40198510a10": 1, + "5aafa857e5b5b00018480968": 2, + "5ac4cd105acfc40016339859": 2, + "5ac66cb05acfc40198510a10": 2, "5ba26383d4351e00334c93d9": 1, - "5cc82d76e24e8d00134b4b83": 1, - "5dcbd56fdbd3d91b3e5468d5": 1, - "5e00903ae9dc277128008b87": 1, + "5cc82d76e24e8d00134b4b83": 2, + "5dcbd56fdbd3d91b3e5468d5": 2, + "5e00903ae9dc277128008b87": 3, "5f2a9575926fd9352339381f": 1, - "5fbcc1d9016cce60e8341ab3": 1, - "5fc3f2d5900b1d5091531e57": 1, + "5fbcc1d9016cce60e8341ab3": 3, + "5fc3f2d5900b1d5091531e57": 3, "60339954d62c9b14ed777c06": 1, "618428466ef05c2ce828f218": 1, "623063e994fc3f7b302a9696": 1, - "628b9c37a733087d0d7fe84b": 1, - "62e14904c2699c0ec93adc47": 1, + "628b9c37a733087d0d7fe84b": 2, + "62e14904c2699c0ec93adc47": 4, "62e7c4fba689e8c9c50dfc38": 1 }, "Headwear": { - "5645bc214bdc2d363b8b4571": 1, + "5645bc214bdc2d363b8b4571": 2, "5a154d5cfcdbcb001a3b00da": 1, - "5aa2b8d7e5b5b00014028f4a": 1, - "5aa2ba19e5b5b00014028f4e": 1, - "5aa7d193e5b5b000171d063f": 1, - "5aa7e4a4e5b5b000137b76f2": 1, - "5ac8d6885acfc400180ae7b0": 1, - "5b40e1525acfc4771e1c6611": 1, - "5b40e2bc5acfc40016388216": 1, - "5b40e3f35acfc40016388218": 1, - "5b40e4035acfc47a87740943": 1, - "5b432d215acfc4771e1c6624": 1, + "5aa2b8d7e5b5b00014028f4a": 5, + "5aa2ba19e5b5b00014028f4e": 6, + "5aa7d193e5b5b000171d063f": 3, + "5aa7e4a4e5b5b000137b76f2": 2, + "5ac8d6885acfc400180ae7b0": 2, + "5b40e1525acfc4771e1c6611": 3, + "5b40e2bc5acfc40016388216": 2, + "5b40e3f35acfc40016388218": 3, + "5b40e4035acfc47a87740943": 2, + "5b432d215acfc4771e1c6624": 2, "5ea17ca01412a1425304d1c0": 1, - "5f60b34a41e30a4ab12a6947": 1, + "5f60b34a41e30a4ab12a6947": 2, "60361b5a9a15b10d96792291": 1, "6040de02647ad86262233012": 1, - "61bca7cda0eae612383adf57": 1 + "61bca7cda0eae612383adf57": 4 }, "Holster": { - "56d59856d2720bd8418b456a": 1, - "59f98b4986f7746f546d2cef": 1, - "5a17f98cfcdbcb0980087290": 1, + "56d59856d2720bd8418b456a": 3, + "59f98b4986f7746f546d2cef": 2, + "5a17f98cfcdbcb0980087290": 2, "5b1fa9b25acfc40018633c01": 1, - "5cadc190ae921500103bb3b6": 1, - "5e81c3cbac2bb513793cdc75": 1, - "602a9740da11d6478d5a06dc": 1, + "5cadc190ae921500103bb3b6": 3, + "5e81c3cbac2bb513793cdc75": 25, + "602a9740da11d6478d5a06dc": 2, "6193a720f8ee7e52e42109ed": 1, - "63088377b5cd696784087147": 1 + "63088377b5cd696784087147": 5 }, "Pockets": { "5af99e9186f7747c447120b8": 1 @@ -2311,19 +2398,19 @@ "5c0a794586f77461c458f892": 1 }, "TacticalVest": { - "544a5caa4bdc2d1a388b4568": 1, + "544a5caa4bdc2d1a388b4568": 2, "5648a69d4bdc2ded0b8b457b": 1, - "5929a2a086f7744f4b234d43": 1, - "5d5d85c586f774279a21cbdb": 1, - "5e9db13186f7742f845ee9d3": 1, - "5f5f41f56760b4138443b352": 1, - "5fd4c60f875c30179f5d04c2": 1, + "5929a2a086f7744f4b234d43": 5, + "5d5d85c586f774279a21cbdb": 5, + "5e9db13186f7742f845ee9d3": 4, + "5f5f41f56760b4138443b352": 5, + "5fd4c60f875c30179f5d04c2": 2, "603648ff5a45383c122086ac": 1, - "6040dd4ddcf9592f401632d2": 1, - "60a621c49c197e4e8c4455e6": 1, + "6040dd4ddcf9592f401632d2": 2, + "60a621c49c197e4e8c4455e6": 10, "60a6220e953894617404b00a": 1, - "61bc85697113f767765c7fe7": 1, - "61bcc89aef0f505f0c6cd0fc": 1, + "61bc85697113f767765c7fe7": 2, + "61bcc89aef0f505f0c6cd0fc": 3, "639343fce101f4caa40a4ef3": 1 } }, @@ -2629,6 +2716,57 @@ "54527ac44bdc2d36668b4567" ] }, + "544a5caa4bdc2d1a388b4568": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fad8c498d1b7e3e071da0", + "656fa25e94b480b8a500c0e0", + "656fa61e94b480b8a500c0e8", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656fb21fa0dce000a2020f7c", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fa76500d62bcd2e024080", + "656fafe3498d1b7e3e071da4", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fb0bd7c2d57afe200c0dc", + "656fac30c6baea13cd07e10c", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Groin": [ + "6570e90b3a5689d85f08db97" + ], + "Soft_armor_back": [ + "6570e87c23c1f638ef0b0ee2" + ], + "Soft_armor_front": [ + "6570e83223c1f638ef0b0ede" + ] + }, "55d355e64bdc2d962f8b4569": { "mod_barrel": [ "55d35ee94bdc2d61338b4568" @@ -2659,6 +2797,34 @@ "56def37dd2720bec348b456a" ] }, + "5645bc214bdc2d363b8b4571": { + "Helmet_back": [ + "657baeaacfcf63c951052db3" + ], + "Helmet_ears": [ + "657baecbc6f689d3a205b863" + ], + "Helmet_top": [ + "657bae18b7e9ca9a02045c0a" + ], + "mod_equipment": [ + "5b46238386f7741a693bcf9c" + ] + }, + "5648a7494bdc2d9d488b4583": { + "Soft_armor_back": [ + "65703fa06584602f7d057a8e" + ], + "Soft_armor_front": [ + "65703d866584602f7d057a8a" + ], + "Soft_armor_left": [ + "65703fe46a912c8b5c03468b" + ], + "soft_armor_right": [ + "657040374e67e8ec7a0d261c" + ] + }, "5649a2464bdc2d91118b45a8": { "mod_scope": [ "5a33b2c9c4a282000c5a9511" @@ -2778,17 +2944,18 @@ ] }, "587e02ff24597743df3deaeb": { + "mod_barrel": [ + "634eff66517ccc8a960fc735" + ], "mod_magazine": [ "587df3a12459772c28142567" ], "mod_mount": [ "587e08ee245977446b4410cf" ], - "mod_muzzle": [ - "5cf67cadd7f00c065a5abab7" - ], - "mod_sight_rear": [ - "574db213245977459a2f3f5d" + "mod_reciever": [ + "634f06262e5def262d0b30ca", + "634f05ca517ccc8a960fc748" ], "mod_stock": [ "5d0236dad7ad1a0940739d29" @@ -2862,6 +3029,14 @@ "59f99a7d86f7745b134aa97b" ] }, + "5a154d5cfcdbcb001a3b00da": { + "Helmet_back": [ + "657f8f10f4c82973640b2350" + ], + "Helmet_top": [ + "657f8ec5f4c82973640b234c" + ] + }, "5a17f98cfcdbcb0980087290": { "mod_magazine": [ "5a17fb03fcdbcbcae668728f" @@ -2970,6 +3145,31 @@ "5b30b0dc5acfc400153b7124" ] }, + "5aa7d193e5b5b000171d063f": { + "Helmet_back": [ + "657bb79ba1c61ee0c303631a" + ], + "Helmet_ears": [ + "657bb7d7b30eca9763051176" + ], + "Helmet_top": [ + "657bb70486c7f9ef7a009936" + ] + }, + "5aa7e4a4e5b5b000137b76f2": { + "Helmet_back": [ + "657f92acada5fadd1f07a57e" + ], + "Helmet_ears": [ + "657f92e7f4c82973640b2354" + ], + "Helmet_top": [ + "657f925dada5fadd1f07a57a" + ], + "mod_equipment": [ + "5aa7e3abe5b5b000171d064d" + ] + }, "5aaf8e43e5b5b00015693246": { "mod_mount": [ "5ab24ef9e5b5b00fe93c9209" @@ -3005,6 +3205,61 @@ "58dd3ad986f77403051cba8f" ] }, + "5ab8e79e86f7742d8b372e78": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Collar": [ + "657326bc5d3a3129fb05f36b" + ], + "Front_plate": [ + "656f611f94b480b8a500c0db", + "656f603f94b480b8a500c0d6", + "656f57dc27aed95beb08f628", + "656f63c027aed95beb08f62c" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "657326978c1cc6dcd9098b56" + ], + "Soft_armor_front": [ + "65732688d9d89ff7ac0d9c4c" + ], + "Soft_armor_left": [ + "657326a28c1cc6dcd9098b5a" + ], + "soft_armor_right": [ + "657326b08c1cc6dcd9098b5e" + ] + }, "5ac4cd105acfc40016339859": { "mod_charge": [ "5648ac824bdc2ded0b8b457d" @@ -3104,6 +3359,130 @@ "5b363dd25acfc4001a598fd2" ] }, + "5b40e1525acfc4771e1c6611": { + "Helmet_back": [ + "657112a4818110db4600aa66" + ], + "Helmet_ears": [ + "657112ce22996eaf110881fb" + ], + "Helmet_top": [ + "657112234269e9a568089eac" + ] + }, + "5b40e2bc5acfc40016388216": { + "Helmet_back": [ + "657112a4818110db4600aa66" + ], + "Helmet_ears": [ + "657112ce22996eaf110881fb" + ], + "Helmet_top": [ + "657112234269e9a568089eac" + ] + }, + "5b40e3f35acfc40016388218": { + "Helmet_back": [ + "657f9605f4c82973640b2358" + ], + "Helmet_top": [ + "657f95bff92cd718b701550c" + ] + }, + "5b40e4035acfc47a87740943": { + "Helmet_back": [ + "657f9605f4c82973640b2358" + ], + "Helmet_top": [ + "657f95bff92cd718b701550c" + ] + }, + "5b432d215acfc4771e1c6624": { + "Helmet_back": [ + "657bb99db30eca976305117f" + ], + "Helmet_top": [ + "657bb92fa1c61ee0c303631f" + ], + "mod_equipment_000": [ + "5a16badafcdbcb001865f72d", + "5a16b672fcdbcb001912fa83", + "5a16b7e1fcdbcb00165aa6c9" + ], + "mod_equipment_001": [ + "5a16b9fffcdbcb0176308b34" + ], + "mod_mount": [ + "5a398b75c4a282000a51a266", + "5a398ab9c4a282000c5a9842" + ], + "mod_nvg": [ + "5ea058e01dbce517f324b3e2", + "5c0558060db834001b735271", + "5a16b8a9fcdbcb00165aa6ca" + ] + }, + "5b44d22286f774172b0c9de8": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fafe3498d1b7e3e071da4", + "656fa0fb498d1b7e3e071d9c", + "656fa25e94b480b8a500c0e0", + "656fa76500d62bcd2e024080", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Collar": [ + "65705cea4916448ae1050897" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "64afdcb83efdfea28601d041", + "655746010177119f4a097ff7", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38" + ], + "Soft_armor_back": [ + "65705c3c14f2ed6d7d0b7738" + ], + "Soft_armor_front": [ + "65704de13e7bba58ea0285c8" + ], + "Soft_armor_left": [ + "65705c777260e1139e091408" + ], + "soft_armor_right": [ + "65705cb314f2ed6d7d0b773c" + ] + }, "5b7be4895acfc400170e2dd5": { "mod_foregrip": [ "58c157c886f774032749fb06", @@ -3143,6 +3522,241 @@ "588226dd24597767ad33f789" ] }, + "5c0e51be86f774598e797894": { + "Back_plate": [ + "656efaf54772930db4031ff5", + "656efd66034e8e01c407f35c", + "654a4a964b446df1ad03f192" + ], + "Collar": [ + "654a8ae00337d53f9102c2aa" + ], + "Front_plate": [ + "656f63c027aed95beb08f62c", + "656f57dc27aed95beb08f628", + "656f603f94b480b8a500c0d6", + "656f611f94b480b8a500c0db" + ], + "Groin": [ + "654a8bc5f414fcea4004d79b" + ], + "Soft_armor_back": [ + "654a8976f414fcea4004d78b" + ], + "Soft_armor_front": [ + "654a8b0b0337d53f9102c2ae" + ], + "Soft_armor_left": [ + "654a8b3df414fcea4004d78f" + ], + "soft_armor_right": [ + "654a8b80f414fcea4004d797" + ] + }, + "5c0e53c886f7747fa54205c7": { + "Collar": [ + "654a8ae00337d53f9102c2aa" + ], + "Groin": [ + "654a8bc5f414fcea4004d79b" + ], + "back_plate": [ + "654a4a964b446df1ad03f192", + "656efaf54772930db4031ff5", + "656efd66034e8e01c407f35c" + ], + "front_plate": [ + "656f603f94b480b8a500c0d6", + "656f611f94b480b8a500c0db", + "656f57dc27aed95beb08f628", + "656f63c027aed95beb08f62c" + ], + "soft_armor_back": [ + "654a8976f414fcea4004d78b" + ], + "soft_armor_front": [ + "654a8b0b0337d53f9102c2ae" + ], + "soft_armor_left": [ + "654a8b3df414fcea4004d78f" + ], + "soft_armor_right": [ + "654a8b80f414fcea4004d797" + ] + }, + "5c0e57ba86f7747fa141986d": { + "Back_plate": [ + "657b22485f444d6dff0c6c2f", + "657b2797c3dbcb01d60c35ea", + "657b28d25f444d6dff0c6c77" + ], + "Collar": [ + "657080ca12755ae0d907ad5e" + ], + "Front_plate": [ + "656f664200d62bcd2e024077", + "654a4dea7c17dec2f50cc86a", + "656f66b5c6baea13cd07e108", + "656f611f94b480b8a500c0db", + "656f603f94b480b8a500c0d6", + "656f57dc27aed95beb08f628", + "656f63c027aed95beb08f62c" + ], + "Groin": [ + "65708122f65e2491bf009755" + ], + "Groin_back": [ + "65708165696fe382cf073255" + ], + "Soft_armor_back": [ + "6570800612755ae0d907acf8" + ], + "Soft_armor_front": [ + "65707fc348c7a887f2010432" + ], + "Soft_armor_left": [ + "65708070f65e2491bf00972c" + ], + "soft_armor_right": [ + "657080a212755ae0d907ad04" + ] + }, + "5c0e5bab86f77461f55ed1f3": { + "Back_plate": [ + "657b22485f444d6dff0c6c2f", + "657b2797c3dbcb01d60c35ea", + "657b28d25f444d6dff0c6c77" + ], + "Collar": [ + "6571babb4076795e5e07383f" + ], + "Front_plate": [ + "656f664200d62bcd2e024077", + "654a4dea7c17dec2f50cc86a", + "656f66b5c6baea13cd07e108" + ], + "Groin": [ + "6571bac34076795e5e073843" + ], + "Groin_back": [ + "6571babf4cb80d995d0a1494" + ], + "Soft_armor_back": [ + "6571baa74cb80d995d0a1490" + ], + "Soft_armor_front": [ + "6571b27a6d84a2b8b6007f92" + ], + "Soft_armor_left": [ + "6571baac6d84a2b8b6007fa3" + ], + "soft_armor_right": [ + "6571bab0f41985531a038091" + ] + }, + "5c0e625a86f7742d77340f62": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa99800d62bcd2e024088", + "656fa8d700d62bcd2e024084", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fa76500d62bcd2e024080", + "656fafe3498d1b7e3e071da4", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fac30c6baea13cd07e10c", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656f9fa0498d1b7e3e071d98", + "656fb0bd7c2d57afe200c0dc", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38" + ], + "Collar": [ + "657643a220cc24d17102b14c" + ], + "Front_plate": [ + "656f611f94b480b8a500c0db", + "656f603f94b480b8a500c0d6", + "656f57dc27aed95beb08f628", + "656f63c027aed95beb08f62c" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "657642b0e6d5dd75f40688a5" + ], + "Soft_armor_front": [ + "65764275d8537eb26a0355e9" + ], + "Soft_armor_left": [ + "6576434820cc24d17102b148" + ], + "soft_armor_right": [ + "657643732bc38ef78e076477" + ] + }, + "5c0e655586f774045612eeb2": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656faf0ca0dce000a2020f77", + "656fae5f7c2d57afe200c0d7", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fa61e94b480b8a500c0e8", + "656fad8c498d1b7e3e071da0", + "656fac30c6baea13cd07e10c", + "656fb21fa0dce000a2020f7c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656fa8d700d62bcd2e024084", + "656f9d5900d62bcd2e02407c", + "656fa99800d62bcd2e024088", + "656fa0fb498d1b7e3e071d9c", + "656faf0ca0dce000a2020f77", + "656fae5f7c2d57afe200c0d7", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Soft_armor_back": [ + "6570e0610b57c03ec90b96ef" + ], + "Soft_armor_front": [ + "6570e025615f54368b04fcb0" + ] + }, "5c7954d52e221600106f4cc7": { "mod_muzzle": [ "5c7955c22e221644f31bfd5e" @@ -3153,6 +3767,83 @@ "61659f79d92c473c770213ee" ] }, + "5ca2151486f774244a3b8d30": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Collar": [ + "6575dd769d3a0ddf660b904b" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Groin": [ + "6575dd800546f8b1de093df6" + ], + "Groin_back": [ + "6575dd94945bf78edd04c43c" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "6575dd519e27f4a85e081146" + ], + "Soft_armor_front": [ + "6575dd3e9e27f4a85e081142" + ], + "Soft_armor_left": [ + "6575dd64945bf78edd04c438" + ], + "soft_armor_right": [ + "6575dd6e9d3a0ddf660b9047" + ] + }, "5cadc190ae921500103bb3b6": { "mod_barrel": [ "5cadc1c6ae9215000f2775a4" @@ -3351,6 +4042,19 @@ "5e81ee4dcb2b95385c177582" ] }, + "5ea17ca01412a1425304d1c0": { + "Helmet_back": [ + "657f9a94ada5fadd1f07a589" + ], + "Helmet_top": [ + "657f9a55c6679fefb3051e19" + ], + "mod_nvg": [ + "5ea18c84ecf1982c7712d9a2", + "5c0558060db834001b735271", + "5a16b8a9fcdbcb00165aa6ca" + ] + }, "5efaf417aeb21837e749c7f2": { "mod_foregrip": [ "5c1bc7432e221602b412949d" @@ -3407,6 +4111,29 @@ "5fb6564947ce63734e3fa1da" ] }, + "5f60b34a41e30a4ab12a6947": { + "Helmet_back": [ + "657bbb31b30eca9763051183" + ], + "Helmet_top": [ + "657bbad7a1c61ee0c3036323" + ], + "mod_equipment_000": [ + "5f60c076f2bcbb675b00dac2" + ], + "mod_equipment_002": [ + "5f60b85bbdb8e27dee3dc985" + ], + "mod_mount": [ + "5a398b75c4a282000a51a266", + "5a398ab9c4a282000c5a9842" + ], + "mod_nvg": [ + "5f60bf4558eff926626a60f2", + "5c0558060db834001b735271", + "5a16b8a9fcdbcb00165aa6ca" + ] + }, "5fb655b748c711690e3a8d5a": { "mod_stock_000": [ "5bb20e58d4351e00320205d7" @@ -3495,6 +4222,48 @@ "5d2369418abbc306c62e0c80" ] }, + "5fd4c474dd870108a754b241": { + "back_plate": [ + "64afdcb83efdfea28601d041", + "655746010177119f4a097ff7", + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4" + ], + "front_plate": [ + "64afdcb83efdfea28601d041", + "655746010177119f4a097ff7", + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4" + ] + }, "60228924961b8d75ee233c32": { "mod_sight_front": [ "60228a76d62c9b14ed777a66" @@ -3569,6 +4338,74 @@ "6086b5392535c57a13424d70" ] }, + "609e8540d5c319764c2bc2e9": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa25e94b480b8a500c0e0", + "656fa76500d62bcd2e024080", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041", + "65573fa5655447403702a816", + "64afc71497cf3a403c01ff38" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "6572e52f73c0eabb700109a0" + ], + "Soft_armor_front": [ + "6572e5221b5bc1185508c24f" + ], + "Soft_armor_left": [ + "6572e53c73c0eabb700109a4" + ], + "soft_armor_right": [ + "6572e54873c0eabb700109a8" + ] + }, "616554fe50224f204c1da2aa": { "mod_scope": [ "61657230d92c473c770213d7" @@ -3576,8 +4413,8 @@ }, "616584766ef05c2ce828ef57": { "mod_scope": [ - "5c7d55de2e221644f31bff68", - "5c7d560b2e22160bc12c6139" + "5c7d560b2e22160bc12c6139", + "5c7d55de2e221644f31bff68" ] }, "61816df1d3a39d50044c139e": { @@ -3673,6 +4510,157 @@ "6194f2df645b5d229654ad77" ] }, + "61bc85697113f767765c7fe7": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656faf0ca0dce000a2020f77", + "656fae5f7c2d57afe200c0d7", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa99800d62bcd2e024088", + "656fa8d700d62bcd2e024084", + "656faf0ca0dce000a2020f77", + "656fae5f7c2d57afe200c0d7", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "6572fc8c9a866b80ab07eb5d" + ], + "Soft_armor_front": [ + "6572fc809a866b80ab07eb59" + ], + "Soft_armor_left": [ + "6572fc989a866b80ab07eb61" + ], + "soft_armor_right": [ + "6572fca39a866b80ab07eb65" + ] + }, + "61bca7cda0eae612383adf57": { + "Helmet_back": [ + "657bbcffbbd440df880b2dd5" + ], + "Helmet_top": [ + "657bbcc9a1c61ee0c3036327" + ], + "mod_equipment_000": [ + "5a16b672fcdbcb001912fa83", + "5a16b7e1fcdbcb00165aa6c9" + ], + "mod_mount": [ + "5a398b75c4a282000a51a266", + "5a398ab9c4a282000c5a9842" + ], + "mod_nvg": [ + "5c0558060db834001b735271", + "5a16b8a9fcdbcb00165aa6ca" + ] + }, + "61bcc89aef0f505f0c6cd0fc": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fafe3498d1b7e3e071da4", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa76500d62bcd2e024080", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Groin": [ + "6572eb865b5eac12f10a03ee" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d", + "64afd81707e2cf40e903a316" + ], + "Soft_armor_back": [ + "6572eb1b04ee6483ef039882" + ], + "Soft_armor_front": [ + "6572eb0e55beba16bc04079f" + ], + "Soft_armor_left": [ + "6572eb3004ee6483ef039886" + ], + "soft_armor_right": [ + "6572eb3b04ee6483ef03988a" + ] + }, "622b379bf9cfc87d675d2de5": { "mod_gas_block": [ "622b327b267a1b13a44abea3" @@ -3885,6 +4873,61 @@ "5c7954d52e221600106f4cc7" ] }, + "634eff66517ccc8a960fc735": { + "mod_mount_000": [ + "634f05a21f9f536910079b56" + ], + "mod_muzzle": [ + "5cf67cadd7f00c065a5abab7" + ] + }, + "634f05a21f9f536910079b56": { + "mod_gas_block": [ + "634f036a517ccc8a960fc746" + ] + }, + "63737f448b28897f2802b874": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa25e94b480b8a500c0e0", + "656fa76500d62bcd2e024080", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fafe3498d1b7e3e071da4", + "656fa0fb498d1b7e3e071d9c", + "656fa76500d62bcd2e024080", + "656fad8c498d1b7e3e071da0", + "656fa25e94b480b8a500c0e0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ] + }, "637f57b78d137b27f70c496a": { "mod_foregrip": [ "5c87ca002e221600114cb150" @@ -3894,6 +4937,68 @@ "mod_scope": [ "616554fe50224f204c1da2aa" ] + }, + "639343fce101f4caa40a4ef3": { + "Back_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fae5f7c2d57afe200c0d7", + "656fa99800d62bcd2e024088", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Front_plate": [ + "656f9d5900d62bcd2e02407c", + "656fa8d700d62bcd2e024084", + "656fa99800d62bcd2e024088", + "656fae5f7c2d57afe200c0d7", + "656faf0ca0dce000a2020f77", + "656fa0fb498d1b7e3e071d9c", + "656fafe3498d1b7e3e071da4", + "656fa76500d62bcd2e024080", + "656fa25e94b480b8a500c0e0", + "656fad8c498d1b7e3e071da0", + "656fa61e94b480b8a500c0e8", + "656fb21fa0dce000a2020f7c", + "656fac30c6baea13cd07e10c", + "656fb0bd7c2d57afe200c0dc", + "656f9fa0498d1b7e3e071d98", + "656fa53d94b480b8a500c0e4", + "655746010177119f4a097ff7", + "64afdcb83efdfea28601d041" + ], + "Left_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d" + ], + "Right_side_plate": [ + "6557458f83942d705f0c4962", + "64afdb577bb3bfe8fe03fd1d" + ], + "Soft_armor_back": [ + "6573102b292ecadbfa09b38d" + ], + "Soft_armor_front": [ + "6573101e292ecadbfa09b389" + ], + "Soft_armor_left": [ + "65731038292ecadbfa09b391" + ], + "soft_armor_right": [ + "65731045f31d5be00e08a75a" + ] } } }, diff --git a/project/assets/database/bots/types/arenafighterevent.json b/project/assets/database/bots/types/arenafighterevent.json index 93f77a42..41ea7788 100644 --- a/project/assets/database/bots/types/arenafighterevent.json +++ b/project/assets/database/bots/types/arenafighterevent.json @@ -2110,12 +2110,36 @@ "2": 0 }, "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 10, + "1": 5, + "2": 1 + }, + "whitelist": [] }, "grenades": { "weights": { "0": 1, "1": 2, - "2": 1, + "2": 3, "3": 1, "4": 0, "5": 0 @@ -2143,8 +2167,8 @@ "pocketLoot": { "weights": { "0": 1, - "1": 6, - "2": 3, + "1": 4, + "2": 4, "3": 1, "4": 1 }, diff --git a/project/assets/database/bots/types/assault.json b/project/assets/database/bots/types/assault.json index 4a036cd9..c1d269d8 100644 --- a/project/assets/database/bots/types/assault.json +++ b/project/assets/database/bots/types/assault.json @@ -2343,6 +2343,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 30, @@ -2351,6 +2367,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 8, diff --git a/project/assets/database/bots/types/assaultgroup.json b/project/assets/database/bots/types/assaultgroup.json new file mode 100644 index 00000000..a907a431 --- /dev/null +++ b/project/assets/database/bots/types/assaultgroup.json @@ -0,0 +1,2263 @@ +{ + "appearance": { + "body": { + "619238266c614e6d15792bca": 1 + }, + "feet": { + "5f5e410c6bdad616ad46d60b": 1 + }, + "hands": { + "618cf9540a5a59657e5f5677": 1 + }, + "head": { + "5d28afe786f774292668618d": 1 + }, + "voice": { + "Scav_5": 1 + } + }, + "experience": { + "level": { + "min": 0, + "max": 1 + }, + "reward": { + "min": -1, + "max": -1 + }, + "standingForKill": -0.03, + "aggressorBonus": 0.01 + }, + "health": { + "Hydration": { + "min": 100, + "max": 100 + }, + "Energy": { + "min": 100, + "max": 100 + }, + "Temperature": { + "min": 36, + "max": 40 + }, + "BodyParts": [ + { + "Head": { + "min": 35, + "max": 35 + }, + "Chest": { + "min": 85, + "max": 85 + }, + "Stomach": { + "min": 70, + "max": 70 + }, + "LeftArm": { + "min": 60, + "max": 60 + }, + "RightArm": { + "min": 60, + "max": 60 + }, + "LeftLeg": { + "min": 65, + "max": 65 + }, + "RightLeg": { + "min": 65, + "max": 65 + } + } + ] + }, + "skills": { + "Common": {} + }, + "inventory": { + "equipment": { + "Headwear": { + "59e770f986f7742cbe3164ef": 1 + }, + "Earpiece": {}, + "FaceCover": { + "59e7715586f7742ee5789605": 1 + }, + "ArmorVest": {}, + "Eyewear": {}, + "ArmBand": {}, + "TacticalVest": { + "64be7110bf597ba84a0a41ea": 1 + }, + "Backpack": {}, + "FirstPrimaryWeapon": {}, + "SecondPrimaryWeapon": {}, + "Holster": { + "5448bd6b4bdc2dfc2f8b4569": 1 + }, + "Scabbard": { + "57e26fc7245977162a14b800": 1 + }, + "Pockets": { + "557ffd194bdc2d28148b457f": 1 + }, + "SecuredContainer": { + "5c0a794586f77461c458f892": 1 + } + }, + "Ammo": { + "Caliber9x18PM": { + "57371eb62459776125652ac1": 1 + } + }, + "mods": { + "5448bd6b4bdc2dfc2f8b4569": { + "mod_reciever": [ + "6374a822e629013b9c0645c8" + ], + "mod_pistolgrip": [ + "6374a7e7417239a7bf00f042" + ], + "mod_magazine": [ + "5448c12b4bdc2d02308b456f" + ], + "patron_in_weapon": [ + "57371eb62459776125652ac1" + ] + } + }, + "items": { + "TacticalVest": { + "5448c12b4bdc2d02308b456f": 1 + }, + "Pockets": { + "544fb37f4bdc2dee738b4567": 1 + }, + "Backpack": {}, + "SecuredContainer": { + "57371eb62459776125652ac1": 1 + }, + "SpecialLoot": {} + } + }, + "firstName": [ + "Гоша" + ], + "lastName": [ + "Статтеринг" + ], + "difficulty": { + "easy": { + "Lay": { + "CHECK_SHOOT_WHEN_LAYING": false, + "DELTA_LAY_CHECK": 2, + "DELTA_GETUP": 5, + "DELTA_AFTER_GETUP": 10, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "MAX_LAY_TIME": 35, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "ATTACK_LAY_CHANCE": 25, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "LAY_AIM": 0.6, + "MIN_CAN_LAY_DIST_SQRT": 121, + "MIN_CAN_LAY_DIST": 11, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_CAN_LAY_DIST": 200, + "LAY_CHANCE_DANGER": 40, + "DAMAGE_TIME_TO_GETUP": 3 + }, + "Aiming": { + "MAX_AIM_PRECICING": 3, + "BETTER_PRECICING_COEF": 0.7, + "RECALC_DIST": 0.7, + "RECALC_SQR_DIST": 0.48999998, + "COEF_FROM_COVER": 0.8, + "PANIC_COEF": 1.2, + "PANIC_ACCURATY_COEF": 1.2, + "HARD_AIM": 0.75, + "HARD_AIM_CHANCE_100": 10, + "PANIC_TIME": 2, + "RECALC_MUST_TIME": 3, + "DAMAGE_PANIC_TIME": 15, + "DANGER_UP_POINT": 1.3, + "MAX_AIMING_UPGRADE_BY_TIME": 0.85, + "DAMAGE_TO_DISCARD_AIM_0_100": 100, + "MIN_TIME_DISCARD_AIM_SEC": 2.9, + "MAX_TIME_DISCARD_AIM_SEC": 3.2, + "XZ_COEF": 0.75, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "BOTTOM_COEF": 0.3, + "FIRST_CONTACT_ADD_SEC": 0.1, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "BASE_HIT_AFFECTION_DELAY_SEC": 1.77, + "BASE_HIT_AFFECTION_MIN_ANG": 14, + "BASE_HIT_AFFECTION_MAX_ANG": 28, + "BASE_SHIEF": 1, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SCATTERING_DIST_MODIF": 0.7, + "SCATTERING_DIST_MODIF_CLOSE": 0.85, + "AIMING_TYPE": 5, + "DIST_TO_SHOOT_TO_CENTER": 3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "SHPERE_FRIENDY_FIRE_SIZE": -1, + "COEF_IF_MOVE": 1.7, + "TIME_COEF_IF_MOVE": 1.5, + "BOT_MOVE_IF_DELTA": 0.01, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 30, + "WEAPON_ROOT_OFFSET": 0.35, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MAX_AIM_TIME": 1.5, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "Y_TOP_OFFSET_COEF": 0.001, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "XZ_COEF_STATIONARY_GRENADE": 0.8 + }, + "Look": { + "OLD_TIME_POINT": 11, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8, + "LOOK_AROUND_DELTA": 1.1, + "MAX_VISION_GRASS_METERS": 0.4, + "MAX_VISION_GRASS_METERS_FLARE": 7, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "LightOnVisionDistance": 30, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "MIDDLE_DIST": 90, + "MiddleDeltaTimeSec": 1, + "CloseDeltaTimeSec": 0.1, + "POSIBLE_VISION_SPACE": 1.2, + "GOAL_TO_FULL_DISSAPEAR": 0.25, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.0001, + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "COME_TO_BODY_DIST": 1.2, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "VISIBLE_DISNACE_WITH_LIGHT": 43, + "ENEMY_LIGHT_ADD": 45, + "ANGLE_FOR_GETUP": 30, + "ENEMY_LIGHT_START_DIST": 40, + "CAN_LOOK_TO_WALL": false, + "CHECK_HEAD_ANY_DIST": false, + "DIST_NOT_TO_IGNORE_WALL": 15, + "DIST_CHECK_WALL": 20, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "MIN_LOOK_AROUD_TIME": 20, + "OPTIMIZE_TO_ONLY_BODY": true + }, + "Shoot": { + "RECOIL_TIME_NORMALIZE": 2, + "RECOIL_PER_METER": 0.1, + "CAN_STOP_SHOOT_CAUSE_ANIMATOR": true, + "MAX_RECOIL_PER_METER": 0.2, + "HORIZONT_RECOIL_COEF": 0.4, + "WAIT_NEXT_SINGLE_SHOT": 0.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.8, + "MARKSMAN_DIST_SEK_COEF": 44, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "BASE_AUTOMATIC_TIME": 0.1, + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 76, + "FAR_DIST_ENEMY": 20, + "SHOOT_FROM_COVER": 4, + "FAR_DIST_ENEMY_SQR": 400, + "MAX_DIST_COEF": 1.35, + "RECOIL_DELTA_PRESS": 0.15, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "CAN_SHOOTS_TIME_TO_AMBUSH": 333, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "CHANCE_TO_CHANGE_WEAPON": 0, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 0, + "LOW_DIST_TO_CHANGE_WEAPON": 10, + "FAR_DIST_TO_CHANGE_WEAPON": 50, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "WAIT_NEXT_STATIONARY_GRENADE": 1, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "VALIDATE_MALFUNCTION_CHANCE": 100, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 + }, + "Move": { + "BASE_ROTATE_SPEED": 270, + "REACH_DIST": 0.5, + "REACH_DIST_RUN": 0.8, + "START_SLOW_DIST": 1.5, + "BASESTART_SLOW_DIST": 1.1, + "SLOW_COEF": 7, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_START_RAYCAST": 15, + "BASE_START_SERACH": 35, + "UPDATE_TIME_RECAL_WAY": 7, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST_SQR": 225, + "BASE_SQRT_START_SERACH": 1225, + "Y_APPROXIMATION": 0.7, + "DELTA_LAST_SEEN_ENEMY": 20, + "REACH_DIST_COVER": 2, + "RUN_TO_COVER_MIN": 2, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "SEC_TO_CHANGE_TO_RUN": 3 + }, + "Grenade": { + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "DELTA_NEXT_ATTEMPT": 10, + "MIN_DIST_NOT_TO_THROW": 8, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 99, + "GrenadePerMeter": 0.2, + "REQUEST_DIST_MUST_THROW_SQRT": 4, + "REQUEST_DIST_MUST_THROW": 2, + "BEWARE_TYPE": 2, + "SHOOT_TO_SMOKE_CHANCE_100": 30, + "CHANCE_RUN_FLASHED_100": 0, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "FLASH_GRENADE_TIME_COEF": 0.3, + "SIZE_SPOTTED_COEF": 2, + "BE_ATTENTION_COEF": 4, + "TIME_SHOOT_TO_FLASH": 4, + "CLOSE_TO_SMOKE_TO_SHOOT": 5, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 25, + "CLOSE_TO_SMOKE_TIME_DELTA": 7, + "SMOKE_CHECK_DELTA": 1, + "DELTA_GRENADE_START_TIME": 0.7, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "NO_RUN_FROM_AI_GRENADES": false, + "MAX_THROW_POWER": 15.7, + "GrenadePrecision": 0.3, + "STOP_WHEN_THROW_GRENADE": true, + "WAIT_TIME_TURN_AWAY": 0.2, + "SMOKE_SUPPRESS_DELTA": 20, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "STUN_SUPPRESS_DELTA": 9, + "CHEAT_START_GRENADE_PLACE": false, + "CAN_THROW_STRAIGHT_CONTACT": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "ANG_TYPE": 4 + }, + "Change": { + "SMOKE_VISION_DIST": 0.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_ACCURATY": 1.6, + "SMOKE_LAY_CHANCE": 1.6, + "FLASH_VISION_DIST": 0.05, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_SCATTERING": 1.6, + "FLASH_PRECICING": 1.6, + "FLASH_HEARING": 1, + "FLASH_ACCURATY": 1.6, + "FLASH_LAY_CHANCE": 1, + "STUN_HEARING": 0.01 + }, + "Cover": { + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "SOUND_TO_GET_SPOTTED": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "MAX_DIST_OF_COVER": 4, + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "MIN_DIST_TO_ENEMY": 9, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CHECK_SFETY": 9, + "TIME_CHECK_SAFE": 2, + "HIDE_TO_COVER_TIME": 1.5, + "MAX_DIST_OF_COVER_SQR": 16, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "SPOTTED_COVERS_RADIUS": 3, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "SPOTTED_GRENADE_RADIUS": 16, + "MAX_SPOTTED_TIME_SEC": 45, + "WAIT_INT_COVER_FINDING_ENEMY": 2, + "CLOSE_DIST_POINT_SQRT": 4, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "MOVE_TO_COVER_WHEN_TARGET": false, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "SPOTTED_GRENADE_TIME": 7, + "DEPENDS_Y_DIST_TO_BOT": false, + "RUN_IF_FAR": 10, + "RUN_IF_FAR_SQRT": 225, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "CHECK_COVER_ENEMY_LOOK": true, + "SHOOT_NEAR_TO_LEAVE": 2, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "DOG_FIGHT_AFTER_LEAVE": 4, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "MIN_DEFENCE_LEVEL": 22, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "ENEMY_DIST_TO_GO_OUT": 1, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 20, + "STATIONARY_WEAPON_MAX_DIST_TO_USE": 25 + }, + "Patrol": { + "DEAD_BODY_LOOK_PERIOD": 8, + "LOOK_TIME_BASE": 12, + "CAN_CHOOSE_RESERV": false, + "DO_RANDOM_DROP_ITEM": true, + "TRY_CHOOSE_RESERV_WAY_ON_START": false, + "CAN_LOOK_TO_DEADBODIES": true, + "CAN_FRIENDLY_TILT": true, + "CAN_HARD_AIM": true, + "RESERVE_TIME_STAY": 72, + "FRIEND_SEARCH_SEC": 12, + "TALK_DELAY": 1.1, + "MIN_TALK_DELAY": 35, + "TALK_DELAY_BIG": 15.1, + "CHANGE_WAY_TIME": 125.1, + "MIN_DIST_TO_CLOSE_TALK": 5, + "VISION_DIST_COEF_PEACE": 0.5, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CUT_WAY_MIN_0_1": 0.4, + "CUT_WAY_MAX_0_1": 0.65, + "CHANCE_TO_CHANGE_WAY_0_100": 50, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "SUSPETION_PLACE_LIFETIME": 7, + "RESERVE_OUT_TIME": 30, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "CAN_WATCH_SECOND_WEAPON": true + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 2, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.45, + "DISPERSION_COEF": 1.6, + "CLOSE_DIST": 10, + "FAR_DIST": 30, + "SOUND_DIR_DEEFREE": 30, + "DIST_PLACE_TO_FIND_POINT": 70, + "DEAD_BODY_SOUND_RAD": 30, + "LOOK_ONLY_DANGER": false, + "RESET_TIMER_DIST": 17, + "HEAR_DELAY_WHEN_PEACE": 0.85, + "HEAR_DELAY_WHEN_HAVE_SMT": 0.56, + "LOOK_ONLY_DANGER_DELTA": 9 + }, + "Mind": { + "HOW_WORK_OVER_DEAD_BODY": 2, + "MIN_SHOOTS_TIME": 2, + "MAX_SHOOTS_TIME": 4, + "TIME_LEAVE_MAP": 23, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "MIN_DAMAGE_SCARE": 20, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_FIND_ENEMY": 22, + "MAX_AGGRO_BOT_DIST": 100, + "HIT_POINT_DETECTION": 4, + "DANGER_POINT_CHOOSE_COEF": 1, + "FOLLOWER_AND_BOSS_WARN_EQUAL_PRIORITY": true, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "COVER_DIST_COEF": 1.5, + "DIST_TO_FOUND_SQRT": 400, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "DIST_TO_STOP_RUN_ENEMY": 15, + "ENEMY_LOOK_AT_ME_ANG": 15, + "MIN_START_AGGRESION_COEF": 1, + "MAX_START_AGGRESION_COEF": 3, + "BULLET_FEEL_DIST": 360, + "BULLET_FEEL_CLOSE_SDIST": 1, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 10, + "FRIEND_DEAD_AGR_LOW": -0.2, + "FRIEND_AGR_KILL": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "SURGE_KIT_ONLY_SAFE_CONTAINER": false, + "CHECK_MARK_OF_UNKNOWS": true, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": true, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_TAKE_ITEMS": true, + "CAN_USE_MEDS": true, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "PROTECT_TIME_REAL": true, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CAN_PANIC_IS_PROTECT": false, + "NO_RUN_AWAY_FOR_SAFE": false, + "PART_PERCENT_TO_HEAL": 0.65, + "PROTECT_DELTA_HEAL_SEC": 10, + "CAN_STAND_BY": true, + "CAN_THROW_REQUESTS": true, + "GROUP_ANY_PHRASE_DELAY": 1, + "GROUP_EXACTLY_PHRASE_DELAY": 24, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "DOG_FIGHT_OUT": 6, + "DOG_FIGHT_IN": 3, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "PISTOL_SHOTGUN_AMBUSH_DIST": 60, + "STANDART_AMBUSH_DIST": 200, + "AI_POWER_COEF": 120, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "TALK_WITH_QUERY": true, + "WILL_PERSUE_AXEMAN": true, + "MAY_BE_CALLED_FOR_HELP": true + }, + "Boss": { + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "CHANCE_TO_SEND_GRENADE_100": 100, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "PERSONS_SEND": 2, + "DELTA_SEARCH_TIME": 18, + "COVER_TO_SEND": true, + "WAIT_NO_ATTACK_SAVAGE": 10, + "CHANCE_USE_RESERVE_PATROL_100": 50, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 45, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_CONTUTION_TIME": 5, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_MIDDLE_ATTACK_DIST": 22, + "KILLA_LARGE_ATTACK_DIST": 41, + "KILLA_SEARCH_METERS": 30, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_HOLD_DELAY": 5, + "KILLA_BULLET_TO_RELOAD": 15, + "SHALL_WARN": true, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_ONE_IS_CLOSE": 30, + "KILLA_TRIGGER_DOWN_DELAY": 1, + "KILLA_WAIT_IN_COVER_COEF": 1 + }, + "Core": { + "VisibleAngle": 130, + "VisibleDistance": 110, + "GainSightCoef": 0.2, + "ScatteringPerMeter": 0.07, + "ScatteringClosePerMeter": 0.12, + "DamageCoeff": 1, + "HearingSense": 1.05, + "CanRun": true, + "CanGrenade": true, + "AimingType": "normal", + "PistolFireDistancePref": 35, + "ShotgunFireDistancePref": 50, + "RifleFireDistancePref": 100, + "AccuratySpeed": 0.3, + "WaitInCoverBetweenShotsSec": 1.5 + }, + "Scattering": { + "MinScatter": 0.015, + "WorkingScatter": 0.15, + "MaxScatter": 0.3, + "SpeedUp": 0.6, + "SpeedUpAim": 1.8, + "SpeedDown": -0.2, + "ToSlowBotSpeed": 1.8, + "ToLowBotSpeed": 2.8, + "ToUpBotSpeed": 4.3, + "MovingSlowCoef": 1.4, + "ToLowBotAngularSpeed": 140, + "ToStopBotAngularSpeed": 80, + "FromShot": 0.001, + "TracerCoef": 1.3, + "HandDamageScatteringMinMax": 0.7, + "HandDamageAccuracySpeed": 1.3, + "BloodFall": 1.45, + "Caution": 0.03, + "ToCaution": 0.6, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "AMPLITUDE_FACTOR": 0.015, + "AMPLITUDE_SPEED": 0.001, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "PoseChnageCoef": 0.1, + "LayFactor": 0.1, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1 + } + }, + "normal": { + "Lay": { + "CHECK_SHOOT_WHEN_LAYING": false, + "DELTA_LAY_CHECK": 2, + "DELTA_GETUP": 5, + "DELTA_AFTER_GETUP": 10, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "MAX_LAY_TIME": 35, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "ATTACK_LAY_CHANCE": 25, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "LAY_AIM": 0.6, + "MIN_CAN_LAY_DIST_SQRT": 121, + "MIN_CAN_LAY_DIST": 11, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_CAN_LAY_DIST": 200, + "LAY_CHANCE_DANGER": 40, + "DAMAGE_TIME_TO_GETUP": 3 + }, + "Aiming": { + "MAX_AIM_PRECICING": 2, + "BETTER_PRECICING_COEF": 0.8, + "RECALC_DIST": 0.7, + "RECALC_SQR_DIST": 0.48999998, + "COEF_FROM_COVER": 0.75, + "PANIC_COEF": 1.2, + "PANIC_ACCURATY_COEF": 1.2, + "HARD_AIM": 0.75, + "HARD_AIM_CHANCE_100": 50, + "PANIC_TIME": 2, + "RECALC_MUST_TIME": 3, + "DAMAGE_PANIC_TIME": 15, + "DANGER_UP_POINT": 1.3, + "MAX_AIMING_UPGRADE_BY_TIME": 0.85, + "DAMAGE_TO_DISCARD_AIM_0_100": 96, + "MIN_TIME_DISCARD_AIM_SEC": 2.3, + "MAX_TIME_DISCARD_AIM_SEC": 3.1, + "XZ_COEF": 0.65, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "BOTTOM_COEF": 0.25, + "FIRST_CONTACT_ADD_SEC": 0.05, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "BASE_HIT_AFFECTION_DELAY_SEC": 1.17, + "BASE_HIT_AFFECTION_MIN_ANG": 14, + "BASE_HIT_AFFECTION_MAX_ANG": 24, + "BASE_SHIEF": 0.8, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SCATTERING_DIST_MODIF": 0.7, + "SCATTERING_DIST_MODIF_CLOSE": 0.82, + "AIMING_TYPE": 5, + "DIST_TO_SHOOT_TO_CENTER": 3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "SHPERE_FRIENDY_FIRE_SIZE": -1, + "COEF_IF_MOVE": 1.6, + "TIME_COEF_IF_MOVE": 1.5, + "BOT_MOVE_IF_DELTA": 0.01, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 30, + "WEAPON_ROOT_OFFSET": 0.35, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MAX_AIM_TIME": 1.5, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "Y_TOP_OFFSET_COEF": 0.001, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "XZ_COEF_STATIONARY_GRENADE": 0.8 + }, + "Look": { + "OLD_TIME_POINT": 11, + "WAIT_NEW_SENSOR": 2.1, + "ANGLE_FOR_GETUP": 30, + "WAIT_NEW__LOOK_SENSOR": 7.8, + "LOOK_AROUND_DELTA": 1.1, + "MAX_VISION_GRASS_METERS": 0.4, + "MAX_VISION_GRASS_METERS_FLARE": 7, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "LightOnVisionDistance": 30, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "MIDDLE_DIST": 90, + "MiddleDeltaTimeSec": 1, + "CloseDeltaTimeSec": 0.1, + "POSIBLE_VISION_SPACE": 1.2, + "GOAL_TO_FULL_DISSAPEAR": 0.25, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.0001, + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "COME_TO_BODY_DIST": 1.2, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "VISIBLE_DISNACE_WITH_LIGHT": 43, + "ENEMY_LIGHT_ADD": 45, + "ENEMY_LIGHT_START_DIST": 40, + "CAN_LOOK_TO_WALL": false, + "CHECK_HEAD_ANY_DIST": false, + "DIST_NOT_TO_IGNORE_WALL": 15, + "DIST_CHECK_WALL": 20, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "MIN_LOOK_AROUD_TIME": 20, + "OPTIMIZE_TO_ONLY_BODY": true + }, + "Shoot": { + "RECOIL_TIME_NORMALIZE": 2, + "CAN_STOP_SHOOT_CAUSE_ANIMATOR": true, + "RECOIL_PER_METER": 0.1, + "MAX_RECOIL_PER_METER": 0.2, + "HORIZONT_RECOIL_COEF": 0.4, + "WAIT_NEXT_SINGLE_SHOT": 0.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.8, + "MARKSMAN_DIST_SEK_COEF": 44, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "BASE_AUTOMATIC_TIME": 0.1, + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 76, + "FAR_DIST_ENEMY": 20, + "SHOOT_FROM_COVER": 4, + "FAR_DIST_ENEMY_SQR": 400, + "MAX_DIST_COEF": 1.35, + "RECOIL_DELTA_PRESS": 0.15, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "CAN_SHOOTS_TIME_TO_AMBUSH": 333, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "CHANCE_TO_CHANGE_WEAPON": 0, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 0, + "LOW_DIST_TO_CHANGE_WEAPON": 10, + "FAR_DIST_TO_CHANGE_WEAPON": 50, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "WAIT_NEXT_STATIONARY_GRENADE": 1, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "VALIDATE_MALFUNCTION_CHANCE": 100, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 + }, + "Move": { + "BASE_ROTATE_SPEED": 270, + "REACH_DIST": 0.5, + "REACH_DIST_RUN": 0.8, + "START_SLOW_DIST": 1.5, + "BASESTART_SLOW_DIST": 1.1, + "SLOW_COEF": 7, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_START_RAYCAST": 15, + "BASE_START_SERACH": 35, + "UPDATE_TIME_RECAL_WAY": 7, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST_SQR": 225, + "BASE_SQRT_START_SERACH": 1225, + "Y_APPROXIMATION": 0.7, + "DELTA_LAST_SEEN_ENEMY": 20, + "REACH_DIST_COVER": 2, + "RUN_TO_COVER_MIN": 2, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "SEC_TO_CHANGE_TO_RUN": 3 + }, + "Grenade": { + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "DELTA_NEXT_ATTEMPT": 10, + "MIN_DIST_NOT_TO_THROW": 8, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 99, + "GrenadePerMeter": 0.15, + "REQUEST_DIST_MUST_THROW_SQRT": 4, + "REQUEST_DIST_MUST_THROW": 2, + "BEWARE_TYPE": 2, + "SHOOT_TO_SMOKE_CHANCE_100": 30, + "CHANCE_RUN_FLASHED_100": 0, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "FLASH_GRENADE_TIME_COEF": 0.3, + "SIZE_SPOTTED_COEF": 2, + "BE_ATTENTION_COEF": 4, + "TIME_SHOOT_TO_FLASH": 4, + "CLOSE_TO_SMOKE_TO_SHOOT": 5, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 25, + "CLOSE_TO_SMOKE_TIME_DELTA": 7, + "SMOKE_CHECK_DELTA": 1, + "DELTA_GRENADE_START_TIME": 0.7, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "NO_RUN_FROM_AI_GRENADES": false, + "MAX_THROW_POWER": 16.7, + "GrenadePrecision": 0.2, + "STOP_WHEN_THROW_GRENADE": true, + "WAIT_TIME_TURN_AWAY": 0.2, + "SMOKE_SUPPRESS_DELTA": 20, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "STUN_SUPPRESS_DELTA": 9, + "CHEAT_START_GRENADE_PLACE": false, + "CAN_THROW_STRAIGHT_CONTACT": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "ANG_TYPE": 4 + }, + "Change": { + "SMOKE_VISION_DIST": 0.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_ACCURATY": 1.6, + "SMOKE_LAY_CHANCE": 1.6, + "FLASH_VISION_DIST": 0.05, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_SCATTERING": 1.6, + "FLASH_PRECICING": 1.6, + "FLASH_HEARING": 1, + "FLASH_ACCURATY": 1.6, + "FLASH_LAY_CHANCE": 1, + "STUN_HEARING": 0.01 + }, + "Cover": { + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "SOUND_TO_GET_SPOTTED": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "MAX_DIST_OF_COVER": 4, + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "MIN_DIST_TO_ENEMY": 9, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CHECK_SFETY": 9, + "TIME_CHECK_SAFE": 2, + "HIDE_TO_COVER_TIME": 1.5, + "MAX_DIST_OF_COVER_SQR": 16, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "SPOTTED_COVERS_RADIUS": 3, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "SPOTTED_GRENADE_RADIUS": 16, + "MAX_SPOTTED_TIME_SEC": 45, + "WAIT_INT_COVER_FINDING_ENEMY": 2, + "CLOSE_DIST_POINT_SQRT": 4, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "MOVE_TO_COVER_WHEN_TARGET": false, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "SPOTTED_GRENADE_TIME": 7, + "DEPENDS_Y_DIST_TO_BOT": false, + "RUN_IF_FAR": 7, + "RUN_IF_FAR_SQRT": 225, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "CHECK_COVER_ENEMY_LOOK": true, + "SHOOT_NEAR_TO_LEAVE": 2, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "DOG_FIGHT_AFTER_LEAVE": 4, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "MIN_DEFENCE_LEVEL": 22, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "ENEMY_DIST_TO_GO_OUT": 1, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 20, + "STATIONARY_WEAPON_MAX_DIST_TO_USE": 25 + }, + "Patrol": { + "DEAD_BODY_LOOK_PERIOD": 8, + "LOOK_TIME_BASE": 12, + "CAN_FRIENDLY_TILT": true, + "CAN_HARD_AIM": true, + "CAN_CHOOSE_RESERV": false, + "DO_RANDOM_DROP_ITEM": true, + "TRY_CHOOSE_RESERV_WAY_ON_START": false, + "CAN_LOOK_TO_DEADBODIES": true, + "RESERVE_TIME_STAY": 72, + "FRIEND_SEARCH_SEC": 12, + "TALK_DELAY": 1.1, + "MIN_TALK_DELAY": 35, + "TALK_DELAY_BIG": 15.1, + "CHANGE_WAY_TIME": 125.1, + "MIN_DIST_TO_CLOSE_TALK": 5, + "VISION_DIST_COEF_PEACE": 0.75, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CUT_WAY_MIN_0_1": 0.4, + "CUT_WAY_MAX_0_1": 0.65, + "CHANCE_TO_CHANGE_WAY_0_100": 50, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "SUSPETION_PLACE_LIFETIME": 7, + "RESERVE_OUT_TIME": 30, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "CAN_WATCH_SECOND_WEAPON": true + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 2, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.65, + "DISPERSION_COEF": 2.6, + "CLOSE_DIST": 10, + "FAR_DIST": 30, + "SOUND_DIR_DEEFREE": 30, + "DIST_PLACE_TO_FIND_POINT": 70, + "DEAD_BODY_SOUND_RAD": 30, + "LOOK_ONLY_DANGER": false, + "RESET_TIMER_DIST": 17, + "HEAR_DELAY_WHEN_PEACE": 0.75, + "HEAR_DELAY_WHEN_HAVE_SMT": 0.5, + "LOOK_ONLY_DANGER_DELTA": 9 + }, + "Mind": { + "HOW_WORK_OVER_DEAD_BODY": 2, + "MIN_SHOOTS_TIME": 2, + "MAX_SHOOTS_TIME": 4, + "TIME_LEAVE_MAP": 23, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "MIN_DAMAGE_SCARE": 20, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_FIND_ENEMY": 22, + "MAX_AGGRO_BOT_DIST": 100, + "HIT_POINT_DETECTION": 4, + "DANGER_POINT_CHOOSE_COEF": 1, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "COVER_DIST_COEF": 1.5, + "DIST_TO_FOUND_SQRT": 400, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "FOLLOWER_AND_BOSS_WARN_EQUAL_PRIORITY": true, + "CHECK_MARK_OF_UNKNOWS": true, + "DIST_TO_STOP_RUN_ENEMY": 15, + "ENEMY_LOOK_AT_ME_ANG": 15, + "MIN_START_AGGRESION_COEF": 1, + "MAX_START_AGGRESION_COEF": 3, + "CAN_TAKE_ITEMS": true, + "BULLET_FEEL_DIST": 360, + "BULLET_FEEL_CLOSE_SDIST": 1, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 10, + "FRIEND_DEAD_AGR_LOW": -0.2, + "FRIEND_AGR_KILL": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "SURGE_KIT_ONLY_SAFE_CONTAINER": false, + "CAN_RECIVE_PLAYER_REQUESTS": true, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": true, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "DEFAULT_ENEMY_SAVAGE": true, + "WARN_BOT_TYPES": [], + "ENEMY_BOT_TYPES": [], + "CAN_USE_MEDS": true, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "PROTECT_TIME_REAL": true, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CAN_PANIC_IS_PROTECT": false, + "NO_RUN_AWAY_FOR_SAFE": false, + "PART_PERCENT_TO_HEAL": 0.65, + "PROTECT_DELTA_HEAL_SEC": 10, + "CAN_STAND_BY": true, + "CAN_THROW_REQUESTS": true, + "GROUP_ANY_PHRASE_DELAY": 1, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "DOG_FIGHT_OUT": 6, + "DOG_FIGHT_IN": 3, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "PISTOL_SHOTGUN_AMBUSH_DIST": 60, + "STANDART_AMBUSH_DIST": 200, + "AI_POWER_COEF": 120, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "TALK_WITH_QUERY": true, + "WILL_PERSUE_AXEMAN": true, + "MAY_BE_CALLED_FOR_HELP": true + }, + "Boss": { + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "CHANCE_TO_SEND_GRENADE_100": 100, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "PERSONS_SEND": 2, + "DELTA_SEARCH_TIME": 18, + "COVER_TO_SEND": true, + "WAIT_NO_ATTACK_SAVAGE": 10, + "CHANCE_USE_RESERVE_PATROL_100": 50, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 45, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_CONTUTION_TIME": 5, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_MIDDLE_ATTACK_DIST": 22, + "KILLA_LARGE_ATTACK_DIST": 41, + "KILLA_SEARCH_METERS": 30, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_HOLD_DELAY": 5, + "KILLA_BULLET_TO_RELOAD": 15, + "SHALL_WARN": true, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_ONE_IS_CLOSE": 30, + "KILLA_TRIGGER_DOWN_DELAY": 1, + "KILLA_WAIT_IN_COVER_COEF": 1 + }, + "Core": { + "VisibleAngle": 130, + "VisibleDistance": 120, + "GainSightCoef": 0.2, + "ScatteringPerMeter": 0.05, + "ScatteringClosePerMeter": 0.1, + "DamageCoeff": 1, + "HearingSense": 1.85, + "CanRun": true, + "CanGrenade": true, + "AimingType": "normal", + "PistolFireDistancePref": 35, + "ShotgunFireDistancePref": 50, + "RifleFireDistancePref": 100, + "AccuratySpeed": 0.3, + "WaitInCoverBetweenShotsSec": 1.5 + }, + "Scattering": { + "MinScatter": 0.015, + "WorkingScatter": 0.15, + "MaxScatter": 0.3, + "SpeedUp": 0.6, + "SpeedUpAim": 1.8, + "SpeedDown": -0.2, + "ToSlowBotSpeed": 1.8, + "ToLowBotSpeed": 2.8, + "ToUpBotSpeed": 4.3, + "MovingSlowCoef": 1.4, + "ToLowBotAngularSpeed": 140, + "ToStopBotAngularSpeed": 80, + "FromShot": 0.001, + "TracerCoef": 1.3, + "HandDamageScatteringMinMax": 0.7, + "HandDamageAccuracySpeed": 1.3, + "BloodFall": 1.45, + "Caution": 0.03, + "ToCaution": 0.6, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "AMPLITUDE_FACTOR": 0.015, + "AMPLITUDE_SPEED": 0.001, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "PoseChnageCoef": 0.1, + "LayFactor": 0.1, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1 + } + }, + "hard": { + "Lay": { + "CHECK_SHOOT_WHEN_LAYING": false, + "DELTA_LAY_CHECK": 2, + "DELTA_GETUP": 5, + "DELTA_AFTER_GETUP": 10, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "MAX_LAY_TIME": 35, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "ATTACK_LAY_CHANCE": 25, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "LAY_AIM": 0.6, + "MIN_CAN_LAY_DIST_SQRT": 121, + "MIN_CAN_LAY_DIST": 11, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_CAN_LAY_DIST": 200, + "LAY_CHANCE_DANGER": 40, + "DAMAGE_TIME_TO_GETUP": 3 + }, + "Aiming": { + "MAX_AIM_PRECICING": 2, + "BETTER_PRECICING_COEF": 0.8, + "RECALC_DIST": 0.7, + "RECALC_SQR_DIST": 0.48999998, + "COEF_FROM_COVER": 0.65, + "PANIC_COEF": 1.2, + "PANIC_ACCURATY_COEF": 1.2, + "HARD_AIM": 0.75, + "HARD_AIM_CHANCE_100": 80, + "PANIC_TIME": 2, + "RECALC_MUST_TIME": 3, + "DAMAGE_PANIC_TIME": 15, + "DANGER_UP_POINT": 1.3, + "MAX_AIMING_UPGRADE_BY_TIME": 0.85, + "DAMAGE_TO_DISCARD_AIM_0_100": 96, + "MIN_TIME_DISCARD_AIM_SEC": 2.3, + "MAX_TIME_DISCARD_AIM_SEC": 2.6, + "XZ_COEF": 0.65, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "BOTTOM_COEF": 0.2, + "FIRST_CONTACT_ADD_SEC": 0.05, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.27, + "BASE_HIT_AFFECTION_MIN_ANG": 14, + "BASE_HIT_AFFECTION_MAX_ANG": 18, + "BASE_SHIEF": 0.5, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SCATTERING_DIST_MODIF": 0.65, + "SCATTERING_DIST_MODIF_CLOSE": 0.8, + "AIMING_TYPE": 5, + "DIST_TO_SHOOT_TO_CENTER": 3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "SHPERE_FRIENDY_FIRE_SIZE": -1, + "COEF_IF_MOVE": 1.5, + "TIME_COEF_IF_MOVE": 1.5, + "BOT_MOVE_IF_DELTA": 0.01, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 30, + "WEAPON_ROOT_OFFSET": 0.35, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MAX_AIM_TIME": 1.5, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "Y_TOP_OFFSET_COEF": 0.001, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "XZ_COEF_STATIONARY_GRENADE": 0.8 + }, + "Look": { + "OLD_TIME_POINT": 11, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8, + "LOOK_AROUND_DELTA": 1.1, + "ANGLE_FOR_GETUP": 30, + "MAX_VISION_GRASS_METERS": 0.4, + "MAX_VISION_GRASS_METERS_FLARE": 7, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "LightOnVisionDistance": 30, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "MIDDLE_DIST": 90, + "MiddleDeltaTimeSec": 1, + "CloseDeltaTimeSec": 0.1, + "POSIBLE_VISION_SPACE": 1.2, + "GOAL_TO_FULL_DISSAPEAR": 0.25, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.0001, + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "COME_TO_BODY_DIST": 1.2, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "VISIBLE_DISNACE_WITH_LIGHT": 43, + "ENEMY_LIGHT_ADD": 45, + "ENEMY_LIGHT_START_DIST": 40, + "CAN_LOOK_TO_WALL": false, + "CHECK_HEAD_ANY_DIST": false, + "DIST_NOT_TO_IGNORE_WALL": 15, + "DIST_CHECK_WALL": 20, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "MIN_LOOK_AROUD_TIME": 20, + "OPTIMIZE_TO_ONLY_BODY": true + }, + "Shoot": { + "RECOIL_TIME_NORMALIZE": 2, + "RECOIL_PER_METER": 0.1, + "CAN_STOP_SHOOT_CAUSE_ANIMATOR": true, + "MAX_RECOIL_PER_METER": 0.2, + "HORIZONT_RECOIL_COEF": 0.4, + "WAIT_NEXT_SINGLE_SHOT": 0.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.8, + "MARKSMAN_DIST_SEK_COEF": 44, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "BASE_AUTOMATIC_TIME": 0.1, + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 76, + "FAR_DIST_ENEMY": 20, + "SHOOT_FROM_COVER": 4, + "FAR_DIST_ENEMY_SQR": 400, + "MAX_DIST_COEF": 1.35, + "RECOIL_DELTA_PRESS": 0.15, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "CAN_SHOOTS_TIME_TO_AMBUSH": 333, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "CHANCE_TO_CHANGE_WEAPON": 0, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 0, + "LOW_DIST_TO_CHANGE_WEAPON": 10, + "FAR_DIST_TO_CHANGE_WEAPON": 50, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "WAIT_NEXT_STATIONARY_GRENADE": 1, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "VALIDATE_MALFUNCTION_CHANCE": 100, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 + }, + "Move": { + "BASE_ROTATE_SPEED": 270, + "REACH_DIST": 0.5, + "REACH_DIST_RUN": 0.8, + "START_SLOW_DIST": 1.5, + "BASESTART_SLOW_DIST": 1.1, + "SLOW_COEF": 7, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_START_RAYCAST": 15, + "BASE_START_SERACH": 35, + "UPDATE_TIME_RECAL_WAY": 7, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST_SQR": 225, + "BASE_SQRT_START_SERACH": 1225, + "Y_APPROXIMATION": 0.7, + "DELTA_LAST_SEEN_ENEMY": 20, + "REACH_DIST_COVER": 2, + "RUN_TO_COVER_MIN": 2, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "SEC_TO_CHANGE_TO_RUN": 3 + }, + "Grenade": { + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "DELTA_NEXT_ATTEMPT": 10, + "MIN_DIST_NOT_TO_THROW": 8, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 99, + "GrenadePerMeter": 0.1, + "REQUEST_DIST_MUST_THROW_SQRT": 4, + "REQUEST_DIST_MUST_THROW": 2, + "BEWARE_TYPE": 2, + "SHOOT_TO_SMOKE_CHANCE_100": 30, + "CHANCE_RUN_FLASHED_100": 0, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "FLASH_GRENADE_TIME_COEF": 0.3, + "SIZE_SPOTTED_COEF": 2, + "BE_ATTENTION_COEF": 4, + "TIME_SHOOT_TO_FLASH": 4, + "CLOSE_TO_SMOKE_TO_SHOOT": 5, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 25, + "CLOSE_TO_SMOKE_TIME_DELTA": 7, + "SMOKE_CHECK_DELTA": 1, + "DELTA_GRENADE_START_TIME": 0.7, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "NO_RUN_FROM_AI_GRENADES": false, + "MAX_THROW_POWER": 16.7, + "GrenadePrecision": 0.1, + "STOP_WHEN_THROW_GRENADE": true, + "WAIT_TIME_TURN_AWAY": 0.2, + "SMOKE_SUPPRESS_DELTA": 20, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "STUN_SUPPRESS_DELTA": 9, + "CHEAT_START_GRENADE_PLACE": false, + "CAN_THROW_STRAIGHT_CONTACT": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "ANG_TYPE": 4 + }, + "Change": { + "SMOKE_VISION_DIST": 0.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_ACCURATY": 1.6, + "SMOKE_LAY_CHANCE": 1.6, + "FLASH_VISION_DIST": 0.05, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_SCATTERING": 1.6, + "FLASH_PRECICING": 1.6, + "FLASH_HEARING": 1, + "FLASH_ACCURATY": 1.6, + "FLASH_LAY_CHANCE": 1, + "STUN_HEARING": 0.01 + }, + "Cover": { + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "SOUND_TO_GET_SPOTTED": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "MAX_DIST_OF_COVER": 4, + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "MIN_DIST_TO_ENEMY": 9, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CHECK_SFETY": 9, + "TIME_CHECK_SAFE": 2, + "HIDE_TO_COVER_TIME": 1.5, + "MAX_DIST_OF_COVER_SQR": 16, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "SPOTTED_COVERS_RADIUS": 3, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "SPOTTED_GRENADE_RADIUS": 16, + "MAX_SPOTTED_TIME_SEC": 45, + "WAIT_INT_COVER_FINDING_ENEMY": 2, + "CLOSE_DIST_POINT_SQRT": 4, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "MOVE_TO_COVER_WHEN_TARGET": false, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "SPOTTED_GRENADE_TIME": 7, + "DEPENDS_Y_DIST_TO_BOT": false, + "RUN_IF_FAR": 10, + "RUN_IF_FAR_SQRT": 225, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "CHECK_COVER_ENEMY_LOOK": true, + "SHOOT_NEAR_TO_LEAVE": 2, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "DOG_FIGHT_AFTER_LEAVE": 4, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "MIN_DEFENCE_LEVEL": 22, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "ENEMY_DIST_TO_GO_OUT": 1, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 20, + "STATIONARY_WEAPON_MAX_DIST_TO_USE": 25 + }, + "Patrol": { + "DEAD_BODY_LOOK_PERIOD": 8, + "LOOK_TIME_BASE": 12, + "CAN_LOOK_TO_DEADBODIES": true, + "CAN_CHOOSE_RESERV": false, + "DO_RANDOM_DROP_ITEM": true, + "TRY_CHOOSE_RESERV_WAY_ON_START": false, + "CAN_FRIENDLY_TILT": true, + "CAN_HARD_AIM": true, + "RESERVE_TIME_STAY": 72, + "FRIEND_SEARCH_SEC": 12, + "TALK_DELAY": 1.1, + "MIN_TALK_DELAY": 35, + "TALK_DELAY_BIG": 15.1, + "CHANGE_WAY_TIME": 125.1, + "MIN_DIST_TO_CLOSE_TALK": 5, + "VISION_DIST_COEF_PEACE": 0.75, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CUT_WAY_MIN_0_1": 0.4, + "CUT_WAY_MAX_0_1": 0.65, + "CHANCE_TO_CHANGE_WAY_0_100": 50, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "SUSPETION_PLACE_LIFETIME": 7, + "RESERVE_OUT_TIME": 30, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "CAN_WATCH_SECOND_WEAPON": true + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 2, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.7, + "DISPERSION_COEF": 3.6, + "CLOSE_DIST": 10, + "FAR_DIST": 30, + "SOUND_DIR_DEEFREE": 30, + "DIST_PLACE_TO_FIND_POINT": 70, + "DEAD_BODY_SOUND_RAD": 30, + "LOOK_ONLY_DANGER": false, + "RESET_TIMER_DIST": 17, + "HEAR_DELAY_WHEN_PEACE": 0.75, + "HEAR_DELAY_WHEN_HAVE_SMT": 0.5, + "LOOK_ONLY_DANGER_DELTA": 9 + }, + "Mind": { + "HOW_WORK_OVER_DEAD_BODY": 2, + "MIN_SHOOTS_TIME": 2, + "MAX_SHOOTS_TIME": 4, + "TIME_LEAVE_MAP": 23, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "MIN_DAMAGE_SCARE": 20, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_FIND_ENEMY": 22, + "MAX_AGGRO_BOT_DIST": 100, + "HIT_POINT_DETECTION": 4, + "DANGER_POINT_CHOOSE_COEF": 1, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "FOLLOWER_AND_BOSS_WARN_EQUAL_PRIORITY": true, + "COVER_DIST_COEF": 1.5, + "DIST_TO_FOUND_SQRT": 400, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "DIST_TO_STOP_RUN_ENEMY": 15, + "CAN_TAKE_ITEMS": true, + "CHECK_MARK_OF_UNKNOWS": true, + "ENEMY_LOOK_AT_ME_ANG": 15, + "MIN_START_AGGRESION_COEF": 1, + "MAX_START_AGGRESION_COEF": 3, + "BULLET_FEEL_DIST": 360, + "BULLET_FEEL_CLOSE_SDIST": 1, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 10, + "FRIEND_DEAD_AGR_LOW": -0.2, + "FRIEND_AGR_KILL": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "SURGE_KIT_ONLY_SAFE_CONTAINER": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": true, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_USE_MEDS": true, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "PROTECT_TIME_REAL": true, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CAN_PANIC_IS_PROTECT": false, + "NO_RUN_AWAY_FOR_SAFE": false, + "PART_PERCENT_TO_HEAL": 0.65, + "PROTECT_DELTA_HEAL_SEC": 10, + "CAN_STAND_BY": true, + "CAN_THROW_REQUESTS": true, + "GROUP_ANY_PHRASE_DELAY": 1, + "GROUP_EXACTLY_PHRASE_DELAY": 24, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "DOG_FIGHT_OUT": 6, + "DOG_FIGHT_IN": 3, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "PISTOL_SHOTGUN_AMBUSH_DIST": 60, + "STANDART_AMBUSH_DIST": 200, + "AI_POWER_COEF": 120, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "TALK_WITH_QUERY": true, + "WILL_PERSUE_AXEMAN": true, + "MAY_BE_CALLED_FOR_HELP": true + }, + "Boss": { + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "CHANCE_TO_SEND_GRENADE_100": 100, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "PERSONS_SEND": 2, + "DELTA_SEARCH_TIME": 18, + "COVER_TO_SEND": true, + "WAIT_NO_ATTACK_SAVAGE": 10, + "CHANCE_USE_RESERVE_PATROL_100": 50, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 45, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_CONTUTION_TIME": 5, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_MIDDLE_ATTACK_DIST": 22, + "KILLA_LARGE_ATTACK_DIST": 41, + "KILLA_SEARCH_METERS": 30, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_HOLD_DELAY": 5, + "KILLA_BULLET_TO_RELOAD": 15, + "SHALL_WARN": true, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_ONE_IS_CLOSE": 30, + "KILLA_TRIGGER_DOWN_DELAY": 1, + "KILLA_WAIT_IN_COVER_COEF": 1 + }, + "Core": { + "VisibleAngle": 140, + "VisibleDistance": 130, + "GainSightCoef": 0.1, + "ScatteringPerMeter": 0.05, + "ScatteringClosePerMeter": 0.1, + "DamageCoeff": 1, + "HearingSense": 2.85, + "CanRun": true, + "CanGrenade": true, + "AimingType": "normal", + "PistolFireDistancePref": 35, + "ShotgunFireDistancePref": 50, + "RifleFireDistancePref": 100, + "AccuratySpeed": 0.3, + "WaitInCoverBetweenShotsSec": 1.5 + }, + "Scattering": { + "MinScatter": 0.015, + "WorkingScatter": 0.15, + "MaxScatter": 0.3, + "SpeedUp": 0.6, + "SpeedUpAim": 1.8, + "SpeedDown": -0.2, + "ToSlowBotSpeed": 1.8, + "ToLowBotSpeed": 2.8, + "ToUpBotSpeed": 4.3, + "MovingSlowCoef": 1.4, + "ToLowBotAngularSpeed": 140, + "ToStopBotAngularSpeed": 80, + "FromShot": 0.001, + "TracerCoef": 1.3, + "HandDamageScatteringMinMax": 0.7, + "HandDamageAccuracySpeed": 1.3, + "BloodFall": 1.45, + "Caution": 0.03, + "ToCaution": 0.6, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "AMPLITUDE_FACTOR": 0.015, + "AMPLITUDE_SPEED": 0.001, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "PoseChnageCoef": 0.1, + "LayFactor": 0.1, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1 + } + }, + "impossible": { + "Lay": { + "CHECK_SHOOT_WHEN_LAYING": false, + "DELTA_LAY_CHECK": 2, + "DELTA_GETUP": 5, + "DELTA_AFTER_GETUP": 10, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "MAX_LAY_TIME": 35, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "ATTACK_LAY_CHANCE": 25, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "LAY_AIM": 0.6, + "MIN_CAN_LAY_DIST_SQRT": 121, + "MIN_CAN_LAY_DIST": 11, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_CAN_LAY_DIST": 200, + "LAY_CHANCE_DANGER": 40, + "DAMAGE_TIME_TO_GETUP": 3 + }, + "Aiming": { + "DEAD_BODY_LOOK_PERIOD": 8, + "MAX_AIM_PRECICING": 4, + "BETTER_PRECICING_COEF": 0.7, + "RECALC_DIST": 0.7, + "RECALC_SQR_DIST": 0.48999998, + "COEF_FROM_COVER": 0.65, + "PANIC_COEF": 1.2, + "PANIC_ACCURATY_COEF": 1.2, + "HARD_AIM": 0.75, + "PANIC_TIME": 2, + "CAN_HARD_AIM": true, + "RECALC_MUST_TIME": 3, + "DAMAGE_PANIC_TIME": 15, + "DANGER_UP_POINT": 1.3, + "MAX_AIMING_UPGRADE_BY_TIME": 0.4, + "DAMAGE_TO_DISCARD_AIM_0_100": 86, + "MIN_TIME_DISCARD_AIM_SEC": 0.3, + "MAX_TIME_DISCARD_AIM_SEC": 0.9, + "XZ_COEF": 0.15, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "BOTTOM_COEF": 0.1, + "FIRST_CONTACT_ADD_SEC": 0.01, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.17, + "BASE_HIT_AFFECTION_MIN_ANG": 4, + "BASE_HIT_AFFECTION_MAX_ANG": 8, + "BASE_SHIEF": 0.05, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SCATTERING_DIST_MODIF": 0.55, + "SCATTERING_DIST_MODIF_CLOSE": 0.6, + "AIMING_TYPE": 4, + "DIST_TO_SHOOT_TO_CENTER": 3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "SHPERE_FRIENDY_FIRE_SIZE": -1, + "COEF_IF_MOVE": 1, + "TIME_COEF_IF_MOVE": 1.1, + "BOT_MOVE_IF_DELTA": 0.01, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 10, + "WEAPON_ROOT_OFFSET": 0.35, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MAX_AIM_TIME": 1.5, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "XZ_COEF_STATIONARY_GRENADE": 0.2 + }, + "Look": { + "OLD_TIME_POINT": 11, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8, + "LOOK_AROUND_DELTA": 1.1, + "ANGLE_FOR_GETUP": 30, + "MAX_VISION_GRASS_METERS": 0.8, + "MAX_VISION_GRASS_METERS_FLARE": 8, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "LightOnVisionDistance": 30, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "MIDDLE_DIST": 90, + "MiddleDeltaTimeSec": 1, + "CloseDeltaTimeSec": 0.1, + "POSIBLE_VISION_SPACE": 1.2, + "GOAL_TO_FULL_DISSAPEAR": 0.5, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.0005, + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "COME_TO_BODY_DIST": 1.2, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "VISIBLE_DISNACE_WITH_LIGHT": 43, + "ENEMY_LIGHT_ADD": 45, + "ENEMY_LIGHT_START_DIST": 40, + "CAN_LOOK_TO_WALL": false, + "DIST_NOT_TO_IGNORE_WALL": 15, + "DIST_CHECK_WALL": 20, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "MIN_LOOK_AROUD_TIME": 20, + "OPTIMIZE_TO_ONLY_BODY": true + }, + "Shoot": { + "RECOIL_TIME_NORMALIZE": 2, + "RECOIL_PER_METER": 0.1, + "MAX_RECOIL_PER_METER": 0.2, + "HORIZONT_RECOIL_COEF": 0.4, + "WAIT_NEXT_SINGLE_SHOT": 0.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.8, + "MARKSMAN_DIST_SEK_COEF": 44, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "BASE_AUTOMATIC_TIME": 0.1, + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 76, + "FAR_DIST_ENEMY": 20, + "SHOOT_FROM_COVER": 4, + "FAR_DIST_ENEMY_SQR": 400, + "MAX_DIST_COEF": 1.35, + "RECOIL_DELTA_PRESS": 0.15, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "CAN_SHOOTS_TIME_TO_AMBUSH": 333, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "CHANCE_TO_CHANGE_WEAPON": 0, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 0, + "LOW_DIST_TO_CHANGE_WEAPON": 10, + "FAR_DIST_TO_CHANGE_WEAPON": 50, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "WAIT_NEXT_STATIONARY_GRENADE": 1, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "VALIDATE_MALFUNCTION_CHANCE": 100, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 + }, + "Move": { + "BASE_ROTATE_SPEED": 270, + "REACH_DIST": 0.5, + "REACH_DIST_RUN": 0.8, + "START_SLOW_DIST": 1.5, + "BASESTART_SLOW_DIST": 1.1, + "SLOW_COEF": 7, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_START_RAYCAST": 15, + "BASE_START_SERACH": 35, + "UPDATE_TIME_RECAL_WAY": 7, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST_SQR": 225, + "BASE_SQRT_START_SERACH": 1225, + "Y_APPROXIMATION": 0.7, + "DELTA_LAST_SEEN_ENEMY": 20, + "REACH_DIST_COVER": 2, + "RUN_TO_COVER_MIN": 2, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "SEC_TO_CHANGE_TO_RUN": 3 + }, + "Grenade": { + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "DELTA_NEXT_ATTEMPT": 10, + "MIN_DIST_NOT_TO_THROW": 8, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 99, + "GrenadePerMeter": 0.1, + "REQUEST_DIST_MUST_THROW_SQRT": 4, + "REQUEST_DIST_MUST_THROW": 2, + "BEWARE_TYPE": 2, + "SHOOT_TO_SMOKE_CHANCE_100": 30, + "CHANCE_RUN_FLASHED_100": 0, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "FLASH_GRENADE_TIME_COEF": 0.3, + "SIZE_SPOTTED_COEF": 2, + "BE_ATTENTION_COEF": 4, + "TIME_SHOOT_TO_FLASH": 4, + "CLOSE_TO_SMOKE_TO_SHOOT": 5, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 25, + "CLOSE_TO_SMOKE_TIME_DELTA": 7, + "SMOKE_CHECK_DELTA": 1, + "DELTA_GRENADE_START_TIME": 0.7, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "NO_RUN_FROM_AI_GRENADES": false, + "MAX_THROW_POWER": 19, + "MIN_THROW_DIST_PERCENT_0_1": 0.8, + "GrenadePrecision": 0.01, + "STOP_WHEN_THROW_GRENADE": true, + "WAIT_TIME_TURN_AWAY": 0.2, + "SMOKE_SUPPRESS_DELTA": 20, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "STUN_SUPPRESS_DELTA": 9, + "CHEAT_START_GRENADE_PLACE": false, + "CAN_THROW_STRAIGHT_CONTACT": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "ANG_TYPE": 4 + }, + "Change": { + "SMOKE_VISION_DIST": 0.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_ACCURATY": 1.6, + "SMOKE_LAY_CHANCE": 1.6, + "FLASH_VISION_DIST": 0.05, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_SCATTERING": 1.6, + "FLASH_PRECICING": 1.6, + "FLASH_HEARING": 1, + "FLASH_ACCURATY": 1.6, + "FLASH_LAY_CHANCE": 1, + "STUN_HEARING": 0.01 + }, + "Cover": { + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "SOUND_TO_GET_SPOTTED": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "MAX_DIST_OF_COVER": 4, + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "MIN_DIST_TO_ENEMY": 9, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CHECK_SFETY": 9, + "TIME_CHECK_SAFE": 2, + "HIDE_TO_COVER_TIME": 1.5, + "MAX_DIST_OF_COVER_SQR": 16, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "SPOTTED_COVERS_RADIUS": 3, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "SPOTTED_GRENADE_RADIUS": 16, + "MAX_SPOTTED_TIME_SEC": 45, + "WAIT_INT_COVER_FINDING_ENEMY": 2, + "CLOSE_DIST_POINT_SQRT": 4, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "MOVE_TO_COVER_WHEN_TARGET": false, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "SPOTTED_GRENADE_TIME": 7, + "DEPENDS_Y_DIST_TO_BOT": false, + "RUN_IF_FAR": 15, + "RUN_IF_FAR_SQRT": 225, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "CHECK_COVER_ENEMY_LOOK": true, + "SHOOT_NEAR_TO_LEAVE": 2, + "SHOOT_NEAR_SEC_PERIOD": 1, + "HITS_TO_LEAVE_COVER": 2, + "HITS_TO_LEAVE_COVER_UNKNOWN": 2, + "DOG_FIGHT_AFTER_LEAVE": 4, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "MIN_DEFENCE_LEVEL": 22, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "ENEMY_DIST_TO_GO_OUT": 1, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 20, + "STATIONARY_WEAPON_MAX_DIST_TO_USE": 40 + }, + "Patrol": { + "LOOK_TIME_BASE": 12, + "CAN_LOOK_TO_DEADBODIES": true, + "RESERVE_TIME_STAY": 72, + "CAN_CHOOSE_RESERV": false, + "TRY_CHOOSE_RESERV_WAY_ON_START": false, + "FRIEND_SEARCH_SEC": 12, + "TALK_DELAY": 1.1, + "MIN_TALK_DELAY": 35, + "TALK_DELAY_BIG": 15.1, + "CHANGE_WAY_TIME": 125.1, + "MIN_DIST_TO_CLOSE_TALK": 5, + "VISION_DIST_COEF_PEACE": 1, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CUT_WAY_MIN_0_1": 0.4, + "CUT_WAY_MAX_0_1": 0.65, + "CHANCE_TO_CHANGE_WAY_0_100": 50, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "SUSPETION_PLACE_LIFETIME": 7, + "RESERVE_OUT_TIME": 30, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "CAN_WATCH_SECOND_WEAPON": true + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 2, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.95, + "DISPERSION_COEF": 10.6, + "CLOSE_DIST": 20, + "FAR_DIST": 60, + "SOUND_DIR_DEEFREE": 30, + "DIST_PLACE_TO_FIND_POINT": 70, + "DEAD_BODY_SOUND_RAD": 30, + "LOOK_ONLY_DANGER": false, + "RESET_TIMER_DIST": 17, + "HEAR_DELAY_WHEN_PEACE": 0.5, + "HEAR_DELAY_WHEN_HAVE_SMT": 0.5, + "LOOK_ONLY_DANGER_DELTA": 9 + }, + "Mind": { + "MIN_SHOOTS_TIME": 2, + "MAX_SHOOTS_TIME": 4, + "TIME_LEAVE_MAP": 23, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "MIN_DAMAGE_SCARE": 20, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_FIND_ENEMY": 22, + "MAX_AGGRO_BOT_DIST": 100, + "HIT_POINT_DETECTION": 4, + "DANGER_POINT_CHOOSE_COEF": 1, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "FOLLOWER_AND_BOSS_WARN_EQUAL_PRIORITY": true, + "COVER_DIST_COEF": 1.5, + "DIST_TO_FOUND_SQRT": 400, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "DIST_TO_STOP_RUN_ENEMY": 15, + "ENEMY_LOOK_AT_ME_ANG": 15, + "MIN_START_AGGRESION_COEF": 1, + "MAX_START_AGGRESION_COEF": 3, + "CAN_TAKE_ITEMS": true, + "CHECK_MARK_OF_UNKNOWS": true, + "BULLET_FEEL_DIST": 160, + "BULLET_FEEL_CLOSE_SDIST": 1, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, + "FRIEND_DEAD_AGR_LOW": -0.2, + "FRIEND_AGR_KILL": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "SURGE_KIT_ONLY_SAFE_CONTAINER": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": true, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_USE_MEDS": true, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "PROTECT_TIME_REAL": true, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CAN_PANIC_IS_PROTECT": false, + "NO_RUN_AWAY_FOR_SAFE": false, + "PART_PERCENT_TO_HEAL": 0.65, + "PROTECT_DELTA_HEAL_SEC": 10, + "CAN_STAND_BY": true, + "CAN_THROW_REQUESTS": true, + "GROUP_ANY_PHRASE_DELAY": -1, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "DOG_FIGHT_OUT": 6, + "DOG_FIGHT_IN": 3, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "PISTOL_SHOTGUN_AMBUSH_DIST": 60, + "STANDART_AMBUSH_DIST": 200, + "AI_POWER_COEF": 120, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "TALK_WITH_QUERY": true, + "WILL_PERSUE_AXEMAN": true, + "MAY_BE_CALLED_FOR_HELP": true + }, + "Boss": { + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "CHANCE_TO_SEND_GRENADE_100": 100, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "PERSONS_SEND": 2, + "DELTA_SEARCH_TIME": 18, + "COVER_TO_SEND": true, + "WAIT_NO_ATTACK_SAVAGE": 10, + "CHANCE_USE_RESERVE_PATROL_100": 50, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 45, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_CONTUTION_TIME": 5, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_MIDDLE_ATTACK_DIST": 22, + "KILLA_LARGE_ATTACK_DIST": 41, + "KILLA_SEARCH_METERS": 30, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_HOLD_DELAY": 5, + "KILLA_BULLET_TO_RELOAD": 15, + "SHALL_WARN": true, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_ONE_IS_CLOSE": 30, + "KILLA_TRIGGER_DOWN_DELAY": 1, + "KILLA_WAIT_IN_COVER_COEF": 1 + }, + "Core": { + "VisibleAngle": 140, + "VisibleDistance": 137, + "GainSightCoef": 0.01, + "ScatteringPerMeter": 0.05, + "ScatteringClosePerMeter": 0.1, + "DamageCoeff": 1, + "HearingSense": 3.85, + "CanRun": true, + "CanGrenade": true, + "AimingType": "normal", + "PistolFireDistancePref": 35, + "ShotgunFireDistancePref": 50, + "RifleFireDistancePref": 100, + "AccuratySpeed": 0.3, + "WaitInCoverBetweenShotsSec": 1.5 + }, + "Scattering": { + "MinScatter": 0.015, + "WorkingScatter": 0.15, + "MaxScatter": 0.3, + "SpeedUp": 0.6, + "SpeedUpAim": 1.8, + "SpeedDown": -0.2, + "ToSlowBotSpeed": 1.8, + "ToLowBotSpeed": 2.8, + "ToUpBotSpeed": 4.3, + "MovingSlowCoef": 1.4, + "ToLowBotAngularSpeed": 140, + "ToStopBotAngularSpeed": 80, + "FromShot": 0.001, + "TracerCoef": 1.3, + "HandDamageScatteringMinMax": 0.7, + "HandDamageAccuracySpeed": 1.3, + "BloodFall": 1.45, + "Caution": 0.03, + "ToCaution": 0.6, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "AMPLITUDE_FACTOR": 0.015, + "AMPLITUDE_SPEED": 0.001, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "PoseChnageCoef": 0.1, + "LayFactor": 0.1, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1 + } + } + }, + "chances": { + "equipment": { + "Headwear": 100, + "Earpiece": 0, + "FaceCover": 100, + "ArmorVest": 0, + "Eyewear": 0, + "ArmBand": 0, + "TacticalVest": 100, + "Backpack": 0, + "FirstPrimaryWeapon": 0, + "SecondPrimaryWeapon": 0, + "Holster": 100, + "Scabbard": 100, + "Pockets": 100, + "SecuredContainer": 100 + }, + "weaponMods": { + "mod_magazine": 100, + "mod_sight_rear": 0 + }, + "equipmentMods": {} + }, + "generation": { + "items": { + "specialItems": { + "weights": { + "0": 1, + "1": 0 + }, + "whitelist": [] + }, + "healing": { + "weights": { + "0": 1, + "1": 2, + "2": 1 + }, + "whitelist": [] + }, + "drugs": { + "weights": { + "0": 1, + "1": 2, + "2": 0 + }, + "whitelist": [] + }, + "stims": { + "weights": { + "0": 2, + "1": 1, + "2": 0 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "backpackLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 0 + }, + "whitelist": [] + }, + "pocketLoot": { + "weights": { + "0": 1, + "1": 6, + "2": 3, + "3": 1, + "4": 1 + }, + "whitelist": [] + }, + "vestLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 0, + "5": 0, + "6": 0 + }, + "whitelist": [] + }, + "magazines": { + "weights": { + "0": 0, + "1": 0, + "2": 1, + "3": 3, + "4": 1 + }, + "whitelist": [] + }, + "grenades": { + "weights": { + "0": 1, + "1": 2, + "2": 1, + "3": 1, + "4": 0, + "5": 0 + }, + "whitelist": [] + } + } + } +} \ No newline at end of file diff --git a/project/assets/database/bots/types/bear.json b/project/assets/database/bots/types/bear.json index c3707080..d215d661 100644 --- a/project/assets/database/bots/types/bear.json +++ b/project/assets/database/bots/types/bear.json @@ -80,6 +80,7 @@ "mod_equipment_001": 25, "mod_equipment_002": 25, "mod_nvg": 40, + "mod_mount": 20, "right_side_plate": 75 }, "weaponMods": { @@ -2188,7 +2189,7 @@ "Basuro", "Bepis", "Baliston", - "Pessin", + "Crow", "Aki-chan", "Fin", "Gatsu66", @@ -2324,7 +2325,7 @@ "SlejmUr", "bandit", "Junko Space Mommy", - "civiciam", + "MoxoPixel", "FlashMode", "Pettan", "Oraceon", @@ -2481,23 +2482,35 @@ "Brin", "Belette", "Agnotology", - "All_Heil_Lord_Ppepe", - "ixcetotis", - "btdc00" + "All_Heil_Lord_Pepe", + "ixcetotis", + "btdc00", + "Bnuy", + "Choccy", + "LunnayaLuna", + "Tyfon", + "weewoo", + "Mattdokn", + "BlackDeathGER", + "Gizzy", + "LuckyCharmT", + "Rena-chan", + "HB" ], "generation": { "items": { "backpackLoot": { "weights": { "0": 1, + "3": 5, + "4": 7, + "5": 6, + "8": 6, "10": 5, "12": 4, "15": 4, "20": 3, - "23": 1, - "3": 2, - "5": 5, - "8": 6 + "23": 1 }, "whitelist": [] }, @@ -2508,11 +2521,34 @@ "2": 1 }, "whitelist": [] + }, + "food": { + "weights": { + "0": 5, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 5, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 5, + "1": 1 + }, + "whitelist": [] }, "grenades": { "weights": { - "0": 1, - "1": 4, + "0": 2, + "1": 6, "2": 5, "3": 2, "4": 1 @@ -2558,7 +2594,7 @@ }, "stims": { "weights": { - "0": 1, + "0": 2, "1": 2, "2": 1 }, @@ -2567,7 +2603,7 @@ "vestLoot": { "weights": { "0": 1, - "1": 2, + "1": 3, "2": 3, "3": 2, "4": 1 @@ -2988,9 +3024,9 @@ "5ac66d9b5acfc4001633997a": 5, "5ae08f0a5acfc408fb1398a1": 4, "5b0bbe4e5acfc40dc528a72d": 4, - "5ba26383d4351e00334c93d9": 5, + "5ba26383d4351e00334c93d9": 4, "5bb2475ed4351e00853264e3": 4, - "5bd70322209c4d00d7167b8f": 5, + "5bd70322209c4d00d7167b8f": 4, "5beed0f50db834001c062b12": 3, "5bf3e03b0db834001d2c4a9c": 5, "5bf3e0490db83400196199af": 5, @@ -3229,7 +3265,6 @@ "58820d1224597753c90aeb13": 1, "5887431f2459777e1612938f": 1, "58dd3ad986f77403051cba8f": 1, - "590c657e86f77412b013051d": 1, "59e0d99486f7744a32234762": 1, "59e4cf5286f7741778269d8a": 1, "59e4d24686f7741776641ac7": 1, @@ -3240,11 +3275,6 @@ "59e690b686f7746c9f75e848": 1, "59e6920f86f77411d82aa167": 1, "59e77a2386f7742ee578960a": 1, - "5a0ec6d286f7742c0b518fb5": 1, - "5a13eebd86f7746fd639aa93": 1, - "5a13ef7e86f7741290491063": 1, - "5a13f24186f77410e57c5626": 1, - "5a1452ee86f7746f33111763": 1, "5a38ebd9c4a282000d722a5b": 1, "5a3c16fe86f77452b62de32a": 1, "5a6086ea4f39f99cd479502f": 1, @@ -3281,7 +3311,6 @@ "5d6e6a42a4b9364f07165f52": 1, "5d6e6a53a4b9361bd473feec": 1, "5d6e6a5fa4b93614ec501745": 1, - "5d8e15b686f774445103b190": 1, "5e023d34e8a400319a28ed44": 1, "5e023d48186a883be655e551": 1, "5e023e53d4353e3302577c4c": 1, diff --git a/project/assets/database/bots/types/bossboar.json b/project/assets/database/bots/types/bossboar.json index 0c193649..0de9d9ad 100644 --- a/project/assets/database/bots/types/bossboar.json +++ b/project/assets/database/bots/types/bossboar.json @@ -2302,6 +2302,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2310,6 +2326,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bossboarsniper.json b/project/assets/database/bots/types/bossboarsniper.json index 2edd63cb..fa4f7e08 100644 --- a/project/assets/database/bots/types/bossboarsniper.json +++ b/project/assets/database/bots/types/bossboarsniper.json @@ -2038,6 +2038,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2046,6 +2062,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bossbully.json b/project/assets/database/bots/types/bossbully.json index 83ebfb9d..3805da27 100644 --- a/project/assets/database/bots/types/bossbully.json +++ b/project/assets/database/bots/types/bossbully.json @@ -2029,6 +2029,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2036,6 +2052,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bossgluhar.json b/project/assets/database/bots/types/bossgluhar.json index 9ea7ff2d..ded75bd2 100644 --- a/project/assets/database/bots/types/bossgluhar.json +++ b/project/assets/database/bots/types/bossgluhar.json @@ -2317,6 +2317,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2324,6 +2340,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosskilla.json b/project/assets/database/bots/types/bosskilla.json index 75d0547e..fad9ce2d 100644 --- a/project/assets/database/bots/types/bosskilla.json +++ b/project/assets/database/bots/types/bosskilla.json @@ -2019,6 +2019,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2026,6 +2042,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bossknight.json b/project/assets/database/bots/types/bossknight.json index 764cc833..8fd71e31 100644 --- a/project/assets/database/bots/types/bossknight.json +++ b/project/assets/database/bots/types/bossknight.json @@ -2167,6 +2167,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2175,6 +2191,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosskojaniy.json b/project/assets/database/bots/types/bosskojaniy.json index 80888a6b..98b46538 100644 --- a/project/assets/database/bots/types/bosskojaniy.json +++ b/project/assets/database/bots/types/bosskojaniy.json @@ -2070,6 +2070,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2078,6 +2094,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosskolontay.json b/project/assets/database/bots/types/bosskolontay.json index c2da4729..9eeab183 100644 --- a/project/assets/database/bots/types/bosskolontay.json +++ b/project/assets/database/bots/types/bosskolontay.json @@ -2322,6 +2322,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2330,6 +2346,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosssanitar.json b/project/assets/database/bots/types/bosssanitar.json index 46b5e082..a7ebb55d 100644 --- a/project/assets/database/bots/types/bosssanitar.json +++ b/project/assets/database/bots/types/bosssanitar.json @@ -2114,6 +2114,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2122,6 +2138,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosstagilla.json b/project/assets/database/bots/types/bosstagilla.json index 0ec8b5cf..c3498d03 100644 --- a/project/assets/database/bots/types/bosstagilla.json +++ b/project/assets/database/bots/types/bosstagilla.json @@ -2113,6 +2113,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2121,6 +2137,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/bosstest.json b/project/assets/database/bots/types/bosstest.json index e065fa11..42e2e553 100644 --- a/project/assets/database/bots/types/bosstest.json +++ b/project/assets/database/bots/types/bosstest.json @@ -1946,6 +1946,22 @@ "healing": { "max": 2, "min": 1 + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] }, "looseLoot": { "max": 3, diff --git a/project/assets/database/bots/types/bosszryachiy.json b/project/assets/database/bots/types/bosszryachiy.json index 36df4eb2..3a3d034c 100644 --- a/project/assets/database/bots/types/bosszryachiy.json +++ b/project/assets/database/bots/types/bosszryachiy.json @@ -2024,6 +2024,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2032,6 +2048,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/crazyassaultevent.json b/project/assets/database/bots/types/crazyassaultevent.json index a83d5f67..1ef4fad5 100644 --- a/project/assets/database/bots/types/crazyassaultevent.json +++ b/project/assets/database/bots/types/crazyassaultevent.json @@ -2348,21 +2348,44 @@ "backpackLoot": { "weights": { "0": 1, - "1": 1, - "2": 2, + "1": 6, + "2": 6, "3": 1, "4": 1, "5": 1, - "6": 1, - "7": 0 + "6": 1 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 }, "whitelist": [] }, "drugs": { "weights": { - "0": 1, - "1": 2, - "2": 0 + "0": 30, + "1": 9, + "2": 1 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 }, "whitelist": [] }, @@ -2397,8 +2420,8 @@ }, "pocketLoot": { "weights": { - "0": 1, - "1": 6, + "0": 2, + "1": 9, "2": 3, "3": 1, "4": 1 @@ -2423,8 +2446,8 @@ "vestLoot": { "weights": { "0": 1, - "1": 1, - "2": 2, + "1": 3, + "2": 4, "3": 1, "4": 0, "5": 0, @@ -3057,6 +3080,7 @@ "5a144bdb86f7741d374bbde0": 1, "5a1452ee86f7746f33111763": 3, "5a26abfac4a28232980eabff": 1, + "5a26ac06c4a282000c5a90a8": 1, "5a26ac0ec4a28200741e1e18": 3, "5a27b281c4a28200741e1e52": 1, "5a27bad7c4a282000b15184b": 1, @@ -3093,6 +3117,7 @@ "5ab3afb2d8ce87001660304d": 1, "5ac66bea5acfc43b321d4aec": 1, "5ad5ccd186f774446d5706e9": 4, + "5ad5cfbd86f7742c825d6104": 1, "5ad5d20586f77449be26d877": 2, "5ad5d49886f77455f9731921": 5, "5ad5d64486f774079b080af8": 1, @@ -3110,6 +3135,7 @@ "5b1fb3e15acfc4001637f068": 1, "5b31163c5acfc400153b71cb": 1, "5b363dd25acfc4001a598fd2": 1, + "5b363dea5acfc4771e1c5e7e": 1, "5b39ffbd5acfc47a8773fb06": 1, "5b3a337e5acfc4704b4a19a0": 1, "5b3f7bf05acfc433000ecf6b": 1, @@ -3133,8 +3159,8 @@ "5bbdb870d4351e00367fb67d": 2, "5bc09a18d4351e003562b68e": 2, "5bc5a351d4351e003477a414": 1, - "5bc9b156d4351e00367fbce9": 10, - "5bc9c29cd4351e003562b8a3": 31, + "5bc9b156d4351e00367fbce9": 12, + "5bc9c29cd4351e003562b8a3": 32, "5be4038986f774527d3fae60": 3, "5beec8b20db834001961942a": 1, "5bfea7ad0db834001c38f1ee": 1, @@ -3153,7 +3179,7 @@ "5c0e531286f7747fa54205c2": 13, "5c0e531d86f7747fa23f4d42": 40, "5c0e533786f7747fa23f4d47": 21, - "5c0e534186f7747fa1419867": 11, + "5c0e534186f7747fa1419867": 13, "5c0fa877d174af02a012e1cf": 35, "5c0fafb6d174af02a96260ba": 1, "5c10c8fd86f7743d7d706df3": 11, @@ -3289,6 +3315,7 @@ "5efb0e16aeb21837e749c7ff": 2, "5f2aa43ba9b91d26f20ae6d2": 1, "5f6331e097199b7db2128dc2": 1, + "5f647f31b6238e5dd066e196": 1, "5fb653962b1b027b1f50bd03": 1, "5fb6567747ce63734e3fa1dc": 1, "5fbcc429900b1d5091531dd7": 1, @@ -3400,17 +3427,19 @@ "64c196ad26a15b84aa07132f": 2, "64ccc1d4a0f13c24561edf27": 1, "64ccc1ec1779ad6ba200a137": 1, + "64ccc206793ca11c8f450a38": 1, "64ccc2111779ad6ba200a139": 1, "64ccc246ff54fb38131acf29": 2, "64ccc24de61ea448b507d34d": 2, "64ccc268c41e91416064ebc7": 1, "6516b129609aaf354b34b3a8": 1, "6516e91f609aaf354b34b3e2": 2, + "651a8e529829226ceb67c319": 1, "6529370c405a5f51dd023db8": 1, "65293c38fc460e50a509cb25": 1, "65293c7a17e14363030ad308": 1, "653ecef836fae5a82f02b869": 1, - "656df4fec921ad01000481a2": 72, + "656df4fec921ad01000481a2": 73, "6576f96220d53a5b8f3e395e": 1, "65815f0e647e3d7246384e14": 31, "6581998038c79576a2569e11": 4, @@ -3541,6 +3570,7 @@ "65815f0e647e3d7246384e14": 37 }, "SecuredContainer": { + "5448be9a4bdc2dfd2f8b456a": 22, "54527a984bdc2d4e668b4567": 1, "54527ac44bdc2d36668b4567": 11, "560d5e524bdc2d25448b4571": 12211, diff --git a/project/assets/database/bots/types/cursedassault.json b/project/assets/database/bots/types/cursedassault.json index a8bbbba4..9509510e 100644 --- a/project/assets/database/bots/types/cursedassault.json +++ b/project/assets/database/bots/types/cursedassault.json @@ -1,59 +1,59 @@ { "appearance": { "body": { - "5cc2e59214c02e000f16684e": 443, - "5cde9f337d6c8b0474535da8": 485, - "5d28ad6986f77429275dba22": 479, - "5d28ad7286f7742926686182": 475, - "5df8a10486f77412672a1e3a": 424, - "5e4bb3ee86f77406975c934e": 486, - "5e9da1d086f774054a667134": 455, - "5fd1eb3fbe3b7107d66cb645": 482, - "5fd22d311add82653b5a704c": 488, - "618d1af10a5a59657e5f56f3": 470, - "619238266c614e6d15792bca": 455, - "637df28ac22da5bb8d046935": 494, - "64a2edba08d26f8d62049c06": 476 + "5cc2e59214c02e000f16684e": 54, + "5cde9f337d6c8b0474535da8": 56, + "5d28ad6986f77429275dba22": 55, + "5d28ad7286f7742926686182": 41, + "5df8a10486f77412672a1e3a": 34, + "5e4bb3ee86f77406975c934e": 52, + "5e9da1d086f774054a667134": 52, + "5fd1eb3fbe3b7107d66cb645": 52, + "5fd22d311add82653b5a704c": 50, + "618d1af10a5a59657e5f56f3": 55, + "619238266c614e6d15792bca": 59, + "637df28ac22da5bb8d046935": 50, + "64a2edba08d26f8d62049c06": 49 }, "feet": { - "5cc2e5d014c02e15d53d9c03": 234, - "5cde9fb87d6c8b0474535da9": 219, - "5d28af3486f774292364a6e7": 200, - "5df8a15186f77412640e2e6a": 224, - "5f5e410c6bdad616ad46d60b": 222, - "5f5e41366760b4138443b343": 243, - "5f5e41576760b4138443b344": 230, - "61922589bb2cea6f7a22d964": 246, - "6193be546e5968395b260157": 221, - "637df25a1e688345e1097bd4": 223, - "64a2e970a74bb33d140e6dc5": 218 + "5cc2e5d014c02e15d53d9c03": 65, + "5cde9fb87d6c8b0474535da9": 72, + "5d28af3486f774292364a6e7": 57, + "5df8a15186f77412640e2e6a": 50, + "5f5e410c6bdad616ad46d60b": 56, + "5f5e41366760b4138443b343": 61, + "5f5e41576760b4138443b344": 64, + "61922589bb2cea6f7a22d964": 62, + "6193be546e5968395b260157": 53, + "637df25a1e688345e1097bd4": 66, + "64a2e970a74bb33d140e6dc5": 53 }, "hands": { - "5cc2e68f14c02e28b47de290": 467, - "5df8eac086f77412640e2ea7": 106, - "5e4bb49586f77406a313ec5a": 120, - "5e9da2dd86f774054e7d0f63": 113, - "5fd78fe9e3bfcf6cab4c9f54": 117, - "5fd7901bdd870108a754c0e6": 121, - "618cf9540a5a59657e5f5677": 114, - "6197aca964ae5436d76c1f98": 107, - "6391c6205dbbdb3b1b049840": 119, - "64ac23c449d74fd5ec0a124e": 120 + "5cc2e68f14c02e28b47de290": 187, + "5df8eac086f77412640e2ea7": 32, + "5e4bb49586f77406a313ec5a": 48, + "5e9da2dd86f774054e7d0f63": 49, + "5fd78fe9e3bfcf6cab4c9f54": 48, + "5fd7901bdd870108a754c0e6": 46, + "618cf9540a5a59657e5f5677": 49, + "6197aca964ae5436d76c1f98": 52, + "6391c6205dbbdb3b1b049840": 46, + "64ac23c449d74fd5ec0a124e": 45 }, "head": { - "5cc2e4d014c02e000d0115f8": 9, - "5cde9ff17d6c8b0474535daa": 8, - "5d28afe786f774292668618d": 7, - "5f68c4a7c174a17c0f4c8945": 7, - "5f68c4c217d579077152a252": 8 + "5cc2e4d014c02e000d0115f8": 20, + "5cde9ff17d6c8b0474535daa": 21, + "5d28afe786f774292668618d": 21, + "5f68c4a7c174a17c0f4c8945": 27, + "5f68c4c217d579077152a252": 19 }, "voice": { - "Scav_1": 24, - "Scav_2": 17, - "Scav_3": 19, - "Scav_4": 26, - "Scav_5": 22, - "Scav_6": 18 + "Scav_1": 8, + "Scav_2": 7, + "Scav_3": 8, + "Scav_4": 11, + "Scav_5": 5, + "Scav_6": 5 } }, "chances": { @@ -2375,8 +2375,8 @@ "backpackLoot": { "weights": { "0": 1, - "1": 2, - "2": 2, + "1": 6, + "2": 6, "3": 1, "4": 1, "5": 1, @@ -2384,18 +2384,42 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { - "0": 1, - "1": 2, - "2": 0 + "0": 30, + "1": 9, + "2": 1 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 }, "whitelist": [] }, "grenades": { "weights": { - "0": 3, - "1": 4, + "0": 8, + "1": 6, "2": 2, "3": 1, "4": 0, @@ -2405,8 +2429,8 @@ }, "healing": { "weights": { - "0": 1, - "1": 2, + "0": 5, + "1": 6, "2": 1 }, "whitelist": [] @@ -2414,17 +2438,17 @@ "magazines": { "weights": { "0": 0, - "1": 0, - "2": 1, - "3": 3, + "1": 5, + "2": 4, + "3": 2, "4": 1 }, "whitelist": [] }, "pocketLoot": { "weights": { - "0": 1, - "1": 6, + "0": 2, + "1": 9, "2": 3, "3": 1, "4": 1 @@ -2440,7 +2464,7 @@ }, "stims": { "weights": { - "0": 15, + "0": 45, "1": 3, "2": 1 }, @@ -2449,8 +2473,8 @@ "vestLoot": { "weights": { "0": 1, - "1": 1, - "2": 2, + "1": 3, + "2": 4, "3": 1, "4": 0, "5": 0, @@ -2838,15 +2862,15 @@ "items": { "Backpack": { "5448ba0b4bdc2d02308b456c": 2, - "5448fee04bdc2dbc018b4567": 312, + "5448fee04bdc2dbc018b4567": 315, "5448ff904bdc2d6f028b456e": 44, "544a3a774bdc2d3a388b4567": 1, "544fb25a4bdc2dfb738b4567": 121, "544fb3364bdc2d34748b456a": 103, "544fb37f4bdc2dee738b4567": 45, - "544fb3f34bdc2d03748b456a": 10, - "544fb45d4bdc2dee738b4568": 44, - "544fb62a4bdc2dfb738b4568": 58, + "544fb3f34bdc2d03748b456a": 11, + "544fb45d4bdc2dee738b4568": 46, + "544fb62a4bdc2dfb738b4568": 59, "544fb6cc4bdc2d34748b456e": 44, "54527a984bdc2d4e668b4567": 1, "54527ac44bdc2d36668b4567": 4, @@ -2862,7 +2886,7 @@ "5649ab884bdc2ded0b8b457f": 1, "5649ae4a4bdc2d1b2b8b4588": 1, "5649b2314bdc2d79388b4576": 1, - "5649d9a14bdc2d79388b4580": 2, + "5649d9a14bdc2d79388b4580": 1, "564ca99c4bdc2d16268b4589": 1, "5656d7c34bdc2d9d198b4587": 5, "5656eb674bdc2d35148b457c": 2, @@ -2882,22 +2906,23 @@ "56dff4a2d2720bbd668b456a": 3, "56e05a6ed2720bd0748b4567": 1, "56ea70acd2720b844b8b4594": 1, + "56ea7165d2720b6e518b4583": 1, "570fd6c2d2720bc6458b457f": 1, "570fd79bd2720bc7458b4583": 1, "573475fb24597737fb1379e1": 1, "573476d324597737da2adc13": 1, "5734770f24597738025ee254": 1, - "5734773724597737fd047c14": 35, + "5734773724597737fd047c14": 36, "57347c77245977448d35f6e2": 1, "57347cd0245977445a2d6ff1": 1, "57347d3d245977448f7b7f61": 61, "57347d5f245977448b40fa81": 52, "57347d692459774491567cf1": 57, "57347d7224597744596b4e72": 56, - "57347d8724597744596b4e76": 56, + "57347d8724597744596b4e76": 59, "57347d90245977448f7b7f65": 56, - "57347d9c245977448b40fa85": 47, - "57347da92459774491567cf5": 47, + "57347d9c245977448b40fa85": 48, + "57347da92459774491567cf5": 49, "5735ff5c245977640e39ba7e": 5, "573601b42459776410737435": 5, "573719df2459775a626ccbc2": 5, @@ -2909,17 +2934,17 @@ "574eb85c245977648157eec3": 2, "57505f6224597709a92585a9": 42, "575062b524597720a31c09a1": 43, - "57513f07245977207e26a311": 402, + "57513f07245977207e26a311": 407, "57513f9324597720a7128161": 38, - "57513fcc24597720a31c09a6": 64, + "57513fcc24597720a31c09a6": 66, "5751435d24597720a27126d1": 33, - "57514643245977207f2c2d09": 34, - "575146b724597720a27126d5": 58, - "5751487e245977207e26a315": 61, - "5751496424597720a27126da": 85, - "5751a25924597722c463c472": 123, + "57514643245977207f2c2d09": 35, + "575146b724597720a27126d5": 59, + "5751487e245977207e26a315": 62, + "5751496424597720a27126da": 86, + "5751a25924597722c463c472": 122, "5751a89d24597722aa0e8db0": 5, - "5755356824597772cb798962": 59, + "5755356824597772cb798962": 61, "5755383e24597772cb798966": 17, "57616a9e2459773c7a400234": 1, "576a5ed62459771e9c2096cb": 1, @@ -2927,16 +2952,16 @@ "576fd4ec2459777f0b518431": 1, "577d141e24597739c5255e01": 1, "5780cf692459777de4559321": 1, - "5780cf722459777a5108b9a1": 2, + "5780cf722459777a5108b9a1": 3, "5780cf7f2459777de4559322": 1, "5780cf942459777df90dcb72": 12, "5780cf9e2459777df90dcb73": 2, - "5780cfa52459777dfb276eb1": 22, + "5780cfa52459777dfb276eb1": 24, "5780d0532459777a5108b9a2": 2, "5780d0652459777df90dcb74": 2, "5780d07a2459777de4559324": 2, "57838f0b2459774a256959b2": 1, - "5783c43d2459774bbe137486": 32, + "5783c43d2459774bbe137486": 33, "5798a2832459774b53341029": 3, "57a0dfb82459774d3078b56c": 1, "57a0e5022459774d1673f889": 4, @@ -2959,7 +2984,7 @@ "588226d124597767ad33f787": 1, "588226dd24597767ad33f789": 1, "588226e62459776e3e094af7": 1, - "58864a4f2459770fcc257101": 3, + "58864a4f2459770fcc257101": 2, "5887431f2459777e1612938f": 2, "5888945a2459774bf43ba385": 1, "5888988e24597752fe43a6fa": 2, @@ -2968,7 +2993,7 @@ "5894a2c386f77427140b8342": 1, "58c157c886f774032749fb06": 1, "58d2912286f7744e27117493": 1, - "58dd3ad986f77403051cba8f": 1, + "58dd3ad986f77403051cba8f": 2, "5909e99886f7740c983b9984": 1, "590a386e86f77429692b27ab": 1, "590a391c86f774385a33c404": 1, @@ -2978,14 +3003,14 @@ "590c5c9f86f77477c91c36e7": 1, "590c5d4b86f774784e1b9c45": 52, "590c5f0d86f77413997acfab": 60, - "590c621186f774138d11ea29": 34, - "590c657e86f77412b013051d": 18, + "590c621186f774138d11ea29": 35, + "590c657e86f77412b013051d": 19, "590c661e86f7741e566b646a": 37, "590c678286f77426c9660122": 16, - "590c695186f7741e566b64a2": 13, + "590c695186f7741e566b64a2": 14, "5913611c86f77479e0084092": 8, "5913651986f774432f15d132": 1, - "59136a4486f774447a1ed172": 4, + "59136a4486f774447a1ed172": 5, "59136e1e86f774432f15d133": 1, "59136f6f86f774447a1ed173": 4, "591382d986f774465a6413a7": 1, @@ -3000,9 +3025,9 @@ "5938144586f77473c2087145": 3, "5938504186f7740991483f30": 6, "593858c486f774253a24cb52": 7, - "5938603e86f77435642354f4": 50, + "5938603e86f77435642354f4": 52, "5938994586f774523a425196": 7, - "593aa4be86f77457f56379f8": 34, + "593aa4be86f77457f56379f8": 36, "593d1fa786f7746da62d61ac": 1, "593d489686f7745c6255d58a": 2, "5943ee5a86f77413872d25ec": 1, @@ -3067,6 +3092,7 @@ "5a144bdb86f7741d374bbde0": 1, "5a1452ee86f7746f33111763": 3, "5a26abfac4a28232980eabff": 1, + "5a26ac06c4a282000c5a90a8": 1, "5a26ac0ec4a28200741e1e18": 3, "5a27b281c4a28200741e1e52": 1, "5a27bad7c4a282000b15184b": 1, @@ -3103,6 +3129,7 @@ "5ab3afb2d8ce87001660304d": 1, "5ac66bea5acfc43b321d4aec": 1, "5ad5ccd186f774446d5706e9": 4, + "5ad5cfbd86f7742c825d6104": 1, "5ad5d20586f77449be26d877": 2, "5ad5d49886f77455f9731921": 5, "5ad5d64486f774079b080af8": 1, @@ -3120,6 +3147,7 @@ "5b1fb3e15acfc4001637f068": 1, "5b31163c5acfc400153b71cb": 1, "5b363dd25acfc4001a598fd2": 1, + "5b363dea5acfc4771e1c5e7e": 1, "5b39ffbd5acfc47a8773fb06": 1, "5b3a337e5acfc4704b4a19a0": 1, "5b3f7bf05acfc433000ecf6b": 1, @@ -3143,8 +3171,8 @@ "5bbdb870d4351e00367fb67d": 2, "5bc09a18d4351e003562b68e": 2, "5bc5a351d4351e003477a414": 1, - "5bc9b156d4351e00367fbce9": 10, - "5bc9c29cd4351e003562b8a3": 31, + "5bc9b156d4351e00367fbce9": 12, + "5bc9c29cd4351e003562b8a3": 32, "5be4038986f774527d3fae60": 3, "5beec8b20db834001961942a": 1, "5bfea7ad0db834001c38f1ee": 1, @@ -3163,7 +3191,7 @@ "5c0e531286f7747fa54205c2": 13, "5c0e531d86f7747fa23f4d42": 40, "5c0e533786f7747fa23f4d47": 21, - "5c0e534186f7747fa1419867": 11, + "5c0e534186f7747fa1419867": 13, "5c0fa877d174af02a012e1cf": 35, "5c0fafb6d174af02a96260ba": 1, "5c10c8fd86f7743d7d706df3": 11, @@ -3200,7 +3228,7 @@ "5cc80f38e4a949001152b560": 1, "5cc80f53e4a949000e1ea4f8": 1, "5cc80f67e4a949035e43bbba": 2, - "5cc80f8fe4a949033b0224a2": 6, + "5cc80f8fe4a949033b0224a2": 7, "5cc86840d7f00c002412c56c": 4, "5cc9ad73d7f00c000e2579d4": 1, "5cdeaca5d7f00c00b61c4b70": 1, @@ -3230,7 +3258,7 @@ "5d40407c86f774318526545a": 17, "5d4406a8a4b9361e4f6eb8b7": 2, "5d44334ba4b9362b346d1948": 1, - "5d6e6806a4b936088465b17e": 3, + "5d6e6806a4b936088465b17e": 4, "5d6e6869a4b9361c140bcfde": 2, "5d6e689ca4b9361bc8618956": 1, "5d6e68b3a4b9361bca7e50b5": 2, @@ -3260,8 +3288,8 @@ "5da743f586f7744014504f72": 2, "5dcbe965e4ed22586443a79d": 1, "5de8ea8ffd6b4e6e2276dc35": 1, - "5df8a6a186f77412640e2e80": 48, - "5df8a72c86f77412640e2e83": 36, + "5df8a6a186f77412640e2e80": 46, + "5df8a72c86f77412640e2e83": 35, "5df8a77486f77412672a1e3f": 7, "5dfa3cd1b33c0951220c079b": 2, "5e023cf8186a883be655e54f": 2, @@ -3269,11 +3297,12 @@ "5e023e88277cce2b522ff2b1": 1, "5e208b9842457a4a7a33d074": 1, "5e2aee0a86f774755a234b62": 1, + "5e2aef7986f7746d3f3c33f5": 1, "5e42c71586f7747f245e1343": 2, "5e569a2e56edd02abe09f280": 1, "5e81f423763d9f754677bf2e": 1, - "5e831507ea0a7c419c2f9bd9": 449, - "5e8488fa988a8701445df1e4": 36, + "5e831507ea0a7c419c2f9bd9": 458, + "5e8488fa988a8701445df1e4": 37, "5e85a9a6eacf8c039e4e2ac1": 2, "5e85aa1a988a8701445df1f5": 2, "5e8f3423fd7471236e6e3b64": 24, @@ -3281,7 +3310,7 @@ "5ed515c8d380ab312177c0fa": 6, "5ed515e03a40a50460332579": 5, "5ed515ece452db0eb56fc028": 5, - "5ed515f6915ec335206e4152": 5, + "5ed515f6915ec335206e4152": 6, "5ed5160a87bb8443d10680b5": 8, "5ed51652f6c34d2cc26336a1": 6, "5ed5166ad380ab312177c100": 4, @@ -3299,6 +3328,7 @@ "5efb0e16aeb21837e749c7ff": 2, "5f2aa43ba9b91d26f20ae6d2": 1, "5f6331e097199b7db2128dc2": 1, + "5f647f31b6238e5dd066e196": 1, "5fb653962b1b027b1f50bd03": 1, "5fb6567747ce63734e3fa1dc": 1, "5fbcc429900b1d5091531dd7": 1, @@ -3410,17 +3440,19 @@ "64c196ad26a15b84aa07132f": 2, "64ccc1d4a0f13c24561edf27": 1, "64ccc1ec1779ad6ba200a137": 1, + "64ccc206793ca11c8f450a38": 1, "64ccc2111779ad6ba200a139": 1, "64ccc246ff54fb38131acf29": 2, "64ccc24de61ea448b507d34d": 2, "64ccc268c41e91416064ebc7": 1, "6516b129609aaf354b34b3a8": 1, "6516e91f609aaf354b34b3e2": 2, + "651a8e529829226ceb67c319": 1, "6529370c405a5f51dd023db8": 1, "65293c38fc460e50a509cb25": 1, "65293c7a17e14363030ad308": 1, "653ecef836fae5a82f02b869": 1, - "656df4fec921ad01000481a2": 72, + "656df4fec921ad01000481a2": 73, "6576f96220d53a5b8f3e395e": 1, "65815f0e647e3d7246384e14": 31, "6581998038c79576a2569e11": 4, @@ -3430,14 +3462,14 @@ "6582dc5740562727a654ebb1": 1 }, "Pockets": { - "5448be9a4bdc2dfd2f8b456a": 366, - "5448ff904bdc2d6f028b456e": 68, - "5449016a4bdc2d6f028b456f": 378, - "544fb25a4bdc2dfb738b4567": 157, - "544fb3364bdc2d34748b456a": 137, - "544fb37f4bdc2dee738b4567": 105, - "544fb3f34bdc2d03748b456a": 24, - "544fb6cc4bdc2d34748b456e": 64, + "5448be9a4bdc2dfd2f8b456a": 372, + "5448ff904bdc2d6f028b456e": 70, + "5449016a4bdc2d6f028b456f": 381, + "544fb25a4bdc2dfb738b4567": 159, + "544fb3364bdc2d34748b456a": 139, + "544fb37f4bdc2dee738b4567": 108, + "544fb3f34bdc2d03748b456a": 25, + "544fb6cc4bdc2d34748b456e": 68, "5673de654bdc2d180f8b456d": 48, "56742c284bdc2d98058b456d": 1, "56742c2e4bdc2d95058b456d": 1, @@ -3453,27 +3485,27 @@ "57347baf24597738002c6178": 1, "57347c1124597737fb1379e3": 4, "57347c5b245977448d35f6e1": 4, - "57347c77245977448d35f6e2": 2, + "57347c77245977448d35f6e2": 3, "57347c93245977448d35f6e3": 3, "57347cd0245977445a2d6ff1": 1, "57347d3d245977448f7b7f61": 78, - "57347d5f245977448b40fa81": 67, + "57347d5f245977448b40fa81": 70, "57347d692459774491567cf1": 83, "57347d7224597744596b4e72": 69, "57347d8724597744596b4e76": 70, - "57347d9c245977448b40fa85": 68, + "57347d9c245977448b40fa85": 69, "57347da92459774491567cf5": 72, - "57505f6224597709a92585a9": 61, + "57505f6224597709a92585a9": 62, "575062b524597720a31c09a1": 63, "5751435d24597720a27126d1": 40, - "57514643245977207f2c2d09": 52, + "57514643245977207f2c2d09": 53, "5751487e245977207e26a315": 89, - "5751496424597720a27126da": 124, - "5751a25924597722c463c472": 159, + "5751496424597720a27126da": 125, + "5751a25924597722c463c472": 160, "5751a89d24597722aa0e8db0": 11, "5755356824597772cb798962": 79, "5755383e24597772cb798966": 15, - "5783c43d2459774bbe137486": 189, + "5783c43d2459774bbe137486": 190, "5909e99886f7740c983b9984": 2, "590a358486f77429692b2790": 4, "590a373286f774287540368b": 1, @@ -3483,14 +3515,14 @@ "590c2d8786f774245b1f03f3": 1, "590c31c586f774245e3141b2": 1, "590c5bbd86f774785762df04": 1, - "590c678286f77426c9660122": 21, - "590c695186f7741e566b64a2": 21, - "59e3577886f774176a362503": 73, + "590c678286f77426c9660122": 22, + "590c695186f7741e566b64a2": 22, + "59e3577886f774176a362503": 76, "59e35abd86f7741778269d82": 2, "59e35ef086f7741777737012": 1, "59e3606886f77417674759a5": 2, "59e361e886f774176c10a2a5": 1, - "5a0c27731526d80618476ac4": 284, + "5a0c27731526d80618476ac4": 289, "5af0454c86f7746bf20992e8": 73, "5af0484c86f7740f02001f7f": 2, "5af0548586f7743a532b7e99": 21, @@ -3501,7 +3533,7 @@ "5bc9c377d4351e3bac12251b": 1, "5c06779c86f77426e00dd782": 4, "5c06782b86f77426df5407d2": 2, - "5c0e530286f7747fa1419862": 22, + "5c0e530286f7747fa1419862": 23, "5c0e531286f7747fa54205c2": 21, "5c0e531d86f7747fa23f4d42": 49, "5c0e533786f7747fa23f4d47": 24, @@ -3515,42 +3547,43 @@ "5d235b4d86f7742e017bc88a": 1, "5d40425986f7743185265461": 1, "5df8a6a186f77412640e2e80": 1, - "5e2af22086f7746d3f3c33fa": 2, + "5e2af22086f7746d3f3c33fa": 3, "5e2af29386f7746d4159f077": 1, "5e2af2bc86f7746d3f3c33fc": 1, "5e2af51086f7746d3f3c3402": 1, - "5e831507ea0a7c419c2f9bd9": 68, - "5e8488fa988a8701445df1e4": 58, - "5ed515c8d380ab312177c0fa": 20, + "5e831507ea0a7c419c2f9bd9": 69, + "5e8488fa988a8701445df1e4": 59, + "5ed515c8d380ab312177c0fa": 21, "5ed515e03a40a50460332579": 11, "5ed515ece452db0eb56fc028": 14, "5ed515f6915ec335206e4152": 11, "5ed5160a87bb8443d10680b5": 7, - "5ed51652f6c34d2cc26336a1": 11, + "5ed51652f6c34d2cc26336a1": 12, "5ed5166ad380ab312177c100": 3, "5f745ee30acaeb0d490d8c5b": 1, "5fca138c2a7b221b2852a5c6": 2, "5fca13ca637ee0341a484f46": 9, - "60098ad7c2240c0fe85c570a": 52, - "60098af40accd37ef2175f27": 57, - "60098b1705871270cd5352a1": 25, + "60098ad7c2240c0fe85c570a": 53, + "60098af40accd37ef2175f27": 59, + "60098b1705871270cd5352a1": 26, "60391b0fb847c71012789415": 3, - "60b0f6c058e0b0481a09ad11": 44, + "60b0f6c058e0b0481a09ad11": 43, "60b0f93284c20f0feb453da7": 30, "619cc01e0a7c3a1a2731940c": 1, "61bf7b6302b3924be92fa8c3": 1, "61bf83814088ec1a363d7097": 2, "62a09cfe4f842e1bd12da3e4": 1, - "62a09d3bcf4a99369e262447": 51, + "62a09d3bcf4a99369e262447": 52, "637b60c3b7afa97bfc3d7001": 4, "637b612fb7afa97bfc3d7005": 8, "637b6179104668754b72f8f5": 6, "637b620db7afa97bfc3d7009": 9, "637b6251104668754b72f8f9": 3, - "656df4fec921ad01000481a2": 124, - "65815f0e647e3d7246384e14": 37 + "656df4fec921ad01000481a2": 125, + "65815f0e647e3d7246384e14": 38 }, "SecuredContainer": { + "5448be9a4bdc2dfd2f8b456a": 22, "54527a984bdc2d4e668b4567": 1, "54527ac44bdc2d36668b4567": 11, "560d5e524bdc2d25448b4571": 12211, diff --git a/project/assets/database/bots/types/exusec.json b/project/assets/database/bots/types/exusec.json index c2c3d2a1..12c61872 100644 --- a/project/assets/database/bots/types/exusec.json +++ b/project/assets/database/bots/types/exusec.json @@ -2254,6 +2254,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2261,6 +2277,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerbigpipe.json b/project/assets/database/bots/types/followerbigpipe.json index e71353f4..3e95e641 100644 --- a/project/assets/database/bots/types/followerbigpipe.json +++ b/project/assets/database/bots/types/followerbigpipe.json @@ -2053,6 +2053,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2061,6 +2077,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerbirdeye.json b/project/assets/database/bots/types/followerbirdeye.json index e8c3893a..1665610f 100644 --- a/project/assets/database/bots/types/followerbirdeye.json +++ b/project/assets/database/bots/types/followerbirdeye.json @@ -2085,6 +2085,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2093,6 +2109,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerboar.json b/project/assets/database/bots/types/followerboar.json index f0901c0a..f88c81c1 100644 --- a/project/assets/database/bots/types/followerboar.json +++ b/project/assets/database/bots/types/followerboar.json @@ -2253,6 +2253,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 9, @@ -2263,6 +2279,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerboarclose1.json b/project/assets/database/bots/types/followerboarclose1.json index e63103ff..c98cebc5 100644 --- a/project/assets/database/bots/types/followerboarclose1.json +++ b/project/assets/database/bots/types/followerboarclose1.json @@ -2173,6 +2173,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2181,6 +2197,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerboarclose2.json b/project/assets/database/bots/types/followerboarclose2.json index 9584a752..81cbd3b7 100644 --- a/project/assets/database/bots/types/followerboarclose2.json +++ b/project/assets/database/bots/types/followerboarclose2.json @@ -2173,6 +2173,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2181,6 +2197,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerbully.json b/project/assets/database/bots/types/followerbully.json index ba12478a..e56016c1 100644 --- a/project/assets/database/bots/types/followerbully.json +++ b/project/assets/database/bots/types/followerbully.json @@ -2044,6 +2044,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2052,6 +2068,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followergluharassault.json b/project/assets/database/bots/types/followergluharassault.json index c8442a6c..4d196985 100644 --- a/project/assets/database/bots/types/followergluharassault.json +++ b/project/assets/database/bots/types/followergluharassault.json @@ -2212,6 +2212,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2220,6 +2236,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followergluharscout.json b/project/assets/database/bots/types/followergluharscout.json index d83921e3..71fa780a 100644 --- a/project/assets/database/bots/types/followergluharscout.json +++ b/project/assets/database/bots/types/followergluharscout.json @@ -2214,6 +2214,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2222,6 +2238,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followergluharsecurity.json b/project/assets/database/bots/types/followergluharsecurity.json index a17e285f..58c44b55 100644 --- a/project/assets/database/bots/types/followergluharsecurity.json +++ b/project/assets/database/bots/types/followergluharsecurity.json @@ -2217,6 +2217,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2225,6 +2241,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followergluharsnipe.json b/project/assets/database/bots/types/followergluharsnipe.json index 18d7f45a..ce647b42 100644 --- a/project/assets/database/bots/types/followergluharsnipe.json +++ b/project/assets/database/bots/types/followergluharsnipe.json @@ -1,2155 +1,2239 @@ { - "appearance": { - "body": {}, - "feet": {}, - "hands": [], - "head": [], - "voice": [] + "appearance": { + "body": {}, + "feet": {}, + "hands": [], + "head": [], + "voice": [] + }, + "chances": { + "equipment": { + "ArmBand": 0, + "ArmorVest": 0, + "Backpack": 0, + "Earpiece": 0, + "Eyewear": 0, + "FaceCover": 0, + "FirstPrimaryWeapon": 0, + "Headwear": 0, + "Holster": 0, + "Scabbard": 0, + "SecondPrimaryWeapon": 0, + "TacticalVest": 0 }, - "experience": { - "level": { - "min": 0, - "max": 0 - }, - "reward": { - "min": 0, - "max": 0 - }, - "standingForKill": 0 + "mods": {} + }, + "difficulty": { + "easy": { + "Aiming": { + "AIMING_TYPE": 5, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 15, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, + "BASE_HIT_AFFECTION_MAX_ANG": 10, + "BASE_HIT_AFFECTION_MIN_ANG": 4, + "BASE_SHIEF": 0.05, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "BETTER_PRECICING_COEF": 0.9, + "BOTTOM_COEF": 0.1, + "BOT_MOVE_IF_DELTA": 3.01, + "COEF_FROM_COVER": 0.45, + "COEF_IF_MOVE": 1, + "DAMAGE_PANIC_TIME": 15, + "DAMAGE_TO_DISCARD_AIM_0_100": 86, + "DANGER_UP_POINT": 1.3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "DIST_TO_SHOOT_TO_CENTER": 3, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "FIRST_CONTACT_ADD_SEC": 0.1, + "HARD_AIM": 0.75, + "MAX_AIMING_UPGRADE_BY_TIME": 0.25, + "MAX_AIM_PRECICING": 2, + "MAX_AIM_TIME": 1.5, + "MAX_TIME_DISCARD_AIM_SEC": 0.6, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MIN_TIME_DISCARD_AIM_SEC": 0.3, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "PANIC_ACCURATY_COEF": 1.2, + "PANIC_COEF": 1.2, + "PANIC_TIME": 2, + "RECALC_DIST": 0.7, + "RECALC_MUST_TIME": 3, + "RECALC_SQR_DIST": 0.48999998, + "SCATTERING_DIST_MODIF": 0.67, + "SCATTERING_DIST_MODIF_CLOSE": 0.6, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "SHPERE_FRIENDY_FIRE_SIZE": -0.1, + "TIME_COEF_IF_MOVE": 1.1, + "WEAPON_ROOT_OFFSET": 0.35, + "XZ_COEF": 0.1, + "XZ_COEF_STATIONARY_GRENADE": 0.2, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "Y_TOP_OFFSET_COEF": 0.001 + }, + "Boss": { + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "CHANCE_TO_SEND_GRENADE_100": 100, + "CHANCE_USE_RESERVE_PATROL_100": 30, + "COVER_TO_SEND": true, + "DELTA_SEARCH_TIME": 18, + "DIST_TO_PROTECT_BOSS": 15, + "GLUHAR_ASSAULT_ATTACK_DIST": 30, + "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, + "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", + "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, + "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, + "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, + "GLUHAR_TIME_TO_ASSAULT": 10, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_BULLET_TO_RELOAD": 15, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_CONTUTION_TIME": 5, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_HOLD_DELAY": 5, + "KILLA_LARGE_ATTACK_DIST": 61, + "KILLA_MIDDLE_ATTACK_DIST": 32, + "KILLA_ONE_IS_CLOSE": 20, + "KILLA_SEARCH_METERS": 30, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_TRIGGER_DOWN_DELAY": 0.1, + "KILLA_WAIT_IN_COVER_COEF": 0.1, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KOJANIY_COVER_POWER": 500, + "KOJANIY_DIST_CORE_SPOS_RECALC": 25, + "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_FIGHT_CENTER_POS_ME": false, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "PERSONS_SEND": 2, + "SHALL_WARN": true, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "WAIT_NO_ATTACK_SAVAGE": 10 + }, + "Change": { + "FLASH_ACCURATY": 1.6, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_HEARING": 1, + "FLASH_LAY_CHANCE": 1, + "FLASH_PRECICING": 1.6, + "FLASH_SCATTERING": 1.6, + "FLASH_VISION_DIST": 0.05, + "SMOKE_ACCURATY": 1.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_LAY_CHANCE": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_VISION_DIST": 0.6, + "STUN_HEARING": 0.01 + }, + "Core": { + "AccuratySpeed": 0.2, + "AimingType": "normal", + "CanGrenade": true, + "CanRun": true, + "DamageCoeff": 1, + "GainSightCoef": 0.1, + "HearingSense": 3.9, + "PistolFireDistancePref": 35, + "RifleFireDistancePref": 100, + "ScatteringClosePerMeter": 0.12, + "ScatteringPerMeter": 0.045, + "ShotgunFireDistancePref": 50, + "VisibleAngle": 160, + "VisibleDistance": 142, + "WaitInCoverBetweenShotsSec": 0.3 + }, + "Cover": { + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "CHECK_CLOSEST_FRIEND": false, + "CHECK_COVER_ENEMY_LOOK": false, + "CLOSE_DIST_POINT_SQRT": 4, + "DELETE_POINTS_BEHIND_ENEMIES": true, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "DEPENDS_Y_DIST_TO_BOT": false, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "DIST_CHECK_SFETY": 9, + "DOG_FIGHT_AFTER_LEAVE": 4, + "ENEMY_DIST_TO_GO_OUT": 1, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "HIDE_TO_COVER_TIME": 1.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "MAX_DIST_OF_COVER": 4, + "MAX_DIST_OF_COVER_SQR": 16, + "MAX_SPOTTED_TIME_SEC": 55, + "MIN_DEFENCE_LEVEL": 22, + "MIN_DIST_TO_ENEMY": 9, + "MOVE_TO_COVER_WHEN_TARGET": false, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "REWORK_NOT_TO_SHOOT": true, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "RUN_IF_FAR": 15, + "RUN_IF_FAR_SQRT": 225, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "SHOOT_NEAR_TO_LEAVE": 2, + "SOUND_TO_GET_SPOTTED": 2, + "SPOTTED_COVERS_RADIUS": 2.5, + "SPOTTED_GRENADE_RADIUS": 16, + "SPOTTED_GRENADE_TIME": 7, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "TIME_CHECK_SAFE": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "WAIT_INT_COVER_FINDING_ENEMY": 2 + }, + "Grenade": { + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "ANG_TYPE": 1, + "BEWARE_TYPE": 2, + "BE_ATTENTION_COEF": 4, + "CAN_THROW_STRAIGHT_CONTACT": true, + "CHANCE_RUN_FLASHED_100": 100, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100, + "CHEAT_START_GRENADE_PLACE": false, + "CLOSE_TO_SMOKE_TIME_DELTA": 5, + "CLOSE_TO_SMOKE_TO_SHOOT": 10, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "DELTA_GRENADE_START_TIME": 0.01, + "DELTA_NEXT_ATTEMPT": 10, + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "FLASH_GRENADE_TIME_COEF": 0.25, + "GrenadePerMeter": 0.1, + "GrenadePrecision": 0.1, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "MAX_THROW_POWER": 25, + "MIN_DIST_NOT_TO_THROW": 8, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "MIN_THROW_DIST_PERCENT_0_1": 0.7, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "NO_RUN_FROM_AI_GRENADES": true, + "REQUEST_DIST_MUST_THROW": 3, + "REQUEST_DIST_MUST_THROW_SQRT": 9, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "SHOOT_TO_SMOKE_CHANCE_100": 50, + "SIZE_SPOTTED_COEF": 2, + "SMOKE_CHECK_DELTA": 1, + "SMOKE_SUPPRESS_DELTA": 20, + "STOP_WHEN_THROW_GRENADE": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "STUN_SUPPRESS_DELTA": 9, + "TIME_SHOOT_TO_FLASH": 4, + "WAIT_TIME_TURN_AWAY": 0.2 + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 1, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, + "CLOSE_DIST": 26, + "DEAD_BODY_SOUND_RAD": 30, + "DISPERSION_COEF": 10, + "DIST_PLACE_TO_FIND_POINT": 70, + "FAR_DIST": 56, + "HEAR_DELAY_WHEN_HAVE_SMT": 0, + "HEAR_DELAY_WHEN_PEACE": 0, + "LOOK_ONLY_DANGER": false, + "LOOK_ONLY_DANGER_DELTA": 9, + "RESET_TIMER_DIST": 17, + "SOUND_DIR_DEEFREE": 30 + }, + "Lay": { + "ATTACK_LAY_CHANCE": 25, + "CHECK_SHOOT_WHEN_LAYING": false, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "DAMAGE_TIME_TO_GETUP": 3, + "DELTA_AFTER_GETUP": 10, + "DELTA_GETUP": 2.7, + "DELTA_LAY_CHECK": 2, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "LAY_AIM": 0.6, + "LAY_CHANCE_DANGER": 40, + "MAX_CAN_LAY_DIST": 200, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_LAY_TIME": 35, + "MIN_CAN_LAY_DIST": 11, + "MIN_CAN_LAY_DIST_SQRT": 121 + }, + "Look": { + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "CAN_LOOK_TO_WALL": true, + "COME_TO_BODY_DIST": 1.2, + "CloseDeltaTimeSec": 0.1, + "DIST_CHECK_WALL": 20, + "DIST_NOT_TO_IGNORE_WALL": 15, + "ENEMY_LIGHT_ADD": 48, + "ENEMY_LIGHT_START_DIST": 90, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "GOAL_TO_FULL_DISSAPEAR": 1.1, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, + "LOOK_AROUND_DELTA": 1.1, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "LightOnVisionDistance": 45, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "MAX_VISION_GRASS_METERS": 0.8, + "MAX_VISION_GRASS_METERS_FLARE": 8, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MIDDLE_DIST": 90, + "MIN_LOOK_AROUD_TIME": 20, + "MiddleDeltaTimeSec": 1, + "OLD_TIME_POINT": 11, + "OPTIMIZE_TO_ONLY_BODY": true, + "POSIBLE_VISION_SPACE": 1.2, + "VISIBLE_DISNACE_WITH_LIGHT": 100, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8 + }, + "Mind": { + "AI_POWER_COEF": 120, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "BULLET_FEEL_CLOSE_SDIST": 1, + "BULLET_FEEL_DIST": 360, + "CAN_PANIC_IS_PROTECT": false, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_STAND_BY": false, + "CAN_TAKE_ITEMS": false, + "CAN_THROW_REQUESTS": true, + "CAN_USE_MEDS": true, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "COVER_DIST_COEF": 1.5, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "DANGER_EXPIRE_TIME_MAX": 1.2, + "DANGER_EXPIRE_TIME_MIN": 0.4, + "DANGER_POINT_CHOOSE_COEF": 1, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "DIST_TO_FOUND_SQRT": 400, + "DIST_TO_STOP_RUN_ENEMY": 15, + "DOG_FIGHT_IN": 3, + "DOG_FIGHT_OUT": 6, + "ENEMY_LOOK_AT_ME_ANG": 15, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "FRIEND_AGR_KILL": 0.2, + "FRIEND_DEAD_AGR_LOW": -0.2, + "GROUP_ANY_PHRASE_DELAY": 20, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "HIT_POINT_DETECTION": 4, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "MAX_AGGRO_BOT_DIST": 100, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "MAX_SHOOTS_TIME": 4, + "MAX_START_AGGRESION_COEF": 3, + "MIN_DAMAGE_SCARE": 20, + "MIN_SHOOTS_TIME": 2, + "MIN_START_AGGRESION_COEF": 1, + "NO_RUN_AWAY_FOR_SAFE": true, + "PANIC_LAY_WEIGHT": 20, + "PANIC_NONE_WEIGHT": 40, + "PANIC_RUN_WEIGHT": 1, + "PANIC_SIT_WEIGHT": 80, + "PANIC_SIT_WEIGHT_PEACE": 60, + "PART_PERCENT_TO_HEAL": 0.65, + "PISTOL_SHOTGUN_AMBUSH_DIST": 30, + "PROTECT_DELTA_HEAL_SEC": 10, + "PROTECT_TIME_REAL": true, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "STANDART_AMBUSH_DIST": 100, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "TALK_WITH_QUERY": true, + "TIME_TO_FIND_ENEMY": 22, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15 + }, + "Move": { + "BASESTART_SLOW_DIST": 1.1, + "BASE_ROTATE_SPEED": 270, + "BASE_SQRT_START_SERACH": 1225, + "BASE_START_SERACH": 35, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "DELTA_LAST_SEEN_ENEMY": 20, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST": 15, + "DIST_TO_START_RAYCAST_SQR": 225, + "ETERNITY_STAMINA": true, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "REACH_DIST": 0.5, + "REACH_DIST_COVER": 2, + "REACH_DIST_RUN": 0.8, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "RUN_TO_COVER_MIN": 2, + "SEC_TO_CHANGE_TO_RUN": 3, + "SLOW_COEF": 7, + "START_SLOW_DIST": 1.5, + "UPDATE_TIME_RECAL_WAY": 7, + "Y_APPROXIMATION": 0.7 + }, + "Patrol": { + "CAN_CHOOSE_RESERV": true, + "CHANCE_TO_CHANGE_WAY_0_100": 30, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "CHANGE_WAY_TIME": 3325.1, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "CUT_WAY_MAX_0_1": 0.65, + "CUT_WAY_MIN_0_1": 0.4, + "FRIEND_SEARCH_SEC": 12, + "LOOK_TIME_BASE": 12, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "MIN_DIST_TO_CLOSE_TALK": 5, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "MIN_TALK_DELAY": 35, + "RESERVE_OUT_TIME": 60, + "RESERVE_TIME_STAY": 72, + "SUSPETION_PLACE_LIFETIME": 7, + "TALK_DELAY": 31.1, + "TALK_DELAY_BIG": 45.1, + "TRY_CHOOSE_RESERV_WAY_ON_START": true, + "VISION_DIST_COEF_PEACE": 1 + }, + "Scattering": { + "AMPLITUDE_FACTOR": 0.25, + "AMPLITUDE_SPEED": 0.1, + "BloodFall": 1.45, + "Caution": 0.3, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "FromShot": 0.001, + "HandDamageAccuracySpeed": 1.3, + "HandDamageScatteringMinMax": 0.7, + "LayFactor": 0.1, + "MaxScatter": 0.4, + "MinScatter": 0.03, + "MovingSlowCoef": 1.5, + "PoseChnageCoef": 0.1, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1, + "SpeedDown": -0.3, + "SpeedUp": 0.3, + "SpeedUpAim": 1.4, + "ToCaution": 0.6, + "ToLowBotAngularSpeed": 80, + "ToLowBotSpeed": 2.4, + "ToSlowBotSpeed": 1.5, + "ToStopBotAngularSpeed": 40, + "ToUpBotSpeed": 3.6, + "TracerCoef": 1.3, + "WorkingScatter": 0.15 + }, + "Shoot": { + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "BASE_AUTOMATIC_TIME": 0.2, + "CAN_SHOOTS_TIME_TO_AMBUSH": 993, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94, + "CHANCE_TO_CHANGE_WEAPON": 100, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5, + "DIST_TO_CHANGE_TO_MAIN": 15, + "FAR_DIST_ENEMY": 20, + "FAR_DIST_ENEMY_SQR": 400, + "FAR_DIST_TO_CHANGE_WEAPON": 30, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "HORIZONT_RECOIL_COEF": 0.1, + "LOW_DIST_TO_CHANGE_WEAPON": 5, + "MARKSMAN_DIST_SEK_COEF": 44, + "MAX_DIST_COEF": 1.35, + "MAX_RECOIL_PER_METER": 0.1, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RECOIL_DELTA_PRESS": 0.15, + "RECOIL_PER_METER": 0.02, + "RECOIL_TIME_NORMALIZE": 1, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "SHOOT_FROM_COVER": 4, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "VALIDATE_MALFUNCTION_CHANCE": 0, + "WAIT_NEXT_SINGLE_SHOT": 0.2, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, + "WAIT_NEXT_STATIONARY_GRENADE": 1 + } }, - "health": { - "Hydration": { - "min": 0, - "max": 0 - }, - "Energy": { - "min": 0, - "max": 0 - }, - "Temperature": { - "min": 0, - "max": 0 - }, - "BodyParts": [{ - "Head": { - "min": 0, - "max": 0 - }, - "Chest": { - "min": 0, - "max": 0 - }, - "Stomach": { - "min": 0, - "max": 0 - }, - "LeftArm": { - "min": 0, - "max": 0 - }, - "RightArm": { - "min": 0, - "max": 0 - }, - "LeftLeg": { - "min": 0, - "max": 0 - }, - "RightLeg": { - "min": 0, - "max": 0 - } - } - ] + "hard": { + "Aiming": { + "AIMING_TYPE": 5, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 15, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, + "BASE_HIT_AFFECTION_MAX_ANG": 10, + "BASE_HIT_AFFECTION_MIN_ANG": 4, + "BASE_SHIEF": 0.05, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "BETTER_PRECICING_COEF": 0.9, + "BOTTOM_COEF": 0.1, + "BOT_MOVE_IF_DELTA": 3.01, + "COEF_FROM_COVER": 0.45, + "COEF_IF_MOVE": 1, + "DAMAGE_PANIC_TIME": 15, + "DAMAGE_TO_DISCARD_AIM_0_100": 86, + "DANGER_UP_POINT": 1.3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "DIST_TO_SHOOT_TO_CENTER": 3, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "FIRST_CONTACT_ADD_SEC": 0.1, + "HARD_AIM": 0.75, + "MAX_AIMING_UPGRADE_BY_TIME": 0.25, + "MAX_AIM_PRECICING": 2, + "MAX_AIM_TIME": 1.5, + "MAX_TIME_DISCARD_AIM_SEC": 0.6, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MIN_TIME_DISCARD_AIM_SEC": 0.3, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "PANIC_ACCURATY_COEF": 1.2, + "PANIC_COEF": 1.2, + "PANIC_TIME": 2, + "RECALC_DIST": 0.7, + "RECALC_MUST_TIME": 3, + "RECALC_SQR_DIST": 0.48999998, + "SCATTERING_DIST_MODIF": 0.67, + "SCATTERING_DIST_MODIF_CLOSE": 0.6, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "SHPERE_FRIENDY_FIRE_SIZE": -0.1, + "TIME_COEF_IF_MOVE": 1.1, + "WEAPON_ROOT_OFFSET": 0.35, + "XZ_COEF": 0.1, + "XZ_COEF_STATIONARY_GRENADE": 0.2, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "Y_TOP_OFFSET_COEF": 0.001 + }, + "Boss": { + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "CHANCE_TO_SEND_GRENADE_100": 100, + "CHANCE_USE_RESERVE_PATROL_100": 30, + "COVER_TO_SEND": true, + "DELTA_SEARCH_TIME": 18, + "DIST_TO_PROTECT_BOSS": 15, + "GLUHAR_ASSAULT_ATTACK_DIST": 30, + "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, + "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", + "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, + "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, + "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, + "GLUHAR_TIME_TO_ASSAULT": 10, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_BULLET_TO_RELOAD": 15, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_CONTUTION_TIME": 5, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_HOLD_DELAY": 5, + "KILLA_LARGE_ATTACK_DIST": 61, + "KILLA_MIDDLE_ATTACK_DIST": 32, + "KILLA_ONE_IS_CLOSE": 20, + "KILLA_SEARCH_METERS": 30, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_TRIGGER_DOWN_DELAY": 0.1, + "KILLA_WAIT_IN_COVER_COEF": 0.1, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KOJANIY_COVER_POWER": 500, + "KOJANIY_DIST_CORE_SPOS_RECALC": 25, + "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_FIGHT_CENTER_POS_ME": false, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "PERSONS_SEND": 2, + "SHALL_WARN": true, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "WAIT_NO_ATTACK_SAVAGE": 10 + }, + "Change": { + "FLASH_ACCURATY": 1.6, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_HEARING": 1, + "FLASH_LAY_CHANCE": 1, + "FLASH_PRECICING": 1.6, + "FLASH_SCATTERING": 1.6, + "FLASH_VISION_DIST": 0.05, + "SMOKE_ACCURATY": 1.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_LAY_CHANCE": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_VISION_DIST": 0.6, + "STUN_HEARING": 0.01 + }, + "Core": { + "AccuratySpeed": 0.2, + "AimingType": "normal", + "CanGrenade": true, + "CanRun": true, + "DamageCoeff": 1, + "GainSightCoef": 0.1, + "HearingSense": 3.9, + "PistolFireDistancePref": 35, + "RifleFireDistancePref": 100, + "ScatteringClosePerMeter": 0.12, + "ScatteringPerMeter": 0.045, + "ShotgunFireDistancePref": 50, + "VisibleAngle": 160, + "VisibleDistance": 142, + "WaitInCoverBetweenShotsSec": 0.3 + }, + "Cover": { + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "CHECK_CLOSEST_FRIEND": false, + "CHECK_COVER_ENEMY_LOOK": false, + "CLOSE_DIST_POINT_SQRT": 4, + "DELETE_POINTS_BEHIND_ENEMIES": true, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "DEPENDS_Y_DIST_TO_BOT": false, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "DIST_CHECK_SFETY": 9, + "DOG_FIGHT_AFTER_LEAVE": 4, + "ENEMY_DIST_TO_GO_OUT": 1, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "HIDE_TO_COVER_TIME": 1.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "MAX_DIST_OF_COVER": 4, + "MAX_DIST_OF_COVER_SQR": 16, + "MAX_SPOTTED_TIME_SEC": 55, + "MIN_DEFENCE_LEVEL": 22, + "MIN_DIST_TO_ENEMY": 9, + "MOVE_TO_COVER_WHEN_TARGET": false, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "REWORK_NOT_TO_SHOOT": true, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "RUN_IF_FAR": 15, + "RUN_IF_FAR_SQRT": 225, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "SHOOT_NEAR_TO_LEAVE": 2, + "SOUND_TO_GET_SPOTTED": 2, + "SPOTTED_COVERS_RADIUS": 2.5, + "SPOTTED_GRENADE_RADIUS": 16, + "SPOTTED_GRENADE_TIME": 7, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "TIME_CHECK_SAFE": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "WAIT_INT_COVER_FINDING_ENEMY": 2 + }, + "Grenade": { + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "ANG_TYPE": 1, + "BEWARE_TYPE": 2, + "BE_ATTENTION_COEF": 4, + "CAN_THROW_STRAIGHT_CONTACT": true, + "CHANCE_RUN_FLASHED_100": 100, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100, + "CHEAT_START_GRENADE_PLACE": false, + "CLOSE_TO_SMOKE_TIME_DELTA": 5, + "CLOSE_TO_SMOKE_TO_SHOOT": 10, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "DELTA_GRENADE_START_TIME": 0.01, + "DELTA_NEXT_ATTEMPT": 10, + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "FLASH_GRENADE_TIME_COEF": 0.25, + "GrenadePerMeter": 0.1, + "GrenadePrecision": 0.1, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "MAX_THROW_POWER": 25, + "MIN_DIST_NOT_TO_THROW": 8, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "MIN_THROW_DIST_PERCENT_0_1": 0.7, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "NO_RUN_FROM_AI_GRENADES": true, + "REQUEST_DIST_MUST_THROW": 3, + "REQUEST_DIST_MUST_THROW_SQRT": 9, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "SHOOT_TO_SMOKE_CHANCE_100": 50, + "SIZE_SPOTTED_COEF": 2, + "SMOKE_CHECK_DELTA": 1, + "SMOKE_SUPPRESS_DELTA": 20, + "STOP_WHEN_THROW_GRENADE": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "STUN_SUPPRESS_DELTA": 9, + "TIME_SHOOT_TO_FLASH": 4, + "WAIT_TIME_TURN_AWAY": 0.2 + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 1, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, + "CLOSE_DIST": 26, + "DEAD_BODY_SOUND_RAD": 30, + "DISPERSION_COEF": 10, + "DIST_PLACE_TO_FIND_POINT": 70, + "FAR_DIST": 56, + "HEAR_DELAY_WHEN_HAVE_SMT": 0, + "HEAR_DELAY_WHEN_PEACE": 0, + "LOOK_ONLY_DANGER": false, + "LOOK_ONLY_DANGER_DELTA": 9, + "RESET_TIMER_DIST": 17, + "SOUND_DIR_DEEFREE": 30 + }, + "Lay": { + "ATTACK_LAY_CHANCE": 25, + "CHECK_SHOOT_WHEN_LAYING": false, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "DAMAGE_TIME_TO_GETUP": 3, + "DELTA_AFTER_GETUP": 10, + "DELTA_GETUP": 2.7, + "DELTA_LAY_CHECK": 2, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "LAY_AIM": 0.6, + "LAY_CHANCE_DANGER": 40, + "MAX_CAN_LAY_DIST": 200, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_LAY_TIME": 35, + "MIN_CAN_LAY_DIST": 11, + "MIN_CAN_LAY_DIST_SQRT": 121 + }, + "Look": { + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "CAN_LOOK_TO_WALL": true, + "COME_TO_BODY_DIST": 1.2, + "CloseDeltaTimeSec": 0.1, + "DIST_CHECK_WALL": 20, + "DIST_NOT_TO_IGNORE_WALL": 15, + "ENEMY_LIGHT_ADD": 48, + "ENEMY_LIGHT_START_DIST": 90, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "GOAL_TO_FULL_DISSAPEAR": 1.1, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, + "LOOK_AROUND_DELTA": 1.1, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "LightOnVisionDistance": 45, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "MAX_VISION_GRASS_METERS": 0.8, + "MAX_VISION_GRASS_METERS_FLARE": 8, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MIDDLE_DIST": 90, + "MIN_LOOK_AROUD_TIME": 20, + "MiddleDeltaTimeSec": 1, + "OLD_TIME_POINT": 11, + "OPTIMIZE_TO_ONLY_BODY": true, + "POSIBLE_VISION_SPACE": 1.2, + "VISIBLE_DISNACE_WITH_LIGHT": 100, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8 + }, + "Mind": { + "AI_POWER_COEF": 120, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "BULLET_FEEL_CLOSE_SDIST": 1, + "BULLET_FEEL_DIST": 360, + "CAN_PANIC_IS_PROTECT": false, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_STAND_BY": false, + "CAN_TAKE_ITEMS": false, + "CAN_THROW_REQUESTS": true, + "CAN_USE_MEDS": true, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "COVER_DIST_COEF": 1.5, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "DANGER_EXPIRE_TIME_MAX": 1.2, + "DANGER_EXPIRE_TIME_MIN": 0.4, + "DANGER_POINT_CHOOSE_COEF": 1, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "DIST_TO_FOUND_SQRT": 400, + "DIST_TO_STOP_RUN_ENEMY": 15, + "DOG_FIGHT_IN": 3, + "DOG_FIGHT_OUT": 6, + "ENEMY_LOOK_AT_ME_ANG": 15, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "FRIEND_AGR_KILL": 0.2, + "FRIEND_DEAD_AGR_LOW": -0.2, + "GROUP_ANY_PHRASE_DELAY": 20, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "HIT_POINT_DETECTION": 4, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "MAX_AGGRO_BOT_DIST": 100, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "MAX_SHOOTS_TIME": 4, + "MAX_START_AGGRESION_COEF": 3, + "MIN_DAMAGE_SCARE": 20, + "MIN_SHOOTS_TIME": 2, + "MIN_START_AGGRESION_COEF": 1, + "NO_RUN_AWAY_FOR_SAFE": true, + "PANIC_LAY_WEIGHT": 20, + "PANIC_NONE_WEIGHT": 40, + "PANIC_RUN_WEIGHT": 1, + "PANIC_SIT_WEIGHT": 80, + "PANIC_SIT_WEIGHT_PEACE": 60, + "PART_PERCENT_TO_HEAL": 0.65, + "PISTOL_SHOTGUN_AMBUSH_DIST": 30, + "PROTECT_DELTA_HEAL_SEC": 10, + "PROTECT_TIME_REAL": true, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "STANDART_AMBUSH_DIST": 100, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "TALK_WITH_QUERY": true, + "TIME_TO_FIND_ENEMY": 22, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15 + }, + "Move": { + "BASESTART_SLOW_DIST": 1.1, + "BASE_ROTATE_SPEED": 270, + "BASE_SQRT_START_SERACH": 1225, + "BASE_START_SERACH": 35, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "DELTA_LAST_SEEN_ENEMY": 20, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST": 15, + "DIST_TO_START_RAYCAST_SQR": 225, + "ETERNITY_STAMINA": true, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "REACH_DIST": 0.5, + "REACH_DIST_COVER": 2, + "REACH_DIST_RUN": 0.8, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "RUN_TO_COVER_MIN": 2, + "SEC_TO_CHANGE_TO_RUN": 3, + "SLOW_COEF": 7, + "START_SLOW_DIST": 1.5, + "UPDATE_TIME_RECAL_WAY": 7, + "Y_APPROXIMATION": 0.7 + }, + "Patrol": { + "CAN_CHOOSE_RESERV": true, + "CHANCE_TO_CHANGE_WAY_0_100": 30, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "CHANGE_WAY_TIME": 3325.1, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "CUT_WAY_MAX_0_1": 0.65, + "CUT_WAY_MIN_0_1": 0.4, + "FRIEND_SEARCH_SEC": 12, + "LOOK_TIME_BASE": 12, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "MIN_DIST_TO_CLOSE_TALK": 5, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "MIN_TALK_DELAY": 35, + "RESERVE_OUT_TIME": 60, + "RESERVE_TIME_STAY": 72, + "SUSPETION_PLACE_LIFETIME": 7, + "TALK_DELAY": 31.1, + "TALK_DELAY_BIG": 45.1, + "TRY_CHOOSE_RESERV_WAY_ON_START": true, + "VISION_DIST_COEF_PEACE": 1 + }, + "Scattering": { + "AMPLITUDE_FACTOR": 0.25, + "AMPLITUDE_SPEED": 0.1, + "BloodFall": 1.45, + "Caution": 0.3, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "FromShot": 0.001, + "HandDamageAccuracySpeed": 1.3, + "HandDamageScatteringMinMax": 0.7, + "LayFactor": 0.1, + "MaxScatter": 0.4, + "MinScatter": 0.03, + "MovingSlowCoef": 1.5, + "PoseChnageCoef": 0.1, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1, + "SpeedDown": -0.3, + "SpeedUp": 0.3, + "SpeedUpAim": 1.4, + "ToCaution": 0.6, + "ToLowBotAngularSpeed": 80, + "ToLowBotSpeed": 2.4, + "ToSlowBotSpeed": 1.5, + "ToStopBotAngularSpeed": 40, + "ToUpBotSpeed": 3.6, + "TracerCoef": 1.3, + "WorkingScatter": 0.15 + }, + "Shoot": { + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "BASE_AUTOMATIC_TIME": 0.2, + "CAN_SHOOTS_TIME_TO_AMBUSH": 993, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94, + "CHANCE_TO_CHANGE_WEAPON": 100, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5, + "DIST_TO_CHANGE_TO_MAIN": 15, + "FAR_DIST_ENEMY": 20, + "FAR_DIST_ENEMY_SQR": 400, + "FAR_DIST_TO_CHANGE_WEAPON": 30, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "HORIZONT_RECOIL_COEF": 0.1, + "LOW_DIST_TO_CHANGE_WEAPON": 5, + "MARKSMAN_DIST_SEK_COEF": 44, + "MAX_DIST_COEF": 1.35, + "MAX_RECOIL_PER_METER": 0.1, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RECOIL_DELTA_PRESS": 0.15, + "RECOIL_PER_METER": 0.02, + "RECOIL_TIME_NORMALIZE": 1, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "SHOOT_FROM_COVER": 4, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "VALIDATE_MALFUNCTION_CHANCE": 0, + "WAIT_NEXT_SINGLE_SHOT": 0.2, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, + "WAIT_NEXT_STATIONARY_GRENADE": 1 + } }, - "skills": { - "Common": {} + "impossible": { + "Aiming": { + "AIMING_TYPE": 5, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 15, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, + "BASE_HIT_AFFECTION_MAX_ANG": 10, + "BASE_HIT_AFFECTION_MIN_ANG": 4, + "BASE_SHIEF": 0.05, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "BETTER_PRECICING_COEF": 0.9, + "BOTTOM_COEF": 0.1, + "BOT_MOVE_IF_DELTA": 3.01, + "COEF_FROM_COVER": 0.45, + "COEF_IF_MOVE": 1, + "DAMAGE_PANIC_TIME": 15, + "DAMAGE_TO_DISCARD_AIM_0_100": 86, + "DANGER_UP_POINT": 1.3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "DIST_TO_SHOOT_TO_CENTER": 3, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "FIRST_CONTACT_ADD_SEC": 0.1, + "HARD_AIM": 0.75, + "MAX_AIMING_UPGRADE_BY_TIME": 0.25, + "MAX_AIM_PRECICING": 2, + "MAX_AIM_TIME": 1.5, + "MAX_TIME_DISCARD_AIM_SEC": 0.6, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MIN_TIME_DISCARD_AIM_SEC": 0.3, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "PANIC_ACCURATY_COEF": 1.2, + "PANIC_COEF": 1.2, + "PANIC_TIME": 2, + "RECALC_DIST": 0.7, + "RECALC_MUST_TIME": 3, + "RECALC_SQR_DIST": 0.48999998, + "SCATTERING_DIST_MODIF": 0.67, + "SCATTERING_DIST_MODIF_CLOSE": 0.6, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "SHPERE_FRIENDY_FIRE_SIZE": -0.1, + "TIME_COEF_IF_MOVE": 1.1, + "WEAPON_ROOT_OFFSET": 0.35, + "XZ_COEF": 0.1, + "XZ_COEF_STATIONARY_GRENADE": 0.2, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "Y_TOP_OFFSET_COEF": 0.001 + }, + "Boss": { + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "CHANCE_TO_SEND_GRENADE_100": 100, + "CHANCE_USE_RESERVE_PATROL_100": 30, + "COVER_TO_SEND": true, + "DELTA_SEARCH_TIME": 18, + "DIST_TO_PROTECT_BOSS": 15, + "GLUHAR_ASSAULT_ATTACK_DIST": 30, + "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, + "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", + "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, + "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, + "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, + "GLUHAR_TIME_TO_ASSAULT": 10, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_BULLET_TO_RELOAD": 15, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_CONTUTION_TIME": 5, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_HOLD_DELAY": 5, + "KILLA_LARGE_ATTACK_DIST": 61, + "KILLA_MIDDLE_ATTACK_DIST": 32, + "KILLA_ONE_IS_CLOSE": 20, + "KILLA_SEARCH_METERS": 30, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_TRIGGER_DOWN_DELAY": 0.1, + "KILLA_WAIT_IN_COVER_COEF": 0.1, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KOJANIY_COVER_POWER": 500, + "KOJANIY_DIST_CORE_SPOS_RECALC": 25, + "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_FIGHT_CENTER_POS_ME": false, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "PERSONS_SEND": 2, + "SHALL_WARN": true, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "WAIT_NO_ATTACK_SAVAGE": 10 + }, + "Change": { + "FLASH_ACCURATY": 1.6, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_HEARING": 1, + "FLASH_LAY_CHANCE": 1, + "FLASH_PRECICING": 1.6, + "FLASH_SCATTERING": 1.6, + "FLASH_VISION_DIST": 0.05, + "SMOKE_ACCURATY": 1.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_LAY_CHANCE": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_VISION_DIST": 0.6, + "STUN_HEARING": 0.01 + }, + "Core": { + "AccuratySpeed": 0.2, + "AimingType": "normal", + "CanGrenade": true, + "CanRun": true, + "DamageCoeff": 1, + "GainSightCoef": 0.1, + "HearingSense": 3.9, + "PistolFireDistancePref": 35, + "RifleFireDistancePref": 100, + "ScatteringClosePerMeter": 0.12, + "ScatteringPerMeter": 0.045, + "ShotgunFireDistancePref": 50, + "VisibleAngle": 160, + "VisibleDistance": 142, + "WaitInCoverBetweenShotsSec": 0.3 + }, + "Cover": { + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "CHECK_CLOSEST_FRIEND": false, + "CHECK_COVER_ENEMY_LOOK": false, + "CLOSE_DIST_POINT_SQRT": 4, + "DELETE_POINTS_BEHIND_ENEMIES": true, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "DEPENDS_Y_DIST_TO_BOT": false, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "DIST_CHECK_SFETY": 9, + "DOG_FIGHT_AFTER_LEAVE": 4, + "ENEMY_DIST_TO_GO_OUT": 1, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "HIDE_TO_COVER_TIME": 1.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "MAX_DIST_OF_COVER": 4, + "MAX_DIST_OF_COVER_SQR": 16, + "MAX_SPOTTED_TIME_SEC": 55, + "MIN_DEFENCE_LEVEL": 22, + "MIN_DIST_TO_ENEMY": 9, + "MOVE_TO_COVER_WHEN_TARGET": false, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "REWORK_NOT_TO_SHOOT": true, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "RUN_IF_FAR": 15, + "RUN_IF_FAR_SQRT": 225, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "SHOOT_NEAR_TO_LEAVE": 2, + "SOUND_TO_GET_SPOTTED": 2, + "SPOTTED_COVERS_RADIUS": 2.5, + "SPOTTED_GRENADE_RADIUS": 16, + "SPOTTED_GRENADE_TIME": 7, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "TIME_CHECK_SAFE": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "WAIT_INT_COVER_FINDING_ENEMY": 2 + }, + "Grenade": { + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "ANG_TYPE": 1, + "BEWARE_TYPE": 2, + "BE_ATTENTION_COEF": 4, + "CAN_THROW_STRAIGHT_CONTACT": true, + "CHANCE_RUN_FLASHED_100": 100, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100, + "CHEAT_START_GRENADE_PLACE": false, + "CLOSE_TO_SMOKE_TIME_DELTA": 5, + "CLOSE_TO_SMOKE_TO_SHOOT": 10, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "DELTA_GRENADE_START_TIME": 0.01, + "DELTA_NEXT_ATTEMPT": 10, + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "FLASH_GRENADE_TIME_COEF": 0.25, + "GrenadePerMeter": 0.1, + "GrenadePrecision": 0.1, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "MAX_THROW_POWER": 25, + "MIN_DIST_NOT_TO_THROW": 8, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "MIN_THROW_DIST_PERCENT_0_1": 0.7, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "NO_RUN_FROM_AI_GRENADES": true, + "REQUEST_DIST_MUST_THROW": 3, + "REQUEST_DIST_MUST_THROW_SQRT": 9, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "SHOOT_TO_SMOKE_CHANCE_100": 50, + "SIZE_SPOTTED_COEF": 2, + "SMOKE_CHECK_DELTA": 1, + "SMOKE_SUPPRESS_DELTA": 20, + "STOP_WHEN_THROW_GRENADE": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "STUN_SUPPRESS_DELTA": 9, + "TIME_SHOOT_TO_FLASH": 4, + "WAIT_TIME_TURN_AWAY": 0.2 + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 1, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, + "CLOSE_DIST": 26, + "DEAD_BODY_SOUND_RAD": 30, + "DISPERSION_COEF": 10, + "DIST_PLACE_TO_FIND_POINT": 70, + "FAR_DIST": 56, + "HEAR_DELAY_WHEN_HAVE_SMT": 0, + "HEAR_DELAY_WHEN_PEACE": 0, + "LOOK_ONLY_DANGER": false, + "LOOK_ONLY_DANGER_DELTA": 9, + "RESET_TIMER_DIST": 17, + "SOUND_DIR_DEEFREE": 30 + }, + "Lay": { + "ATTACK_LAY_CHANCE": 25, + "CHECK_SHOOT_WHEN_LAYING": false, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "DAMAGE_TIME_TO_GETUP": 3, + "DELTA_AFTER_GETUP": 10, + "DELTA_GETUP": 2.7, + "DELTA_LAY_CHECK": 2, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "LAY_AIM": 0.6, + "LAY_CHANCE_DANGER": 40, + "MAX_CAN_LAY_DIST": 200, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_LAY_TIME": 35, + "MIN_CAN_LAY_DIST": 11, + "MIN_CAN_LAY_DIST_SQRT": 121 + }, + "Look": { + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "CAN_LOOK_TO_WALL": true, + "COME_TO_BODY_DIST": 1.2, + "CloseDeltaTimeSec": 0.1, + "DIST_CHECK_WALL": 20, + "DIST_NOT_TO_IGNORE_WALL": 15, + "ENEMY_LIGHT_ADD": 48, + "ENEMY_LIGHT_START_DIST": 90, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "GOAL_TO_FULL_DISSAPEAR": 1.1, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, + "LOOK_AROUND_DELTA": 1.1, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "LightOnVisionDistance": 45, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "MAX_VISION_GRASS_METERS": 0.8, + "MAX_VISION_GRASS_METERS_FLARE": 8, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MIDDLE_DIST": 90, + "MIN_LOOK_AROUD_TIME": 20, + "MiddleDeltaTimeSec": 1, + "OLD_TIME_POINT": 11, + "OPTIMIZE_TO_ONLY_BODY": true, + "POSIBLE_VISION_SPACE": 1.2, + "VISIBLE_DISNACE_WITH_LIGHT": 100, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8 + }, + "Mind": { + "AI_POWER_COEF": 120, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "BULLET_FEEL_CLOSE_SDIST": 1, + "BULLET_FEEL_DIST": 360, + "CAN_PANIC_IS_PROTECT": false, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_STAND_BY": false, + "CAN_TAKE_ITEMS": false, + "CAN_THROW_REQUESTS": true, + "CAN_USE_MEDS": true, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "COVER_DIST_COEF": 1.5, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "DANGER_EXPIRE_TIME_MAX": 1.2, + "DANGER_EXPIRE_TIME_MIN": 0.4, + "DANGER_POINT_CHOOSE_COEF": 1, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "DIST_TO_FOUND_SQRT": 400, + "DIST_TO_STOP_RUN_ENEMY": 15, + "DOG_FIGHT_IN": 3, + "DOG_FIGHT_OUT": 6, + "ENEMY_LOOK_AT_ME_ANG": 15, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "FRIEND_AGR_KILL": 0.2, + "FRIEND_DEAD_AGR_LOW": -0.2, + "GROUP_ANY_PHRASE_DELAY": 20, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "HIT_POINT_DETECTION": 4, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "MAX_AGGRO_BOT_DIST": 100, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "MAX_SHOOTS_TIME": 4, + "MAX_START_AGGRESION_COEF": 3, + "MIN_DAMAGE_SCARE": 20, + "MIN_SHOOTS_TIME": 2, + "MIN_START_AGGRESION_COEF": 1, + "NO_RUN_AWAY_FOR_SAFE": true, + "PANIC_LAY_WEIGHT": 20, + "PANIC_NONE_WEIGHT": 40, + "PANIC_RUN_WEIGHT": 1, + "PANIC_SIT_WEIGHT": 80, + "PANIC_SIT_WEIGHT_PEACE": 60, + "PART_PERCENT_TO_HEAL": 0.65, + "PISTOL_SHOTGUN_AMBUSH_DIST": 30, + "PROTECT_DELTA_HEAL_SEC": 10, + "PROTECT_TIME_REAL": true, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "STANDART_AMBUSH_DIST": 100, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "TALK_WITH_QUERY": true, + "TIME_TO_FIND_ENEMY": 22, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15 + }, + "Move": { + "BASESTART_SLOW_DIST": 1.1, + "BASE_ROTATE_SPEED": 270, + "BASE_SQRT_START_SERACH": 1225, + "BASE_START_SERACH": 35, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "DELTA_LAST_SEEN_ENEMY": 20, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST": 15, + "DIST_TO_START_RAYCAST_SQR": 225, + "ETERNITY_STAMINA": true, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "REACH_DIST": 0.5, + "REACH_DIST_COVER": 2, + "REACH_DIST_RUN": 0.8, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "RUN_TO_COVER_MIN": 2, + "SEC_TO_CHANGE_TO_RUN": 3, + "SLOW_COEF": 7, + "START_SLOW_DIST": 1.5, + "UPDATE_TIME_RECAL_WAY": 7, + "Y_APPROXIMATION": 0.7 + }, + "Patrol": { + "CAN_CHOOSE_RESERV": true, + "CHANCE_TO_CHANGE_WAY_0_100": 30, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "CHANGE_WAY_TIME": 3325.1, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "CUT_WAY_MAX_0_1": 0.65, + "CUT_WAY_MIN_0_1": 0.4, + "FRIEND_SEARCH_SEC": 12, + "LOOK_TIME_BASE": 12, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "MIN_DIST_TO_CLOSE_TALK": 5, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "MIN_TALK_DELAY": 35, + "RESERVE_OUT_TIME": 60, + "RESERVE_TIME_STAY": 72, + "SUSPETION_PLACE_LIFETIME": 7, + "TALK_DELAY": 31.1, + "TALK_DELAY_BIG": 45.1, + "TRY_CHOOSE_RESERV_WAY_ON_START": true, + "VISION_DIST_COEF_PEACE": 1 + }, + "Scattering": { + "AMPLITUDE_FACTOR": 0.25, + "AMPLITUDE_SPEED": 0.1, + "BloodFall": 1.45, + "Caution": 0.3, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "FromShot": 0.001, + "HandDamageAccuracySpeed": 1.3, + "HandDamageScatteringMinMax": 0.7, + "LayFactor": 0.1, + "MaxScatter": 0.4, + "MinScatter": 0.03, + "MovingSlowCoef": 1.5, + "PoseChnageCoef": 0.1, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1, + "SpeedDown": -0.3, + "SpeedUp": 0.3, + "SpeedUpAim": 1.4, + "ToCaution": 0.6, + "ToLowBotAngularSpeed": 80, + "ToLowBotSpeed": 2.4, + "ToSlowBotSpeed": 1.5, + "ToStopBotAngularSpeed": 40, + "ToUpBotSpeed": 3.6, + "TracerCoef": 1.3, + "WorkingScatter": 0.15 + }, + "Shoot": { + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "BASE_AUTOMATIC_TIME": 0.2, + "CAN_SHOOTS_TIME_TO_AMBUSH": 993, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94, + "CHANCE_TO_CHANGE_WEAPON": 100, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5, + "DIST_TO_CHANGE_TO_MAIN": 15, + "FAR_DIST_ENEMY": 20, + "FAR_DIST_ENEMY_SQR": 400, + "FAR_DIST_TO_CHANGE_WEAPON": 30, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "HORIZONT_RECOIL_COEF": 0.1, + "LOW_DIST_TO_CHANGE_WEAPON": 5, + "MARKSMAN_DIST_SEK_COEF": 44, + "MAX_DIST_COEF": 1.35, + "MAX_RECOIL_PER_METER": 0.1, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RECOIL_DELTA_PRESS": 0.15, + "RECOIL_PER_METER": 0.02, + "RECOIL_TIME_NORMALIZE": 1, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "SHOOT_FROM_COVER": 4, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "VALIDATE_MALFUNCTION_CHANCE": 0, + "WAIT_NEXT_SINGLE_SHOT": 0.2, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, + "WAIT_NEXT_STATIONARY_GRENADE": 1 + } }, - "inventory": { - "equipment": { - "Headwear": [], - "Earpiece": [], - "FaceCover": [], - "ArmorVest": [], - "Eyewear": [], - "ArmBand": [], - "TacticalVest": [], - "Backpack": [], - "FirstPrimaryWeapon": [], - "SecondPrimaryWeapon": [], - "Holster": [], - "Scabbard": [], - "Pockets": [], - "SecuredContainer": [] - }, - "mods": {}, - "items": { - "TacticalVest": [], - "Pockets": [], - "Backpack": [], - "SecuredContainer": [], - "SpecialLoot": [] - } - }, - "firstName": [], - "lastName": [], - "difficulty": { - "easy": { - "Lay": { - "CHECK_SHOOT_WHEN_LAYING": false, - "DELTA_LAY_CHECK": 2.0, - "DELTA_GETUP": 2.7, - "DELTA_AFTER_GETUP": 10.0, - "CLEAR_POINTS_OF_SCARE_SEC": 20.0, - "MAX_LAY_TIME": 35.0, - "DELTA_WANT_LAY_CHECL_SEC": 5.0, - "ATTACK_LAY_CHANCE": 25.0, - "DIST_TO_COVER_TO_LAY": 3.5, - "DIST_TO_COVER_TO_LAY_SQRT": 12.25, - "DIST_GRASS_TERRAIN_SQRT": 0.160000011, - "DIST_ENEMY_NULL_DANGER_LAY": 15.0, - "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225.0, - "DIST_ENEMY_GETUP_LAY": 10.0, - "DIST_ENEMY_GETUP_LAY_SQRT": 100.0, - "DIST_ENEMY_CAN_LAY": 15.0, - "DIST_ENEMY_CAN_LAY_SQRT": 225.0, - "LAY_AIM": 0.6, - "MIN_CAN_LAY_DIST_SQRT": 121.0, - "MIN_CAN_LAY_DIST": 11.0, - "MAX_CAN_LAY_DIST_SQRT": 40000.0, - "MAX_CAN_LAY_DIST": 200.0, - "LAY_CHANCE_DANGER": 40.0, - "DAMAGE_TIME_TO_GETUP": 3 - }, - "Aiming": { - "MAX_AIM_PRECICING": 2.0, - "BETTER_PRECICING_COEF": 0.9, - "RECALC_DIST": 0.7, - "RECALC_SQR_DIST": 0.48999998, - "COEF_FROM_COVER": 0.45, - "PANIC_COEF": 1.2, - "PANIC_ACCURATY_COEF": 1.2, - "HARD_AIM": 0.75, - "PANIC_TIME": 2.0, - "RECALC_MUST_TIME": 3, - "DAMAGE_PANIC_TIME": 15.0, - "DANGER_UP_POINT": 1.3, - "MAX_AIMING_UPGRADE_BY_TIME": 0.25, - "DAMAGE_TO_DISCARD_AIM_0_100": 86.0, - "MIN_TIME_DISCARD_AIM_SEC": 0.3, - "MAX_TIME_DISCARD_AIM_SEC": 0.6, - "XZ_COEF": 0.10, - "SHOOT_TO_CHANGE_PRIORITY": 5525, - "BOTTOM_COEF": 0.1, - "FIRST_CONTACT_ADD_SEC": 0.1, - "FIRST_CONTACT_ADD_CHANCE_100": 80.0, - "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, - "BASE_HIT_AFFECTION_MIN_ANG": 4.0, - "BASE_HIT_AFFECTION_MAX_ANG": 10.0, - "BASE_SHIEF": 0.05, - "SCATTERING_HAVE_DAMAGE_COEF": 2.0, - "SCATTERING_DIST_MODIF": 0.67, - "SCATTERING_DIST_MODIF_CLOSE": 0.6, - "AIMING_TYPE": 5, - "DIST_TO_SHOOT_TO_CENTER": 3.0, - "DIST_TO_SHOOT_NO_OFFSET": 3.0, - "SHPERE_FRIENDY_FIRE_SIZE": -0.1, - "COEF_IF_MOVE": 1.0, - "TIME_COEF_IF_MOVE": 1.1, - "BOT_MOVE_IF_DELTA": 3.01, - "NEXT_SHOT_MISS_CHANCE_100": 100.0, - "NEXT_SHOT_MISS_Y_OFFSET": 1.0, - "ANYTIME_LIGHT_WHEN_AIM_100": -1.0, - "ANY_PART_SHOOT_TIME": 15.0, - "WEAPON_ROOT_OFFSET": 0.35, - "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1.0, - "MAX_AIM_TIME": 1.5, - "OFFSET_RECAL_ANYWAY_TIME": 1.0, - "BASE_SHIEF_STATIONARY_GRENADE": 1.1, - "XZ_COEF_STATIONARY_GRENADE": 0.2, - "Y_TOP_OFFSET_COEF": 0.001, - "Y_BOTTOM_OFFSET_COEF": 0.015 - }, - "Look": { - "OLD_TIME_POINT": 11.0, - "WAIT_NEW_SENSOR": 2.1, - "WAIT_NEW__LOOK_SENSOR": 7.8, - "LOOK_AROUND_DELTA": 1.1, - "MAX_VISION_GRASS_METERS": 0.8, - "MAX_VISION_GRASS_METERS_FLARE": 8.0, - "MAX_VISION_GRASS_METERS_OPT": 0.9090909, - "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, - "LightOnVisionDistance": 45.0, - "FAR_DISTANCE": 160.0, - "FarDeltaTimeSec": 3.0, - "MIDDLE_DIST": 90.0, - "MiddleDeltaTimeSec": 1.0, - "CloseDeltaTimeSec": 0.1, - "POSIBLE_VISION_SPACE": 1.2, - "GOAL_TO_FULL_DISSAPEAR": 1.1, - "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, - "BODY_DELTA_TIME_SEARCH_SEC": 1.7, - "COME_TO_BODY_DIST": 1.2, - "MARKSMAN_VISIBLE_DIST_COEF": 1.15, - "VISIBLE_DISNACE_WITH_LIGHT": 100.0, - "ENEMY_LIGHT_ADD": 48.0, - "ENEMY_LIGHT_START_DIST": 90.0, - "CAN_LOOK_TO_WALL": true, - "DIST_NOT_TO_IGNORE_WALL": 15.0, - "DIST_CHECK_WALL": 20.0, - "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25.0, - "MIN_LOOK_AROUD_TIME": 20.0, - "OPTIMIZE_TO_ONLY_BODY": true - }, - "Shoot": { - "RECOIL_TIME_NORMALIZE": 1.0, - "RECOIL_PER_METER": 0.02, - "MAX_RECOIL_PER_METER": 0.1, - "HORIZONT_RECOIL_COEF": 0.1, - "WAIT_NEXT_SINGLE_SHOT": 0.2, - "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, - "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, - "MARKSMAN_DIST_SEK_COEF": 44.0, - "FINGER_HOLD_SINGLE_SHOT": 0.14, - "BASE_AUTOMATIC_TIME": 0.2, - "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, - "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94.0, - "FAR_DIST_ENEMY": 20.0, - "SHOOT_FROM_COVER": 4, - "FAR_DIST_ENEMY_SQR": 400.0, - "MAX_DIST_COEF": 1.35, - "RECOIL_DELTA_PRESS": 0.15, - "RUN_DIST_NO_AMMO": 25.0, - "RUN_DIST_NO_AMMO_SQRT": 625.0, - "CAN_SHOOTS_TIME_TO_AMBUSH": 993, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2.0, - "RELOAD_PECNET_NO_ENEMY": 0.6, - "CHANCE_TO_CHANGE_WEAPON": 100.0, - "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80.0, - "LOW_DIST_TO_CHANGE_WEAPON": 5.0, - "FAR_DIST_TO_CHANGE_WEAPON": 30.0, - "SUPPRESS_BY_SHOOT_TIME": 6.0, - "SUPPRESS_TRIGGERS_DOWN": 3, - "DIST_TO_CHANGE_TO_MAIN": 15.0, - "WAIT_NEXT_STATIONARY_GRENADE": 1.0, - "FINGER_HOLD_STATIONARY_GRENADE": 0.3, - "VALIDATE_MALFUNCTION_CHANCE": 0, - "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, - "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, - "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 - }, - "Move": { - "BASE_ROTATE_SPEED": 270.0, - "REACH_DIST": 0.5, - "REACH_DIST_RUN": 0.8, - "START_SLOW_DIST": 1.5, - "BASESTART_SLOW_DIST": 1.1, - "SLOW_COEF": 7.0, - "DIST_TO_CAN_CHANGE_WAY": 8.0, - "DIST_TO_START_RAYCAST": 15.0, - "BASE_START_SERACH": 35.0, - "UPDATE_TIME_RECAL_WAY": 7.0, - "FAR_DIST": 4.0, - "FAR_DIST_SQR": 16.0, - "DIST_TO_CAN_CHANGE_WAY_SQR": 64.0, - "DIST_TO_START_RAYCAST_SQR": 225.0, - "BASE_SQRT_START_SERACH": 1225.0, - "Y_APPROXIMATION": 0.7, - "DELTA_LAST_SEEN_ENEMY": 20.0, - "REACH_DIST_COVER": 2.0, - "RUN_TO_COVER_MIN": 2.0, - "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100.0, - "RUN_IF_CANT_SHOOT": false, - "RUN_IF_GAOL_FAR_THEN": 10.0, - "SEC_TO_CHANGE_TO_RUN": 3.0, - "ETERNITY_STAMINA": true - }, - "Grenade": { - "DELTA_NEXT_ATTEMPT_FROM_COVER": 5.0, - "DELTA_NEXT_ATTEMPT": 10.0, - "MIN_DIST_NOT_TO_THROW": 8.0, - "NEAR_DELTA_THROW_TIME_SEC": 2.0, - "MIN_THROW_GRENADE_DIST": 12.0, - "MIN_THROW_GRENADE_DIST_SQRT": 144.0, - "MIN_DIST_NOT_TO_THROW_SQR": 64.0, - "RUN_AWAY": 22.0, - "RUN_AWAY_SQR": 484.0, - "ADD_GRENADE_AS_DANGER": 65.0, - "ADD_GRENADE_AS_DANGER_SQR": 4225.0, - "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100.0, - "GrenadePerMeter": 0.1, - "REQUEST_DIST_MUST_THROW_SQRT": 9.0, - "REQUEST_DIST_MUST_THROW": 3.0, - "BEWARE_TYPE": 2, - "SHOOT_TO_SMOKE_CHANCE_100": 50.0, - "CHANCE_RUN_FLASHED_100": 100.0, - "MAX_FLASHED_DIST_TO_SHOOT": 10.0, - "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100.0, - "FLASH_GRENADE_TIME_COEF": 0.25, - "SIZE_SPOTTED_COEF": 2.0, - "BE_ATTENTION_COEF": 4.0, - "TIME_SHOOT_TO_FLASH": 4.0, - "CLOSE_TO_SMOKE_TO_SHOOT": 10.0, - "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100.0, - "CLOSE_TO_SMOKE_TIME_DELTA": 5.0, - "SMOKE_CHECK_DELTA": 1.0, - "DELTA_GRENADE_START_TIME": 0.01, - "AMBUSH_IF_SMOKE_IN_ZONE_100": 40.0, - "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30.0, - "NO_RUN_FROM_AI_GRENADES": true, - "MAX_THROW_POWER": 25.0, - "MIN_THROW_DIST_PERCENT_0_1": 0.7, - "GrenadePrecision": 0.1, - "STOP_WHEN_THROW_GRENADE": true, - "WAIT_TIME_TURN_AWAY": 0.2, - "SMOKE_SUPPRESS_DELTA": 20.0, - "DAMAGE_GRENADE_SUPPRESS_DELTA": 8.0, - "STUN_SUPPRESS_DELTA": 9.0, - "CHEAT_START_GRENADE_PLACE": false, - "CAN_THROW_STRAIGHT_CONTACT": true, - "STRAIGHT_CONTACT_DELTA_SEC": -1.0, - "ANG_TYPE": 1 - }, - "Change": { - "SMOKE_VISION_DIST": 0.6, - "SMOKE_GAIN_SIGHT": 1.6, - "SMOKE_SCATTERING": 1.6, - "SMOKE_PRECICING": 1.6, - "SMOKE_HEARING": 1.0, - "SMOKE_ACCURATY": 1.6, - "SMOKE_LAY_CHANCE": 1.6, - "FLASH_VISION_DIST": 0.05, - "FLASH_GAIN_SIGHT": 1.8, - "FLASH_SCATTERING": 1.6, - "FLASH_PRECICING": 1.6, - "FLASH_HEARING": 1.0, - "FLASH_ACCURATY": 1.6, - "FLASH_LAY_CHANCE": 1.0, - "STUN_HEARING": 0.01 - }, - "Cover": { - "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20.0, - "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50.0, - "SOUND_TO_GET_SPOTTED": 2.0, - "TIME_TO_MOVE_TO_COVER": 15.0, - "MAX_DIST_OF_COVER": 4.0, - "CHANGE_RUN_TO_COVER_SEC": 5.0, - "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, - "MIN_DIST_TO_ENEMY": 9.0, - "DIST_CANT_CHANGE_WAY": 5.0, - "DIST_CHECK_SFETY": 9.0, - "TIME_CHECK_SAFE": 2.0, - "HIDE_TO_COVER_TIME": 1.5, - "MAX_DIST_OF_COVER_SQR": 16.0, - "DIST_CANT_CHANGE_WAY_SQR": 25.0, - "SPOTTED_COVERS_RADIUS": 2.5, - "LOOK_LAST_ENEMY_POS_MOVING": 1.5, - "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3.0, - "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45.0, - "OFFSET_LOOK_ALONG_WALL_ANG": 20, - "SPOTTED_GRENADE_RADIUS": 16.0, - "MAX_SPOTTED_TIME_SEC": 55.0, - "WAIT_INT_COVER_FINDING_ENEMY": 2.0, - "CLOSE_DIST_POINT_SQRT": 4.0, - "DELTA_SEEN_FROM_COVE_LAST_POS": 15.0, - "MOVE_TO_COVER_WHEN_TARGET": false, - "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, - "SPOTTED_GRENADE_TIME": 7.0, - "DEPENDS_Y_DIST_TO_BOT": false, - "RUN_IF_FAR": 15.0, - "RUN_IF_FAR_SQRT": 225.0, - "STAY_IF_FAR": 25.0, - "STAY_IF_FAR_SQRT": 625.0, - "CHECK_COVER_ENEMY_LOOK": false, - "SHOOT_NEAR_TO_LEAVE": 2, - "SHOOT_NEAR_SEC_PERIOD": 0.5, - "HITS_TO_LEAVE_COVER": 1, - "HITS_TO_LEAVE_COVER_UNKNOWN": 1, - "DOG_FIGHT_AFTER_LEAVE": 4.0, - "NOT_LOOK_AT_WALL_IS_DANGER": true, - "MIN_DEFENCE_LEVEL": 22.0, - "REWORK_NOT_TO_SHOOT": true, - "DELETE_POINTS_BEHIND_ENEMIES": true, - "GOOD_DIST_TO_POINT_COEF": 1.8, - "ENEMY_DIST_TO_GO_OUT": 1.0, - "CHECK_CLOSEST_FRIEND": false, - "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15.0 - }, - "Patrol": { - "LOOK_TIME_BASE": 12.0, - "RESERVE_TIME_STAY": 72.0, - "FRIEND_SEARCH_SEC": 12.0, - "TALK_DELAY": 31.1, - "MIN_TALK_DELAY": 35.0, - "TALK_DELAY_BIG": 45.1, - "CHANGE_WAY_TIME": 3325.1, - "MIN_DIST_TO_CLOSE_TALK": 5.0, - "VISION_DIST_COEF_PEACE": 1.0, - "MIN_DIST_TO_CLOSE_TALK_SQR": 25.0, - "CHANCE_TO_CUT_WAY_0_100": 75.0, - "CUT_WAY_MIN_0_1": 0.4, - "CUT_WAY_MAX_0_1": 0.65, - "CHANCE_TO_CHANGE_WAY_0_100": 30.0, - "CHANCE_TO_SHOOT_DEADBODY": 52, - "SUSPETION_PLACE_LIFETIME": 7.0, - "RESERVE_OUT_TIME": 60.0, - "CLOSE_TO_SELECT_RESERV_WAY": 25.0, - "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5.0, - "CAN_CHOOSE_RESERV": true, - "TRY_CHOOSE_RESERV_WAY_ON_START": true - }, - "Hearing": { - "BOT_CLOSE_PANIC_DIST": 1.0, - "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, - "DISPERSION_COEF": 10.0, - "CLOSE_DIST": 26.0, - "FAR_DIST": 56.0, - "SOUND_DIR_DEEFREE": 30.0, - "DIST_PLACE_TO_FIND_POINT": 70.0, - "DEAD_BODY_SOUND_RAD": 30.0, - "LOOK_ONLY_DANGER": false, - "RESET_TIMER_DIST": 17.0, - "HEAR_DELAY_WHEN_PEACE": 0.0, - "HEAR_DELAY_WHEN_HAVE_SMT": 0.0, - "LOOK_ONLY_DANGER_DELTA": 9.0 - }, - "Mind": { - "MIN_SHOOTS_TIME": 2, - "MAX_SHOOTS_TIME": 4, - "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15.0, - "DAMAGE_REDUCTION_TIME_SEC": 20.0, - "MIN_DAMAGE_SCARE": 20.0, - "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35.0, - "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52.0, - "TIME_TO_FIND_ENEMY": 22.0, - "MAX_AGGRO_BOT_DIST": 100.0, - "HIT_POINT_DETECTION": 4.0, - "DANGER_POINT_CHOOSE_COEF": 1.0, - "SIMPLE_POINT_CHOOSE_COEF": 0.4, - "LASTSEEN_POINT_CHOOSE_COEF": 0.2, - "COVER_DIST_COEF": 1.5, - "DIST_TO_FOUND_SQRT": 400.0, - "MAX_AGGRO_BOT_DIST_SQR": 10000.0, - "DIST_TO_STOP_RUN_ENEMY": 15.0, - "ENEMY_LOOK_AT_ME_ANG": 15.0, - "MIN_START_AGGRESION_COEF": 1.0, - "MAX_START_AGGRESION_COEF": 3.0, - "BULLET_FEEL_DIST": 360.0, - "BULLET_FEEL_CLOSE_SDIST": 1.0, - "ATTACK_IMMEDIATLY_CHANCE_0_100": 40.0, - "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, - "FRIEND_DEAD_AGR_LOW": -0.2, - "FRIEND_AGR_KILL": 0.2, - "LAST_ENEMY_LOOK_TO": 40.0, - "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, - "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, - "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, - "CAN_USE_MEDS": true, - "SUSPETION_POINT_CHANCE_ADD100": 0.0, - "AMBUSH_WHEN_UNDER_FIRE": true, - "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60.0, - "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, - "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, - "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2.0, - "PROTECT_TIME_REAL": true, - "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25.0, - "CAN_PANIC_IS_PROTECT": false, - "NO_RUN_AWAY_FOR_SAFE": true, - "PART_PERCENT_TO_HEAL": 0.65, - "PROTECT_DELTA_HEAL_SEC": 10.0, - "CAN_STAND_BY": false, - "CAN_THROW_REQUESTS": true, - "GROUP_ANY_PHRASE_DELAY": 20.0, - "GROUP_EXACTLY_PHRASE_DELAY": 20.0, - "DIST_TO_ENEMY_YO_CAN_HEAL": 30.0, - "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80.0, - "DOG_FIGHT_OUT": 6.0, - "DOG_FIGHT_IN": 3.0, - "SHOOT_INSTEAD_DOG_FIGHT": 9.0, - "PISTOL_SHOTGUN_AMBUSH_DIST": 30.0, - "STANDART_AMBUSH_DIST": 100.0, - "AI_POWER_COEF": 120.0, - "COVER_SECONDS_AFTER_LOSE_VISION": 10.0, - "COVER_SELF_ALWAYS_IF_DAMAGED": false, - "SEC_TO_MORE_DIST_TO_RUN": 10.0, - "HEAL_DELAY_SEC": 5.0, - "HIT_DELAY_WHEN_HAVE_SMT": -1.0, - "HIT_DELAY_WHEN_PEACE": -1.0, - "TALK_WITH_QUERY": true, - "DANGER_EXPIRE_TIME_MIN": 0.4, - "DANGER_EXPIRE_TIME_MAX": 1.2, - "PANIC_RUN_WEIGHT": 1.0, - "PANIC_SIT_WEIGHT": 80.0, - "PANIC_LAY_WEIGHT": 20.0, - "PANIC_NONE_WEIGHT": 40.0, - "CAN_TAKE_ITEMS": false, - "PANIC_SIT_WEIGHT_PEACE": 60.0 - }, - "Boss": { - "BOSS_DIST_TO_WARNING": 34.0, - "BOSS_DIST_TO_WARNING_SQRT": 1156.0, - "BOSS_DIST_TO_WARNING_OUT": 43.0, - "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849.0, - "BOSS_DIST_TO_SHOOT": 16.0, - "BOSS_DIST_TO_SHOOT_SQRT": 256.0, - "CHANCE_TO_SEND_GRENADE_100": 100.0, - "MAX_DIST_COVER_BOSS": 25.0, - "MAX_DIST_COVER_BOSS_SQRT": 625.0, - "MAX_DIST_DECIDER_TO_SEND": 35.0, - "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225.0, - "TIME_AFTER_LOSE": 15.0, - "TIME_AFTER_LOSE_DELTA": 60.0, - "PERSONS_SEND": 2, - "DELTA_SEARCH_TIME": 18.0, - "COVER_TO_SEND": true, - "WAIT_NO_ATTACK_SAVAGE": 10.0, - "CHANCE_USE_RESERVE_PATROL_100": 30.0, - "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5.0, - "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65.0, - "KILLA_START_SEARCH_SEC": 40.0, - "KILLA_CONTUTION_TIME": 5.0, - "KILLA_CLOSE_ATTACK_DIST": 8.0, - "KILLA_MIDDLE_ATTACK_DIST": 32.0, - "KILLA_LARGE_ATTACK_DIST": 61.0, - "KILLA_SEARCH_METERS": 30.0, - "KILLA_DEF_DIST_SQRT": 225.0, - "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25.0, - "KILLA_DIST_TO_GO_TO_SUPPRESS": 6.0, - "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2.0, - "KILLA_CLOSEATTACK_TIMES": 3, - "KILLA_CLOSEATTACK_DELAY": 10.0, - "KILLA_HOLD_DELAY": 5.0, - "KILLA_BULLET_TO_RELOAD": 15, - "SHALL_WARN": true, - "KOJANIY_DIST_WHEN_READY": 40.0, - "KOJANIY_DIST_TO_BE_ENEMY": 200.0, - "KOJANIY_MIN_DIST_TO_LOOT": 20.0, - "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400.0, - "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17.0, - "KOJANIY_MANY_ENEMIES_COEF": 1.5, - "KILLA_ENEMIES_TO_ATTACK": 3, - "KILLA_ONE_IS_CLOSE": 20.0, - "KILLA_TRIGGER_DOWN_DELAY": 0.1, - "KILLA_WAIT_IN_COVER_COEF": 0.1, - "KOJANIY_COVER_POWER": 500.0, - "KOJANIY_FIGHT_CENTER_POS_ME": false, - "KOJANIY_DIST_CORE_SPOS_RECALC": 25.0, - "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625.0, - "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", - "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, - "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, - "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, - "GLUHAR_ASSAULT_ATTACK_DIST": 30, - "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, - "GLUHAR_TIME_TO_ASSAULT": 10, - "DIST_TO_PROTECT_BOSS": 15 - }, - "Core": { - "VisibleAngle": 160.0, - "VisibleDistance": 142.0, - "GainSightCoef": 0.1, - "ScatteringPerMeter": 0.045, - "ScatteringClosePerMeter": 0.12, - "DamageCoeff": 1.0, - "HearingSense": 3.9, - "CanRun": true, - "CanGrenade": true, - "AimingType": "normal", - "PistolFireDistancePref": 35.0, - "ShotgunFireDistancePref": 50.0, - "RifleFireDistancePref": 100.0, - "AccuratySpeed": 0.2, - "WaitInCoverBetweenShotsSec": 0.3 - }, - "Scattering": { - "MinScatter": 0.03, - "WorkingScatter": 0.15, - "MaxScatter": 0.4, - "SpeedUp": 0.3, - "SpeedUpAim": 1.4, - "SpeedDown": -0.3, - "ToSlowBotSpeed": 1.5, - "ToLowBotSpeed": 2.4, - "ToUpBotSpeed": 3.6, - "MovingSlowCoef": 1.5, - "ToLowBotAngularSpeed": 80.0, - "ToStopBotAngularSpeed": 40.0, - "FromShot": 0.001, - "TracerCoef": 1.3, - "HandDamageScatteringMinMax": 0.7, - "HandDamageAccuracySpeed": 1.3, - "BloodFall": 1.45, - "Caution": 0.3, - "ToCaution": 0.6, - "RecoilControlCoefShootDone": 0.0003, - "RecoilControlCoefShootDoneAuto": 0.00015, - "AMPLITUDE_FACTOR": 0.25, - "AMPLITUDE_SPEED": 0.1, - "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15.0, - "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225.0, - "DIST_NOT_TO_SHOOT": 0.3, - "PoseChnageCoef": 0.1, - "LayFactor": 0.1, - "RecoilYCoef": 0.0005, - "RecoilYCoefSppedDown": -0.52, - "RecoilYMax": 1.0 - } - }, - "normal": { - "Lay": { - "CHECK_SHOOT_WHEN_LAYING": false, - "DELTA_LAY_CHECK": 2.0, - "DELTA_GETUP": 2.7, - "DELTA_AFTER_GETUP": 10.0, - "CLEAR_POINTS_OF_SCARE_SEC": 20.0, - "MAX_LAY_TIME": 35.0, - "DELTA_WANT_LAY_CHECL_SEC": 5.0, - "ATTACK_LAY_CHANCE": 25.0, - "DIST_TO_COVER_TO_LAY": 3.5, - "DIST_TO_COVER_TO_LAY_SQRT": 12.25, - "DIST_GRASS_TERRAIN_SQRT": 0.160000011, - "DIST_ENEMY_NULL_DANGER_LAY": 15.0, - "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225.0, - "DIST_ENEMY_GETUP_LAY": 10.0, - "DIST_ENEMY_GETUP_LAY_SQRT": 100.0, - "DIST_ENEMY_CAN_LAY": 15.0, - "DIST_ENEMY_CAN_LAY_SQRT": 225.0, - "LAY_AIM": 0.6, - "MIN_CAN_LAY_DIST_SQRT": 121.0, - "MIN_CAN_LAY_DIST": 11.0, - "MAX_CAN_LAY_DIST_SQRT": 40000.0, - "MAX_CAN_LAY_DIST": 200.0, - "LAY_CHANCE_DANGER": 40.0, - "DAMAGE_TIME_TO_GETUP": 3 - }, - "Aiming": { - "MAX_AIM_PRECICING": 2.0, - "BETTER_PRECICING_COEF": 0.9, - "RECALC_DIST": 0.7, - "RECALC_SQR_DIST": 0.48999998, - "COEF_FROM_COVER": 0.45, - "PANIC_COEF": 1.2, - "PANIC_ACCURATY_COEF": 1.2, - "HARD_AIM": 0.75, - "PANIC_TIME": 2.0, - "RECALC_MUST_TIME": 3, - "DAMAGE_PANIC_TIME": 15.0, - "DANGER_UP_POINT": 1.3, - "MAX_AIMING_UPGRADE_BY_TIME": 0.25, - "DAMAGE_TO_DISCARD_AIM_0_100": 86.0, - "MIN_TIME_DISCARD_AIM_SEC": 0.3, - "MAX_TIME_DISCARD_AIM_SEC": 0.6, - "XZ_COEF": 0.10, - "SHOOT_TO_CHANGE_PRIORITY": 5525, - "BOTTOM_COEF": 0.1, - "FIRST_CONTACT_ADD_SEC": 0.1, - "FIRST_CONTACT_ADD_CHANCE_100": 80.0, - "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, - "BASE_HIT_AFFECTION_MIN_ANG": 4.0, - "BASE_HIT_AFFECTION_MAX_ANG": 10.0, - "BASE_SHIEF": 0.05, - "SCATTERING_HAVE_DAMAGE_COEF": 2.0, - "SCATTERING_DIST_MODIF": 0.67, - "SCATTERING_DIST_MODIF_CLOSE": 0.6, - "AIMING_TYPE": 5, - "DIST_TO_SHOOT_TO_CENTER": 3.0, - "DIST_TO_SHOOT_NO_OFFSET": 3.0, - "SHPERE_FRIENDY_FIRE_SIZE": -0.1, - "COEF_IF_MOVE": 1.0, - "TIME_COEF_IF_MOVE": 1.1, - "BOT_MOVE_IF_DELTA": 3.01, - "NEXT_SHOT_MISS_CHANCE_100": 100.0, - "NEXT_SHOT_MISS_Y_OFFSET": 1.0, - "ANYTIME_LIGHT_WHEN_AIM_100": -1.0, - "ANY_PART_SHOOT_TIME": 15.0, - "WEAPON_ROOT_OFFSET": 0.35, - "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1.0, - "MAX_AIM_TIME": 1.5, - "OFFSET_RECAL_ANYWAY_TIME": 1.0, - "BASE_SHIEF_STATIONARY_GRENADE": 1.1, - "XZ_COEF_STATIONARY_GRENADE": 0.2, - "Y_TOP_OFFSET_COEF": 0.001, - "Y_BOTTOM_OFFSET_COEF": 0.015 - }, - "Look": { - "OLD_TIME_POINT": 11.0, - "WAIT_NEW_SENSOR": 2.1, - "WAIT_NEW__LOOK_SENSOR": 7.8, - "LOOK_AROUND_DELTA": 1.1, - "MAX_VISION_GRASS_METERS": 0.8, - "MAX_VISION_GRASS_METERS_FLARE": 8.0, - "MAX_VISION_GRASS_METERS_OPT": 0.9090909, - "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, - "LightOnVisionDistance": 45.0, - "FAR_DISTANCE": 160.0, - "FarDeltaTimeSec": 3.0, - "MIDDLE_DIST": 90.0, - "MiddleDeltaTimeSec": 1.0, - "CloseDeltaTimeSec": 0.1, - "POSIBLE_VISION_SPACE": 1.2, - "GOAL_TO_FULL_DISSAPEAR": 1.1, - "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, - "BODY_DELTA_TIME_SEARCH_SEC": 1.7, - "COME_TO_BODY_DIST": 1.2, - "MARKSMAN_VISIBLE_DIST_COEF": 1.15, - "VISIBLE_DISNACE_WITH_LIGHT": 100.0, - "ENEMY_LIGHT_ADD": 48.0, - "ENEMY_LIGHT_START_DIST": 90.0, - "CAN_LOOK_TO_WALL": true, - "DIST_NOT_TO_IGNORE_WALL": 15.0, - "DIST_CHECK_WALL": 20.0, - "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25.0, - "MIN_LOOK_AROUD_TIME": 20.0, - "OPTIMIZE_TO_ONLY_BODY": true - }, - "Shoot": { - "RECOIL_TIME_NORMALIZE": 1.0, - "RECOIL_PER_METER": 0.02, - "MAX_RECOIL_PER_METER": 0.1, - "HORIZONT_RECOIL_COEF": 0.1, - "WAIT_NEXT_SINGLE_SHOT": 0.2, - "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, - "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, - "MARKSMAN_DIST_SEK_COEF": 44.0, - "FINGER_HOLD_SINGLE_SHOT": 0.14, - "BASE_AUTOMATIC_TIME": 0.2, - "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, - "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94.0, - "FAR_DIST_ENEMY": 20.0, - "SHOOT_FROM_COVER": 4, - "FAR_DIST_ENEMY_SQR": 400.0, - "MAX_DIST_COEF": 1.35, - "RECOIL_DELTA_PRESS": 0.15, - "RUN_DIST_NO_AMMO": 25.0, - "RUN_DIST_NO_AMMO_SQRT": 625.0, - "CAN_SHOOTS_TIME_TO_AMBUSH": 993, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2.0, - "RELOAD_PECNET_NO_ENEMY": 0.6, - "CHANCE_TO_CHANGE_WEAPON": 100.0, - "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80.0, - "LOW_DIST_TO_CHANGE_WEAPON": 5.0, - "FAR_DIST_TO_CHANGE_WEAPON": 30.0, - "SUPPRESS_BY_SHOOT_TIME": 6.0, - "SUPPRESS_TRIGGERS_DOWN": 3, - "DIST_TO_CHANGE_TO_MAIN": 15.0, - "WAIT_NEXT_STATIONARY_GRENADE": 1.0, - "FINGER_HOLD_STATIONARY_GRENADE": 0.3, - "VALIDATE_MALFUNCTION_CHANCE": 0, - "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, - "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, - "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 - }, - "Move": { - "BASE_ROTATE_SPEED": 270.0, - "REACH_DIST": 0.5, - "REACH_DIST_RUN": 0.8, - "START_SLOW_DIST": 1.5, - "BASESTART_SLOW_DIST": 1.1, - "SLOW_COEF": 7.0, - "DIST_TO_CAN_CHANGE_WAY": 8.0, - "DIST_TO_START_RAYCAST": 15.0, - "BASE_START_SERACH": 35.0, - "UPDATE_TIME_RECAL_WAY": 7.0, - "FAR_DIST": 4.0, - "FAR_DIST_SQR": 16.0, - "DIST_TO_CAN_CHANGE_WAY_SQR": 64.0, - "DIST_TO_START_RAYCAST_SQR": 225.0, - "BASE_SQRT_START_SERACH": 1225.0, - "Y_APPROXIMATION": 0.7, - "DELTA_LAST_SEEN_ENEMY": 20.0, - "REACH_DIST_COVER": 2.0, - "RUN_TO_COVER_MIN": 2.0, - "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100.0, - "RUN_IF_CANT_SHOOT": false, - "RUN_IF_GAOL_FAR_THEN": 10.0, - "SEC_TO_CHANGE_TO_RUN": 3.0, - "ETERNITY_STAMINA": true - }, - "Grenade": { - "DELTA_NEXT_ATTEMPT_FROM_COVER": 5.0, - "DELTA_NEXT_ATTEMPT": 10.0, - "MIN_DIST_NOT_TO_THROW": 8.0, - "NEAR_DELTA_THROW_TIME_SEC": 2.0, - "MIN_THROW_GRENADE_DIST": 12.0, - "MIN_THROW_GRENADE_DIST_SQRT": 144.0, - "MIN_DIST_NOT_TO_THROW_SQR": 64.0, - "RUN_AWAY": 22.0, - "RUN_AWAY_SQR": 484.0, - "ADD_GRENADE_AS_DANGER": 65.0, - "ADD_GRENADE_AS_DANGER_SQR": 4225.0, - "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100.0, - "GrenadePerMeter": 0.1, - "REQUEST_DIST_MUST_THROW_SQRT": 9.0, - "REQUEST_DIST_MUST_THROW": 3.0, - "BEWARE_TYPE": 2, - "SHOOT_TO_SMOKE_CHANCE_100": 50.0, - "CHANCE_RUN_FLASHED_100": 100.0, - "MAX_FLASHED_DIST_TO_SHOOT": 10.0, - "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100.0, - "FLASH_GRENADE_TIME_COEF": 0.25, - "SIZE_SPOTTED_COEF": 2.0, - "BE_ATTENTION_COEF": 4.0, - "TIME_SHOOT_TO_FLASH": 4.0, - "CLOSE_TO_SMOKE_TO_SHOOT": 10.0, - "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100.0, - "CLOSE_TO_SMOKE_TIME_DELTA": 5.0, - "SMOKE_CHECK_DELTA": 1.0, - "DELTA_GRENADE_START_TIME": 0.01, - "AMBUSH_IF_SMOKE_IN_ZONE_100": 40.0, - "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30.0, - "NO_RUN_FROM_AI_GRENADES": true, - "MAX_THROW_POWER": 25.0, - "MIN_THROW_DIST_PERCENT_0_1": 0.7, - "GrenadePrecision": 0.1, - "STOP_WHEN_THROW_GRENADE": true, - "WAIT_TIME_TURN_AWAY": 0.2, - "SMOKE_SUPPRESS_DELTA": 20.0, - "DAMAGE_GRENADE_SUPPRESS_DELTA": 8.0, - "STUN_SUPPRESS_DELTA": 9.0, - "CHEAT_START_GRENADE_PLACE": false, - "CAN_THROW_STRAIGHT_CONTACT": true, - "STRAIGHT_CONTACT_DELTA_SEC": -1.0, - "ANG_TYPE": 1 - }, - "Change": { - "SMOKE_VISION_DIST": 0.6, - "SMOKE_GAIN_SIGHT": 1.6, - "SMOKE_SCATTERING": 1.6, - "SMOKE_PRECICING": 1.6, - "SMOKE_HEARING": 1.0, - "SMOKE_ACCURATY": 1.6, - "SMOKE_LAY_CHANCE": 1.6, - "FLASH_VISION_DIST": 0.05, - "FLASH_GAIN_SIGHT": 1.8, - "FLASH_SCATTERING": 1.6, - "FLASH_PRECICING": 1.6, - "FLASH_HEARING": 1.0, - "FLASH_ACCURATY": 1.6, - "FLASH_LAY_CHANCE": 1.0, - "STUN_HEARING": 0.01 - }, - "Cover": { - "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20.0, - "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50.0, - "SOUND_TO_GET_SPOTTED": 2.0, - "TIME_TO_MOVE_TO_COVER": 15.0, - "MAX_DIST_OF_COVER": 4.0, - "CHANGE_RUN_TO_COVER_SEC": 5.0, - "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, - "MIN_DIST_TO_ENEMY": 9.0, - "DIST_CANT_CHANGE_WAY": 5.0, - "DIST_CHECK_SFETY": 9.0, - "TIME_CHECK_SAFE": 2.0, - "HIDE_TO_COVER_TIME": 1.5, - "MAX_DIST_OF_COVER_SQR": 16.0, - "DIST_CANT_CHANGE_WAY_SQR": 25.0, - "SPOTTED_COVERS_RADIUS": 2.5, - "LOOK_LAST_ENEMY_POS_MOVING": 1.5, - "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3.0, - "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45.0, - "OFFSET_LOOK_ALONG_WALL_ANG": 20, - "SPOTTED_GRENADE_RADIUS": 16.0, - "MAX_SPOTTED_TIME_SEC": 55.0, - "WAIT_INT_COVER_FINDING_ENEMY": 2.0, - "CLOSE_DIST_POINT_SQRT": 4.0, - "DELTA_SEEN_FROM_COVE_LAST_POS": 15.0, - "MOVE_TO_COVER_WHEN_TARGET": false, - "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, - "SPOTTED_GRENADE_TIME": 7.0, - "DEPENDS_Y_DIST_TO_BOT": false, - "RUN_IF_FAR": 15.0, - "RUN_IF_FAR_SQRT": 225.0, - "STAY_IF_FAR": 25.0, - "STAY_IF_FAR_SQRT": 625.0, - "CHECK_COVER_ENEMY_LOOK": false, - "SHOOT_NEAR_TO_LEAVE": 2, - "SHOOT_NEAR_SEC_PERIOD": 0.5, - "HITS_TO_LEAVE_COVER": 1, - "HITS_TO_LEAVE_COVER_UNKNOWN": 1, - "DOG_FIGHT_AFTER_LEAVE": 4.0, - "NOT_LOOK_AT_WALL_IS_DANGER": true, - "MIN_DEFENCE_LEVEL": 22.0, - "REWORK_NOT_TO_SHOOT": true, - "DELETE_POINTS_BEHIND_ENEMIES": true, - "GOOD_DIST_TO_POINT_COEF": 1.8, - "ENEMY_DIST_TO_GO_OUT": 1.0, - "CHECK_CLOSEST_FRIEND": false, - "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15.0 - }, - "Patrol": { - "LOOK_TIME_BASE": 12.0, - "RESERVE_TIME_STAY": 72.0, - "FRIEND_SEARCH_SEC": 12.0, - "TALK_DELAY": 31.1, - "MIN_TALK_DELAY": 35.0, - "TALK_DELAY_BIG": 45.1, - "CHANGE_WAY_TIME": 3325.1, - "MIN_DIST_TO_CLOSE_TALK": 5.0, - "VISION_DIST_COEF_PEACE": 1.0, - "MIN_DIST_TO_CLOSE_TALK_SQR": 25.0, - "CHANCE_TO_CUT_WAY_0_100": 75.0, - "CUT_WAY_MIN_0_1": 0.4, - "CUT_WAY_MAX_0_1": 0.65, - "CHANCE_TO_CHANGE_WAY_0_100": 30.0, - "CHANCE_TO_SHOOT_DEADBODY": 52, - "SUSPETION_PLACE_LIFETIME": 7.0, - "RESERVE_OUT_TIME": 60.0, - "CLOSE_TO_SELECT_RESERV_WAY": 25.0, - "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5.0, - "CAN_CHOOSE_RESERV": true, - "TRY_CHOOSE_RESERV_WAY_ON_START": true - }, - "Hearing": { - "BOT_CLOSE_PANIC_DIST": 1.0, - "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, - "DISPERSION_COEF": 10.0, - "CLOSE_DIST": 26.0, - "FAR_DIST": 56.0, - "SOUND_DIR_DEEFREE": 30.0, - "DIST_PLACE_TO_FIND_POINT": 70.0, - "DEAD_BODY_SOUND_RAD": 30.0, - "LOOK_ONLY_DANGER": false, - "RESET_TIMER_DIST": 17.0, - "HEAR_DELAY_WHEN_PEACE": 0.0, - "HEAR_DELAY_WHEN_HAVE_SMT": 0.0, - "LOOK_ONLY_DANGER_DELTA": 9.0 - }, - "Mind": { - "MIN_SHOOTS_TIME": 2, - "MAX_SHOOTS_TIME": 4, - "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15.0, - "DAMAGE_REDUCTION_TIME_SEC": 20.0, - "MIN_DAMAGE_SCARE": 20.0, - "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35.0, - "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52.0, - "TIME_TO_FIND_ENEMY": 22.0, - "MAX_AGGRO_BOT_DIST": 100.0, - "HIT_POINT_DETECTION": 4.0, - "DANGER_POINT_CHOOSE_COEF": 1.0, - "SIMPLE_POINT_CHOOSE_COEF": 0.4, - "LASTSEEN_POINT_CHOOSE_COEF": 0.2, - "COVER_DIST_COEF": 1.5, - "DIST_TO_FOUND_SQRT": 400.0, - "MAX_AGGRO_BOT_DIST_SQR": 10000.0, - "DIST_TO_STOP_RUN_ENEMY": 15.0, - "ENEMY_LOOK_AT_ME_ANG": 15.0, - "MIN_START_AGGRESION_COEF": 1.0, - "MAX_START_AGGRESION_COEF": 3.0, - "BULLET_FEEL_DIST": 360.0, - "BULLET_FEEL_CLOSE_SDIST": 1.0, - "ATTACK_IMMEDIATLY_CHANCE_0_100": 40.0, - "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, - "FRIEND_DEAD_AGR_LOW": -0.2, - "FRIEND_AGR_KILL": 0.2, - "LAST_ENEMY_LOOK_TO": 40.0, - "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, - "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, - "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, - "CAN_USE_MEDS": true, - "SUSPETION_POINT_CHANCE_ADD100": 0.0, - "AMBUSH_WHEN_UNDER_FIRE": true, - "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60.0, - "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, - "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, - "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2.0, - "PROTECT_TIME_REAL": true, - "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25.0, - "CAN_PANIC_IS_PROTECT": false, - "NO_RUN_AWAY_FOR_SAFE": true, - "PART_PERCENT_TO_HEAL": 0.65, - "PROTECT_DELTA_HEAL_SEC": 10.0, - "CAN_STAND_BY": false, - "CAN_THROW_REQUESTS": true, - "GROUP_ANY_PHRASE_DELAY": 20.0, - "GROUP_EXACTLY_PHRASE_DELAY": 20.0, - "DIST_TO_ENEMY_YO_CAN_HEAL": 30.0, - "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80.0, - "DOG_FIGHT_OUT": 6.0, - "DOG_FIGHT_IN": 3.0, - "SHOOT_INSTEAD_DOG_FIGHT": 9.0, - "PISTOL_SHOTGUN_AMBUSH_DIST": 30.0, - "STANDART_AMBUSH_DIST": 100.0, - "AI_POWER_COEF": 120.0, - "COVER_SECONDS_AFTER_LOSE_VISION": 10.0, - "COVER_SELF_ALWAYS_IF_DAMAGED": false, - "SEC_TO_MORE_DIST_TO_RUN": 10.0, - "HEAL_DELAY_SEC": 5.0, - "HIT_DELAY_WHEN_HAVE_SMT": -1.0, - "HIT_DELAY_WHEN_PEACE": -1.0, - "TALK_WITH_QUERY": true, - "DANGER_EXPIRE_TIME_MIN": 0.4, - "DANGER_EXPIRE_TIME_MAX": 1.2, - "PANIC_RUN_WEIGHT": 1.0, - "PANIC_SIT_WEIGHT": 80.0, - "PANIC_LAY_WEIGHT": 20.0, - "PANIC_NONE_WEIGHT": 40.0, - "CAN_TAKE_ITEMS": false, - "PANIC_SIT_WEIGHT_PEACE": 60.0 - }, - "Boss": { - "BOSS_DIST_TO_WARNING": 34.0, - "BOSS_DIST_TO_WARNING_SQRT": 1156.0, - "BOSS_DIST_TO_WARNING_OUT": 43.0, - "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849.0, - "BOSS_DIST_TO_SHOOT": 16.0, - "BOSS_DIST_TO_SHOOT_SQRT": 256.0, - "CHANCE_TO_SEND_GRENADE_100": 100.0, - "MAX_DIST_COVER_BOSS": 25.0, - "MAX_DIST_COVER_BOSS_SQRT": 625.0, - "MAX_DIST_DECIDER_TO_SEND": 35.0, - "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225.0, - "TIME_AFTER_LOSE": 15.0, - "TIME_AFTER_LOSE_DELTA": 60.0, - "PERSONS_SEND": 2, - "DELTA_SEARCH_TIME": 18.0, - "COVER_TO_SEND": true, - "WAIT_NO_ATTACK_SAVAGE": 10.0, - "CHANCE_USE_RESERVE_PATROL_100": 30.0, - "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5.0, - "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65.0, - "KILLA_START_SEARCH_SEC": 40.0, - "KILLA_CONTUTION_TIME": 5.0, - "KILLA_CLOSE_ATTACK_DIST": 8.0, - "KILLA_MIDDLE_ATTACK_DIST": 32.0, - "KILLA_LARGE_ATTACK_DIST": 61.0, - "KILLA_SEARCH_METERS": 30.0, - "KILLA_DEF_DIST_SQRT": 225.0, - "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25.0, - "KILLA_DIST_TO_GO_TO_SUPPRESS": 6.0, - "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2.0, - "KILLA_CLOSEATTACK_TIMES": 3, - "KILLA_CLOSEATTACK_DELAY": 10.0, - "KILLA_HOLD_DELAY": 5.0, - "KILLA_BULLET_TO_RELOAD": 15, - "SHALL_WARN": true, - "KOJANIY_DIST_WHEN_READY": 40.0, - "KOJANIY_DIST_TO_BE_ENEMY": 200.0, - "KOJANIY_MIN_DIST_TO_LOOT": 20.0, - "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400.0, - "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17.0, - "KOJANIY_MANY_ENEMIES_COEF": 1.5, - "KILLA_ENEMIES_TO_ATTACK": 3, - "KILLA_ONE_IS_CLOSE": 20.0, - "KILLA_TRIGGER_DOWN_DELAY": 0.1, - "KILLA_WAIT_IN_COVER_COEF": 0.1, - "KOJANIY_COVER_POWER": 500.0, - "KOJANIY_FIGHT_CENTER_POS_ME": false, - "KOJANIY_DIST_CORE_SPOS_RECALC": 25.0, - "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625.0, - "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", - "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, - "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, - "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, - "GLUHAR_ASSAULT_ATTACK_DIST": 30, - "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, - "GLUHAR_TIME_TO_ASSAULT": 10, - "DIST_TO_PROTECT_BOSS": 15 - }, - "Core": { - "VisibleAngle": 160.0, - "VisibleDistance": 142.0, - "GainSightCoef": 0.1, - "ScatteringPerMeter": 0.045, - "ScatteringClosePerMeter": 0.12, - "DamageCoeff": 1.0, - "HearingSense": 3.9, - "CanRun": true, - "CanGrenade": true, - "AimingType": "normal", - "PistolFireDistancePref": 35.0, - "ShotgunFireDistancePref": 50.0, - "RifleFireDistancePref": 100.0, - "AccuratySpeed": 0.2, - "WaitInCoverBetweenShotsSec": 0.3 - }, - "Scattering": { - "MinScatter": 0.03, - "WorkingScatter": 0.15, - "MaxScatter": 0.4, - "SpeedUp": 0.3, - "SpeedUpAim": 1.4, - "SpeedDown": -0.3, - "ToSlowBotSpeed": 1.5, - "ToLowBotSpeed": 2.4, - "ToUpBotSpeed": 3.6, - "MovingSlowCoef": 1.5, - "ToLowBotAngularSpeed": 80.0, - "ToStopBotAngularSpeed": 40.0, - "FromShot": 0.001, - "TracerCoef": 1.3, - "HandDamageScatteringMinMax": 0.7, - "HandDamageAccuracySpeed": 1.3, - "BloodFall": 1.45, - "Caution": 0.3, - "ToCaution": 0.6, - "RecoilControlCoefShootDone": 0.0003, - "RecoilControlCoefShootDoneAuto": 0.00015, - "AMPLITUDE_FACTOR": 0.25, - "AMPLITUDE_SPEED": 0.1, - "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15.0, - "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225.0, - "DIST_NOT_TO_SHOOT": 0.3, - "PoseChnageCoef": 0.1, - "LayFactor": 0.1, - "RecoilYCoef": 0.0005, - "RecoilYCoefSppedDown": -0.52, - "RecoilYMax": 1.0 - } - }, - "hard": { - "Lay": { - "CHECK_SHOOT_WHEN_LAYING": false, - "DELTA_LAY_CHECK": 2.0, - "DELTA_GETUP": 2.7, - "DELTA_AFTER_GETUP": 10.0, - "CLEAR_POINTS_OF_SCARE_SEC": 20.0, - "MAX_LAY_TIME": 35.0, - "DELTA_WANT_LAY_CHECL_SEC": 5.0, - "ATTACK_LAY_CHANCE": 25.0, - "DIST_TO_COVER_TO_LAY": 3.5, - "DIST_TO_COVER_TO_LAY_SQRT": 12.25, - "DIST_GRASS_TERRAIN_SQRT": 0.160000011, - "DIST_ENEMY_NULL_DANGER_LAY": 15.0, - "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225.0, - "DIST_ENEMY_GETUP_LAY": 10.0, - "DIST_ENEMY_GETUP_LAY_SQRT": 100.0, - "DIST_ENEMY_CAN_LAY": 15.0, - "DIST_ENEMY_CAN_LAY_SQRT": 225.0, - "LAY_AIM": 0.6, - "MIN_CAN_LAY_DIST_SQRT": 121.0, - "MIN_CAN_LAY_DIST": 11.0, - "MAX_CAN_LAY_DIST_SQRT": 40000.0, - "MAX_CAN_LAY_DIST": 200.0, - "LAY_CHANCE_DANGER": 40.0, - "DAMAGE_TIME_TO_GETUP": 3 - }, - "Aiming": { - "MAX_AIM_PRECICING": 2.0, - "BETTER_PRECICING_COEF": 0.9, - "RECALC_DIST": 0.7, - "RECALC_SQR_DIST": 0.48999998, - "COEF_FROM_COVER": 0.45, - "PANIC_COEF": 1.2, - "PANIC_ACCURATY_COEF": 1.2, - "HARD_AIM": 0.75, - "PANIC_TIME": 2.0, - "RECALC_MUST_TIME": 3, - "DAMAGE_PANIC_TIME": 15.0, - "DANGER_UP_POINT": 1.3, - "MAX_AIMING_UPGRADE_BY_TIME": 0.25, - "DAMAGE_TO_DISCARD_AIM_0_100": 86.0, - "MIN_TIME_DISCARD_AIM_SEC": 0.3, - "MAX_TIME_DISCARD_AIM_SEC": 0.6, - "XZ_COEF": 0.10, - "SHOOT_TO_CHANGE_PRIORITY": 5525, - "BOTTOM_COEF": 0.1, - "FIRST_CONTACT_ADD_SEC": 0.1, - "FIRST_CONTACT_ADD_CHANCE_100": 80.0, - "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, - "BASE_HIT_AFFECTION_MIN_ANG": 4.0, - "BASE_HIT_AFFECTION_MAX_ANG": 10.0, - "BASE_SHIEF": 0.05, - "SCATTERING_HAVE_DAMAGE_COEF": 2.0, - "SCATTERING_DIST_MODIF": 0.67, - "SCATTERING_DIST_MODIF_CLOSE": 0.6, - "AIMING_TYPE": 5, - "DIST_TO_SHOOT_TO_CENTER": 3.0, - "DIST_TO_SHOOT_NO_OFFSET": 3.0, - "SHPERE_FRIENDY_FIRE_SIZE": -0.1, - "COEF_IF_MOVE": 1.0, - "TIME_COEF_IF_MOVE": 1.1, - "BOT_MOVE_IF_DELTA": 3.01, - "NEXT_SHOT_MISS_CHANCE_100": 100.0, - "NEXT_SHOT_MISS_Y_OFFSET": 1.0, - "ANYTIME_LIGHT_WHEN_AIM_100": -1.0, - "ANY_PART_SHOOT_TIME": 15.0, - "WEAPON_ROOT_OFFSET": 0.35, - "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1.0, - "MAX_AIM_TIME": 1.5, - "OFFSET_RECAL_ANYWAY_TIME": 1.0, - "BASE_SHIEF_STATIONARY_GRENADE": 1.1, - "XZ_COEF_STATIONARY_GRENADE": 0.2, - "Y_TOP_OFFSET_COEF": 0.001, - "Y_BOTTOM_OFFSET_COEF": 0.015 - }, - "Look": { - "OLD_TIME_POINT": 11.0, - "WAIT_NEW_SENSOR": 2.1, - "WAIT_NEW__LOOK_SENSOR": 7.8, - "LOOK_AROUND_DELTA": 1.1, - "MAX_VISION_GRASS_METERS": 0.8, - "MAX_VISION_GRASS_METERS_FLARE": 8.0, - "MAX_VISION_GRASS_METERS_OPT": 0.9090909, - "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, - "LightOnVisionDistance": 45.0, - "FAR_DISTANCE": 160.0, - "FarDeltaTimeSec": 3.0, - "MIDDLE_DIST": 90.0, - "MiddleDeltaTimeSec": 1.0, - "CloseDeltaTimeSec": 0.1, - "POSIBLE_VISION_SPACE": 1.2, - "GOAL_TO_FULL_DISSAPEAR": 1.1, - "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, - "BODY_DELTA_TIME_SEARCH_SEC": 1.7, - "COME_TO_BODY_DIST": 1.2, - "MARKSMAN_VISIBLE_DIST_COEF": 1.15, - "VISIBLE_DISNACE_WITH_LIGHT": 100.0, - "ENEMY_LIGHT_ADD": 48.0, - "ENEMY_LIGHT_START_DIST": 90.0, - "CAN_LOOK_TO_WALL": true, - "DIST_NOT_TO_IGNORE_WALL": 15.0, - "DIST_CHECK_WALL": 20.0, - "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25.0, - "MIN_LOOK_AROUD_TIME": 20.0, - "OPTIMIZE_TO_ONLY_BODY": true - }, - "Shoot": { - "RECOIL_TIME_NORMALIZE": 1.0, - "RECOIL_PER_METER": 0.02, - "MAX_RECOIL_PER_METER": 0.1, - "HORIZONT_RECOIL_COEF": 0.1, - "WAIT_NEXT_SINGLE_SHOT": 0.2, - "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, - "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, - "MARKSMAN_DIST_SEK_COEF": 44.0, - "FINGER_HOLD_SINGLE_SHOT": 0.14, - "BASE_AUTOMATIC_TIME": 0.2, - "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, - "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94.0, - "FAR_DIST_ENEMY": 20.0, - "SHOOT_FROM_COVER": 4, - "FAR_DIST_ENEMY_SQR": 400.0, - "MAX_DIST_COEF": 1.35, - "RECOIL_DELTA_PRESS": 0.15, - "RUN_DIST_NO_AMMO": 25.0, - "RUN_DIST_NO_AMMO_SQRT": 625.0, - "CAN_SHOOTS_TIME_TO_AMBUSH": 993, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2.0, - "RELOAD_PECNET_NO_ENEMY": 0.6, - "CHANCE_TO_CHANGE_WEAPON": 100.0, - "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80.0, - "LOW_DIST_TO_CHANGE_WEAPON": 5.0, - "FAR_DIST_TO_CHANGE_WEAPON": 30.0, - "SUPPRESS_BY_SHOOT_TIME": 6.0, - "SUPPRESS_TRIGGERS_DOWN": 3, - "DIST_TO_CHANGE_TO_MAIN": 15.0, - "WAIT_NEXT_STATIONARY_GRENADE": 1.0, - "FINGER_HOLD_STATIONARY_GRENADE": 0.3, - "VALIDATE_MALFUNCTION_CHANCE": 0, - "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, - "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, - "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 - }, - "Move": { - "BASE_ROTATE_SPEED": 270.0, - "REACH_DIST": 0.5, - "REACH_DIST_RUN": 0.8, - "START_SLOW_DIST": 1.5, - "BASESTART_SLOW_DIST": 1.1, - "SLOW_COEF": 7.0, - "DIST_TO_CAN_CHANGE_WAY": 8.0, - "DIST_TO_START_RAYCAST": 15.0, - "BASE_START_SERACH": 35.0, - "UPDATE_TIME_RECAL_WAY": 7.0, - "FAR_DIST": 4.0, - "FAR_DIST_SQR": 16.0, - "DIST_TO_CAN_CHANGE_WAY_SQR": 64.0, - "DIST_TO_START_RAYCAST_SQR": 225.0, - "BASE_SQRT_START_SERACH": 1225.0, - "Y_APPROXIMATION": 0.7, - "DELTA_LAST_SEEN_ENEMY": 20.0, - "REACH_DIST_COVER": 2.0, - "RUN_TO_COVER_MIN": 2.0, - "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100.0, - "RUN_IF_CANT_SHOOT": false, - "RUN_IF_GAOL_FAR_THEN": 10.0, - "SEC_TO_CHANGE_TO_RUN": 3.0, - "ETERNITY_STAMINA": true - }, - "Grenade": { - "DELTA_NEXT_ATTEMPT_FROM_COVER": 5.0, - "DELTA_NEXT_ATTEMPT": 10.0, - "MIN_DIST_NOT_TO_THROW": 8.0, - "NEAR_DELTA_THROW_TIME_SEC": 2.0, - "MIN_THROW_GRENADE_DIST": 12.0, - "MIN_THROW_GRENADE_DIST_SQRT": 144.0, - "MIN_DIST_NOT_TO_THROW_SQR": 64.0, - "RUN_AWAY": 22.0, - "RUN_AWAY_SQR": 484.0, - "ADD_GRENADE_AS_DANGER": 65.0, - "ADD_GRENADE_AS_DANGER_SQR": 4225.0, - "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100.0, - "GrenadePerMeter": 0.1, - "REQUEST_DIST_MUST_THROW_SQRT": 9.0, - "REQUEST_DIST_MUST_THROW": 3.0, - "BEWARE_TYPE": 2, - "SHOOT_TO_SMOKE_CHANCE_100": 50.0, - "CHANCE_RUN_FLASHED_100": 100.0, - "MAX_FLASHED_DIST_TO_SHOOT": 10.0, - "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100.0, - "FLASH_GRENADE_TIME_COEF": 0.25, - "SIZE_SPOTTED_COEF": 2.0, - "BE_ATTENTION_COEF": 4.0, - "TIME_SHOOT_TO_FLASH": 4.0, - "CLOSE_TO_SMOKE_TO_SHOOT": 10.0, - "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100.0, - "CLOSE_TO_SMOKE_TIME_DELTA": 5.0, - "SMOKE_CHECK_DELTA": 1.0, - "DELTA_GRENADE_START_TIME": 0.01, - "AMBUSH_IF_SMOKE_IN_ZONE_100": 40.0, - "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30.0, - "NO_RUN_FROM_AI_GRENADES": true, - "MAX_THROW_POWER": 25.0, - "MIN_THROW_DIST_PERCENT_0_1": 0.7, - "GrenadePrecision": 0.1, - "STOP_WHEN_THROW_GRENADE": true, - "WAIT_TIME_TURN_AWAY": 0.2, - "SMOKE_SUPPRESS_DELTA": 20.0, - "DAMAGE_GRENADE_SUPPRESS_DELTA": 8.0, - "STUN_SUPPRESS_DELTA": 9.0, - "CHEAT_START_GRENADE_PLACE": false, - "CAN_THROW_STRAIGHT_CONTACT": true, - "STRAIGHT_CONTACT_DELTA_SEC": -1.0, - "ANG_TYPE": 1 - }, - "Change": { - "SMOKE_VISION_DIST": 0.6, - "SMOKE_GAIN_SIGHT": 1.6, - "SMOKE_SCATTERING": 1.6, - "SMOKE_PRECICING": 1.6, - "SMOKE_HEARING": 1.0, - "SMOKE_ACCURATY": 1.6, - "SMOKE_LAY_CHANCE": 1.6, - "FLASH_VISION_DIST": 0.05, - "FLASH_GAIN_SIGHT": 1.8, - "FLASH_SCATTERING": 1.6, - "FLASH_PRECICING": 1.6, - "FLASH_HEARING": 1.0, - "FLASH_ACCURATY": 1.6, - "FLASH_LAY_CHANCE": 1.0, - "STUN_HEARING": 0.01 - }, - "Cover": { - "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20.0, - "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50.0, - "SOUND_TO_GET_SPOTTED": 2.0, - "TIME_TO_MOVE_TO_COVER": 15.0, - "MAX_DIST_OF_COVER": 4.0, - "CHANGE_RUN_TO_COVER_SEC": 5.0, - "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, - "MIN_DIST_TO_ENEMY": 9.0, - "DIST_CANT_CHANGE_WAY": 5.0, - "DIST_CHECK_SFETY": 9.0, - "TIME_CHECK_SAFE": 2.0, - "HIDE_TO_COVER_TIME": 1.5, - "MAX_DIST_OF_COVER_SQR": 16.0, - "DIST_CANT_CHANGE_WAY_SQR": 25.0, - "SPOTTED_COVERS_RADIUS": 2.5, - "LOOK_LAST_ENEMY_POS_MOVING": 1.5, - "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3.0, - "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45.0, - "OFFSET_LOOK_ALONG_WALL_ANG": 20, - "SPOTTED_GRENADE_RADIUS": 16.0, - "MAX_SPOTTED_TIME_SEC": 55.0, - "WAIT_INT_COVER_FINDING_ENEMY": 2.0, - "CLOSE_DIST_POINT_SQRT": 4.0, - "DELTA_SEEN_FROM_COVE_LAST_POS": 15.0, - "MOVE_TO_COVER_WHEN_TARGET": false, - "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, - "SPOTTED_GRENADE_TIME": 7.0, - "DEPENDS_Y_DIST_TO_BOT": false, - "RUN_IF_FAR": 15.0, - "RUN_IF_FAR_SQRT": 225.0, - "STAY_IF_FAR": 25.0, - "STAY_IF_FAR_SQRT": 625.0, - "CHECK_COVER_ENEMY_LOOK": false, - "SHOOT_NEAR_TO_LEAVE": 2, - "SHOOT_NEAR_SEC_PERIOD": 0.5, - "HITS_TO_LEAVE_COVER": 1, - "HITS_TO_LEAVE_COVER_UNKNOWN": 1, - "DOG_FIGHT_AFTER_LEAVE": 4.0, - "NOT_LOOK_AT_WALL_IS_DANGER": true, - "MIN_DEFENCE_LEVEL": 22.0, - "REWORK_NOT_TO_SHOOT": true, - "DELETE_POINTS_BEHIND_ENEMIES": true, - "GOOD_DIST_TO_POINT_COEF": 1.8, - "ENEMY_DIST_TO_GO_OUT": 1.0, - "CHECK_CLOSEST_FRIEND": false, - "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15.0 - }, - "Patrol": { - "LOOK_TIME_BASE": 12.0, - "RESERVE_TIME_STAY": 72.0, - "FRIEND_SEARCH_SEC": 12.0, - "TALK_DELAY": 31.1, - "MIN_TALK_DELAY": 35.0, - "TALK_DELAY_BIG": 45.1, - "CHANGE_WAY_TIME": 3325.1, - "MIN_DIST_TO_CLOSE_TALK": 5.0, - "VISION_DIST_COEF_PEACE": 1.0, - "MIN_DIST_TO_CLOSE_TALK_SQR": 25.0, - "CHANCE_TO_CUT_WAY_0_100": 75.0, - "CUT_WAY_MIN_0_1": 0.4, - "CUT_WAY_MAX_0_1": 0.65, - "CHANCE_TO_CHANGE_WAY_0_100": 30.0, - "CHANCE_TO_SHOOT_DEADBODY": 52, - "SUSPETION_PLACE_LIFETIME": 7.0, - "RESERVE_OUT_TIME": 60.0, - "CLOSE_TO_SELECT_RESERV_WAY": 25.0, - "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5.0, - "CAN_CHOOSE_RESERV": true, - "TRY_CHOOSE_RESERV_WAY_ON_START": true - }, - "Hearing": { - "BOT_CLOSE_PANIC_DIST": 1.0, - "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, - "DISPERSION_COEF": 10.0, - "CLOSE_DIST": 26.0, - "FAR_DIST": 56.0, - "SOUND_DIR_DEEFREE": 30.0, - "DIST_PLACE_TO_FIND_POINT": 70.0, - "DEAD_BODY_SOUND_RAD": 30.0, - "LOOK_ONLY_DANGER": false, - "RESET_TIMER_DIST": 17.0, - "HEAR_DELAY_WHEN_PEACE": 0.0, - "HEAR_DELAY_WHEN_HAVE_SMT": 0.0, - "LOOK_ONLY_DANGER_DELTA": 9.0 - }, - "Mind": { - "MIN_SHOOTS_TIME": 2, - "MAX_SHOOTS_TIME": 4, - "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15.0, - "DAMAGE_REDUCTION_TIME_SEC": 20.0, - "MIN_DAMAGE_SCARE": 20.0, - "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35.0, - "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52.0, - "TIME_TO_FIND_ENEMY": 22.0, - "MAX_AGGRO_BOT_DIST": 100.0, - "HIT_POINT_DETECTION": 4.0, - "DANGER_POINT_CHOOSE_COEF": 1.0, - "SIMPLE_POINT_CHOOSE_COEF": 0.4, - "LASTSEEN_POINT_CHOOSE_COEF": 0.2, - "COVER_DIST_COEF": 1.5, - "DIST_TO_FOUND_SQRT": 400.0, - "MAX_AGGRO_BOT_DIST_SQR": 10000.0, - "DIST_TO_STOP_RUN_ENEMY": 15.0, - "ENEMY_LOOK_AT_ME_ANG": 15.0, - "MIN_START_AGGRESION_COEF": 1.0, - "MAX_START_AGGRESION_COEF": 3.0, - "BULLET_FEEL_DIST": 360.0, - "BULLET_FEEL_CLOSE_SDIST": 1.0, - "ATTACK_IMMEDIATLY_CHANCE_0_100": 40.0, - "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, - "FRIEND_DEAD_AGR_LOW": -0.2, - "FRIEND_AGR_KILL": 0.2, - "LAST_ENEMY_LOOK_TO": 40.0, - "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, - "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, - "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, - "CAN_USE_MEDS": true, - "SUSPETION_POINT_CHANCE_ADD100": 0.0, - "AMBUSH_WHEN_UNDER_FIRE": true, - "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60.0, - "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, - "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, - "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2.0, - "PROTECT_TIME_REAL": true, - "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25.0, - "CAN_PANIC_IS_PROTECT": false, - "NO_RUN_AWAY_FOR_SAFE": true, - "PART_PERCENT_TO_HEAL": 0.65, - "PROTECT_DELTA_HEAL_SEC": 10.0, - "CAN_STAND_BY": false, - "CAN_THROW_REQUESTS": true, - "GROUP_ANY_PHRASE_DELAY": 20.0, - "GROUP_EXACTLY_PHRASE_DELAY": 20.0, - "DIST_TO_ENEMY_YO_CAN_HEAL": 30.0, - "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80.0, - "DOG_FIGHT_OUT": 6.0, - "DOG_FIGHT_IN": 3.0, - "SHOOT_INSTEAD_DOG_FIGHT": 9.0, - "PISTOL_SHOTGUN_AMBUSH_DIST": 30.0, - "STANDART_AMBUSH_DIST": 100.0, - "AI_POWER_COEF": 120.0, - "COVER_SECONDS_AFTER_LOSE_VISION": 10.0, - "COVER_SELF_ALWAYS_IF_DAMAGED": false, - "SEC_TO_MORE_DIST_TO_RUN": 10.0, - "HEAL_DELAY_SEC": 5.0, - "HIT_DELAY_WHEN_HAVE_SMT": -1.0, - "HIT_DELAY_WHEN_PEACE": -1.0, - "TALK_WITH_QUERY": true, - "DANGER_EXPIRE_TIME_MIN": 0.4, - "DANGER_EXPIRE_TIME_MAX": 1.2, - "PANIC_RUN_WEIGHT": 1.0, - "PANIC_SIT_WEIGHT": 80.0, - "PANIC_LAY_WEIGHT": 20.0, - "PANIC_NONE_WEIGHT": 40.0, - "CAN_TAKE_ITEMS": false, - "PANIC_SIT_WEIGHT_PEACE": 60.0 - }, - "Boss": { - "BOSS_DIST_TO_WARNING": 34.0, - "BOSS_DIST_TO_WARNING_SQRT": 1156.0, - "BOSS_DIST_TO_WARNING_OUT": 43.0, - "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849.0, - "BOSS_DIST_TO_SHOOT": 16.0, - "BOSS_DIST_TO_SHOOT_SQRT": 256.0, - "CHANCE_TO_SEND_GRENADE_100": 100.0, - "MAX_DIST_COVER_BOSS": 25.0, - "MAX_DIST_COVER_BOSS_SQRT": 625.0, - "MAX_DIST_DECIDER_TO_SEND": 35.0, - "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225.0, - "TIME_AFTER_LOSE": 15.0, - "TIME_AFTER_LOSE_DELTA": 60.0, - "PERSONS_SEND": 2, - "DELTA_SEARCH_TIME": 18.0, - "COVER_TO_SEND": true, - "WAIT_NO_ATTACK_SAVAGE": 10.0, - "CHANCE_USE_RESERVE_PATROL_100": 30.0, - "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5.0, - "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65.0, - "KILLA_START_SEARCH_SEC": 40.0, - "KILLA_CONTUTION_TIME": 5.0, - "KILLA_CLOSE_ATTACK_DIST": 8.0, - "KILLA_MIDDLE_ATTACK_DIST": 32.0, - "KILLA_LARGE_ATTACK_DIST": 61.0, - "KILLA_SEARCH_METERS": 30.0, - "KILLA_DEF_DIST_SQRT": 225.0, - "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25.0, - "KILLA_DIST_TO_GO_TO_SUPPRESS": 6.0, - "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2.0, - "KILLA_CLOSEATTACK_TIMES": 3, - "KILLA_CLOSEATTACK_DELAY": 10.0, - "KILLA_HOLD_DELAY": 5.0, - "KILLA_BULLET_TO_RELOAD": 15, - "SHALL_WARN": true, - "KOJANIY_DIST_WHEN_READY": 40.0, - "KOJANIY_DIST_TO_BE_ENEMY": 200.0, - "KOJANIY_MIN_DIST_TO_LOOT": 20.0, - "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400.0, - "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17.0, - "KOJANIY_MANY_ENEMIES_COEF": 1.5, - "KILLA_ENEMIES_TO_ATTACK": 3, - "KILLA_ONE_IS_CLOSE": 20.0, - "KILLA_TRIGGER_DOWN_DELAY": 0.1, - "KILLA_WAIT_IN_COVER_COEF": 0.1, - "KOJANIY_COVER_POWER": 500.0, - "KOJANIY_FIGHT_CENTER_POS_ME": false, - "KOJANIY_DIST_CORE_SPOS_RECALC": 25.0, - "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625.0, - "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", - "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, - "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, - "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, - "GLUHAR_ASSAULT_ATTACK_DIST": 30, - "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, - "GLUHAR_TIME_TO_ASSAULT": 10, - "DIST_TO_PROTECT_BOSS": 15 - }, - "Core": { - "VisibleAngle": 160.0, - "VisibleDistance": 142.0, - "GainSightCoef": 0.1, - "ScatteringPerMeter": 0.045, - "ScatteringClosePerMeter": 0.12, - "DamageCoeff": 1.0, - "HearingSense": 3.9, - "CanRun": true, - "CanGrenade": true, - "AimingType": "normal", - "PistolFireDistancePref": 35.0, - "ShotgunFireDistancePref": 50.0, - "RifleFireDistancePref": 100.0, - "AccuratySpeed": 0.2, - "WaitInCoverBetweenShotsSec": 0.3 - }, - "Scattering": { - "MinScatter": 0.03, - "WorkingScatter": 0.15, - "MaxScatter": 0.4, - "SpeedUp": 0.3, - "SpeedUpAim": 1.4, - "SpeedDown": -0.3, - "ToSlowBotSpeed": 1.5, - "ToLowBotSpeed": 2.4, - "ToUpBotSpeed": 3.6, - "MovingSlowCoef": 1.5, - "ToLowBotAngularSpeed": 80.0, - "ToStopBotAngularSpeed": 40.0, - "FromShot": 0.001, - "TracerCoef": 1.3, - "HandDamageScatteringMinMax": 0.7, - "HandDamageAccuracySpeed": 1.3, - "BloodFall": 1.45, - "Caution": 0.3, - "ToCaution": 0.6, - "RecoilControlCoefShootDone": 0.0003, - "RecoilControlCoefShootDoneAuto": 0.00015, - "AMPLITUDE_FACTOR": 0.25, - "AMPLITUDE_SPEED": 0.1, - "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15.0, - "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225.0, - "DIST_NOT_TO_SHOOT": 0.3, - "PoseChnageCoef": 0.1, - "LayFactor": 0.1, - "RecoilYCoef": 0.0005, - "RecoilYCoefSppedDown": -0.52, - "RecoilYMax": 1.0 - } - }, - "impossible": { - "Lay": { - "CHECK_SHOOT_WHEN_LAYING": false, - "DELTA_LAY_CHECK": 2.0, - "DELTA_GETUP": 2.7, - "DELTA_AFTER_GETUP": 10.0, - "CLEAR_POINTS_OF_SCARE_SEC": 20.0, - "MAX_LAY_TIME": 35.0, - "DELTA_WANT_LAY_CHECL_SEC": 5.0, - "ATTACK_LAY_CHANCE": 25.0, - "DIST_TO_COVER_TO_LAY": 3.5, - "DIST_TO_COVER_TO_LAY_SQRT": 12.25, - "DIST_GRASS_TERRAIN_SQRT": 0.160000011, - "DIST_ENEMY_NULL_DANGER_LAY": 15.0, - "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225.0, - "DIST_ENEMY_GETUP_LAY": 10.0, - "DIST_ENEMY_GETUP_LAY_SQRT": 100.0, - "DIST_ENEMY_CAN_LAY": 15.0, - "DIST_ENEMY_CAN_LAY_SQRT": 225.0, - "LAY_AIM": 0.6, - "MIN_CAN_LAY_DIST_SQRT": 121.0, - "MIN_CAN_LAY_DIST": 11.0, - "MAX_CAN_LAY_DIST_SQRT": 40000.0, - "MAX_CAN_LAY_DIST": 200.0, - "LAY_CHANCE_DANGER": 40.0, - "DAMAGE_TIME_TO_GETUP": 3 - }, - "Aiming": { - "MAX_AIM_PRECICING": 2.0, - "BETTER_PRECICING_COEF": 0.9, - "RECALC_DIST": 0.7, - "RECALC_SQR_DIST": 0.48999998, - "COEF_FROM_COVER": 0.45, - "PANIC_COEF": 1.2, - "PANIC_ACCURATY_COEF": 1.2, - "HARD_AIM": 0.75, - "PANIC_TIME": 2.0, - "RECALC_MUST_TIME": 3, - "DAMAGE_PANIC_TIME": 15.0, - "DANGER_UP_POINT": 1.3, - "MAX_AIMING_UPGRADE_BY_TIME": 0.25, - "DAMAGE_TO_DISCARD_AIM_0_100": 86.0, - "MIN_TIME_DISCARD_AIM_SEC": 0.3, - "MAX_TIME_DISCARD_AIM_SEC": 0.6, - "XZ_COEF": 0.10, - "SHOOT_TO_CHANGE_PRIORITY": 5525, - "BOTTOM_COEF": 0.1, - "FIRST_CONTACT_ADD_SEC": 0.1, - "FIRST_CONTACT_ADD_CHANCE_100": 80.0, - "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, - "BASE_HIT_AFFECTION_MIN_ANG": 4.0, - "BASE_HIT_AFFECTION_MAX_ANG": 10.0, - "BASE_SHIEF": 0.05, - "SCATTERING_HAVE_DAMAGE_COEF": 2.0, - "SCATTERING_DIST_MODIF": 0.67, - "SCATTERING_DIST_MODIF_CLOSE": 0.6, - "AIMING_TYPE": 5, - "DIST_TO_SHOOT_TO_CENTER": 3.0, - "DIST_TO_SHOOT_NO_OFFSET": 3.0, - "SHPERE_FRIENDY_FIRE_SIZE": -0.1, - "COEF_IF_MOVE": 1.0, - "TIME_COEF_IF_MOVE": 1.1, - "BOT_MOVE_IF_DELTA": 3.01, - "NEXT_SHOT_MISS_CHANCE_100": 100.0, - "NEXT_SHOT_MISS_Y_OFFSET": 1.0, - "ANYTIME_LIGHT_WHEN_AIM_100": -1.0, - "ANY_PART_SHOOT_TIME": 15.0, - "WEAPON_ROOT_OFFSET": 0.35, - "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1.0, - "MAX_AIM_TIME": 1.5, - "OFFSET_RECAL_ANYWAY_TIME": 1.0, - "BASE_SHIEF_STATIONARY_GRENADE": 1.1, - "XZ_COEF_STATIONARY_GRENADE": 0.2, - "Y_TOP_OFFSET_COEF": 0.001, - "Y_BOTTOM_OFFSET_COEF": 0.015 - }, - "Look": { - "OLD_TIME_POINT": 11.0, - "WAIT_NEW_SENSOR": 2.1, - "WAIT_NEW__LOOK_SENSOR": 7.8, - "LOOK_AROUND_DELTA": 1.1, - "MAX_VISION_GRASS_METERS": 0.8, - "MAX_VISION_GRASS_METERS_FLARE": 8.0, - "MAX_VISION_GRASS_METERS_OPT": 0.9090909, - "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, - "LightOnVisionDistance": 45.0, - "FAR_DISTANCE": 160.0, - "FarDeltaTimeSec": 3.0, - "MIDDLE_DIST": 90.0, - "MiddleDeltaTimeSec": 1.0, - "CloseDeltaTimeSec": 0.1, - "POSIBLE_VISION_SPACE": 1.2, - "GOAL_TO_FULL_DISSAPEAR": 1.1, - "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, - "BODY_DELTA_TIME_SEARCH_SEC": 1.7, - "COME_TO_BODY_DIST": 1.2, - "MARKSMAN_VISIBLE_DIST_COEF": 1.15, - "VISIBLE_DISNACE_WITH_LIGHT": 100.0, - "ENEMY_LIGHT_ADD": 48.0, - "ENEMY_LIGHT_START_DIST": 90.0, - "CAN_LOOK_TO_WALL": true, - "DIST_NOT_TO_IGNORE_WALL": 15.0, - "DIST_CHECK_WALL": 20.0, - "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25.0, - "MIN_LOOK_AROUD_TIME": 20.0, - "OPTIMIZE_TO_ONLY_BODY": true - }, - "Shoot": { - "RECOIL_TIME_NORMALIZE": 1.0, - "RECOIL_PER_METER": 0.02, - "MAX_RECOIL_PER_METER": 0.1, - "HORIZONT_RECOIL_COEF": 0.1, - "WAIT_NEXT_SINGLE_SHOT": 0.2, - "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, - "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, - "MARKSMAN_DIST_SEK_COEF": 44.0, - "FINGER_HOLD_SINGLE_SHOT": 0.14, - "BASE_AUTOMATIC_TIME": 0.2, - "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, - "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94.0, - "FAR_DIST_ENEMY": 20.0, - "SHOOT_FROM_COVER": 4, - "FAR_DIST_ENEMY_SQR": 400.0, - "MAX_DIST_COEF": 1.35, - "RECOIL_DELTA_PRESS": 0.15, - "RUN_DIST_NO_AMMO": 25.0, - "RUN_DIST_NO_AMMO_SQRT": 625.0, - "CAN_SHOOTS_TIME_TO_AMBUSH": 993, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, - "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2.0, - "RELOAD_PECNET_NO_ENEMY": 0.6, - "CHANCE_TO_CHANGE_WEAPON": 100.0, - "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80.0, - "LOW_DIST_TO_CHANGE_WEAPON": 5.0, - "FAR_DIST_TO_CHANGE_WEAPON": 30.0, - "SUPPRESS_BY_SHOOT_TIME": 6.0, - "SUPPRESS_TRIGGERS_DOWN": 3, - "DIST_TO_CHANGE_TO_MAIN": 15.0, - "WAIT_NEXT_STATIONARY_GRENADE": 1.0, - "FINGER_HOLD_STATIONARY_GRENADE": 0.3, - "VALIDATE_MALFUNCTION_CHANCE": 0, - "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, - "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, - "DELAY_BEFORE_FIX_MALFUNCTION": 0.5 - }, - "Move": { - "BASE_ROTATE_SPEED": 270.0, - "REACH_DIST": 0.5, - "REACH_DIST_RUN": 0.8, - "START_SLOW_DIST": 1.5, - "BASESTART_SLOW_DIST": 1.1, - "SLOW_COEF": 7.0, - "DIST_TO_CAN_CHANGE_WAY": 8.0, - "DIST_TO_START_RAYCAST": 15.0, - "BASE_START_SERACH": 35.0, - "UPDATE_TIME_RECAL_WAY": 7.0, - "FAR_DIST": 4.0, - "FAR_DIST_SQR": 16.0, - "DIST_TO_CAN_CHANGE_WAY_SQR": 64.0, - "DIST_TO_START_RAYCAST_SQR": 225.0, - "BASE_SQRT_START_SERACH": 1225.0, - "Y_APPROXIMATION": 0.7, - "DELTA_LAST_SEEN_ENEMY": 20.0, - "REACH_DIST_COVER": 2.0, - "RUN_TO_COVER_MIN": 2.0, - "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100.0, - "RUN_IF_CANT_SHOOT": false, - "RUN_IF_GAOL_FAR_THEN": 10.0, - "SEC_TO_CHANGE_TO_RUN": 3.0, - "ETERNITY_STAMINA": true - }, - "Grenade": { - "DELTA_NEXT_ATTEMPT_FROM_COVER": 5.0, - "DELTA_NEXT_ATTEMPT": 10.0, - "MIN_DIST_NOT_TO_THROW": 8.0, - "NEAR_DELTA_THROW_TIME_SEC": 2.0, - "MIN_THROW_GRENADE_DIST": 12.0, - "MIN_THROW_GRENADE_DIST_SQRT": 144.0, - "MIN_DIST_NOT_TO_THROW_SQR": 64.0, - "RUN_AWAY": 22.0, - "RUN_AWAY_SQR": 484.0, - "ADD_GRENADE_AS_DANGER": 65.0, - "ADD_GRENADE_AS_DANGER_SQR": 4225.0, - "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100.0, - "GrenadePerMeter": 0.1, - "REQUEST_DIST_MUST_THROW_SQRT": 9.0, - "REQUEST_DIST_MUST_THROW": 3.0, - "BEWARE_TYPE": 2, - "SHOOT_TO_SMOKE_CHANCE_100": 50.0, - "CHANCE_RUN_FLASHED_100": 100.0, - "MAX_FLASHED_DIST_TO_SHOOT": 10.0, - "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100.0, - "FLASH_GRENADE_TIME_COEF": 0.25, - "SIZE_SPOTTED_COEF": 2.0, - "BE_ATTENTION_COEF": 4.0, - "TIME_SHOOT_TO_FLASH": 4.0, - "CLOSE_TO_SMOKE_TO_SHOOT": 10.0, - "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100.0, - "CLOSE_TO_SMOKE_TIME_DELTA": 5.0, - "SMOKE_CHECK_DELTA": 1.0, - "DELTA_GRENADE_START_TIME": 0.01, - "AMBUSH_IF_SMOKE_IN_ZONE_100": 40.0, - "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30.0, - "NO_RUN_FROM_AI_GRENADES": true, - "MAX_THROW_POWER": 25.0, - "MIN_THROW_DIST_PERCENT_0_1": 0.7, - "GrenadePrecision": 0.1, - "STOP_WHEN_THROW_GRENADE": true, - "WAIT_TIME_TURN_AWAY": 0.2, - "SMOKE_SUPPRESS_DELTA": 20.0, - "DAMAGE_GRENADE_SUPPRESS_DELTA": 8.0, - "STUN_SUPPRESS_DELTA": 9.0, - "CHEAT_START_GRENADE_PLACE": false, - "CAN_THROW_STRAIGHT_CONTACT": true, - "STRAIGHT_CONTACT_DELTA_SEC": -1.0, - "ANG_TYPE": 1 - }, - "Change": { - "SMOKE_VISION_DIST": 0.6, - "SMOKE_GAIN_SIGHT": 1.6, - "SMOKE_SCATTERING": 1.6, - "SMOKE_PRECICING": 1.6, - "SMOKE_HEARING": 1.0, - "SMOKE_ACCURATY": 1.6, - "SMOKE_LAY_CHANCE": 1.6, - "FLASH_VISION_DIST": 0.05, - "FLASH_GAIN_SIGHT": 1.8, - "FLASH_SCATTERING": 1.6, - "FLASH_PRECICING": 1.6, - "FLASH_HEARING": 1.0, - "FLASH_ACCURATY": 1.6, - "FLASH_LAY_CHANCE": 1.0, - "STUN_HEARING": 0.01 - }, - "Cover": { - "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20.0, - "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50.0, - "SOUND_TO_GET_SPOTTED": 2.0, - "TIME_TO_MOVE_TO_COVER": 15.0, - "MAX_DIST_OF_COVER": 4.0, - "CHANGE_RUN_TO_COVER_SEC": 5.0, - "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, - "MIN_DIST_TO_ENEMY": 9.0, - "DIST_CANT_CHANGE_WAY": 5.0, - "DIST_CHECK_SFETY": 9.0, - "TIME_CHECK_SAFE": 2.0, - "HIDE_TO_COVER_TIME": 1.5, - "MAX_DIST_OF_COVER_SQR": 16.0, - "DIST_CANT_CHANGE_WAY_SQR": 25.0, - "SPOTTED_COVERS_RADIUS": 2.5, - "LOOK_LAST_ENEMY_POS_MOVING": 1.5, - "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3.0, - "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45.0, - "OFFSET_LOOK_ALONG_WALL_ANG": 20, - "SPOTTED_GRENADE_RADIUS": 16.0, - "MAX_SPOTTED_TIME_SEC": 55.0, - "WAIT_INT_COVER_FINDING_ENEMY": 2.0, - "CLOSE_DIST_POINT_SQRT": 4.0, - "DELTA_SEEN_FROM_COVE_LAST_POS": 15.0, - "MOVE_TO_COVER_WHEN_TARGET": false, - "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, - "SPOTTED_GRENADE_TIME": 7.0, - "DEPENDS_Y_DIST_TO_BOT": false, - "RUN_IF_FAR": 15.0, - "RUN_IF_FAR_SQRT": 225.0, - "STAY_IF_FAR": 25.0, - "STAY_IF_FAR_SQRT": 625.0, - "CHECK_COVER_ENEMY_LOOK": false, - "SHOOT_NEAR_TO_LEAVE": 2, - "SHOOT_NEAR_SEC_PERIOD": 0.5, - "HITS_TO_LEAVE_COVER": 1, - "HITS_TO_LEAVE_COVER_UNKNOWN": 1, - "DOG_FIGHT_AFTER_LEAVE": 4.0, - "NOT_LOOK_AT_WALL_IS_DANGER": true, - "MIN_DEFENCE_LEVEL": 22.0, - "REWORK_NOT_TO_SHOOT": true, - "DELETE_POINTS_BEHIND_ENEMIES": true, - "GOOD_DIST_TO_POINT_COEF": 1.8, - "ENEMY_DIST_TO_GO_OUT": 1.0, - "CHECK_CLOSEST_FRIEND": false, - "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15.0 - }, - "Patrol": { - "LOOK_TIME_BASE": 12.0, - "RESERVE_TIME_STAY": 72.0, - "FRIEND_SEARCH_SEC": 12.0, - "TALK_DELAY": 31.1, - "MIN_TALK_DELAY": 35.0, - "TALK_DELAY_BIG": 45.1, - "CHANGE_WAY_TIME": 3325.1, - "MIN_DIST_TO_CLOSE_TALK": 5.0, - "VISION_DIST_COEF_PEACE": 1.0, - "MIN_DIST_TO_CLOSE_TALK_SQR": 25.0, - "CHANCE_TO_CUT_WAY_0_100": 75.0, - "CUT_WAY_MIN_0_1": 0.4, - "CUT_WAY_MAX_0_1": 0.65, - "CHANCE_TO_CHANGE_WAY_0_100": 30.0, - "CHANCE_TO_SHOOT_DEADBODY": 52, - "SUSPETION_PLACE_LIFETIME": 7.0, - "RESERVE_OUT_TIME": 60.0, - "CLOSE_TO_SELECT_RESERV_WAY": 25.0, - "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5.0, - "CAN_CHOOSE_RESERV": true, - "TRY_CHOOSE_RESERV_WAY_ON_START": true - }, - "Hearing": { - "BOT_CLOSE_PANIC_DIST": 1.0, - "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, - "DISPERSION_COEF": 10.0, - "CLOSE_DIST": 26.0, - "FAR_DIST": 56.0, - "SOUND_DIR_DEEFREE": 30.0, - "DIST_PLACE_TO_FIND_POINT": 70.0, - "DEAD_BODY_SOUND_RAD": 30.0, - "LOOK_ONLY_DANGER": false, - "RESET_TIMER_DIST": 17.0, - "HEAR_DELAY_WHEN_PEACE": 0.0, - "HEAR_DELAY_WHEN_HAVE_SMT": 0.0, - "LOOK_ONLY_DANGER_DELTA": 9.0 - }, - "Mind": { - "MIN_SHOOTS_TIME": 2, - "MAX_SHOOTS_TIME": 4, - "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15.0, - "DAMAGE_REDUCTION_TIME_SEC": 20.0, - "MIN_DAMAGE_SCARE": 20.0, - "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35.0, - "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52.0, - "TIME_TO_FIND_ENEMY": 22.0, - "MAX_AGGRO_BOT_DIST": 100.0, - "HIT_POINT_DETECTION": 4.0, - "DANGER_POINT_CHOOSE_COEF": 1.0, - "SIMPLE_POINT_CHOOSE_COEF": 0.4, - "LASTSEEN_POINT_CHOOSE_COEF": 0.2, - "COVER_DIST_COEF": 1.5, - "DIST_TO_FOUND_SQRT": 400.0, - "MAX_AGGRO_BOT_DIST_SQR": 10000.0, - "DIST_TO_STOP_RUN_ENEMY": 15.0, - "ENEMY_LOOK_AT_ME_ANG": 15.0, - "MIN_START_AGGRESION_COEF": 1.0, - "MAX_START_AGGRESION_COEF": 3.0, - "BULLET_FEEL_DIST": 360.0, - "BULLET_FEEL_CLOSE_SDIST": 1.0, - "ATTACK_IMMEDIATLY_CHANCE_0_100": 40.0, - "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, - "FRIEND_DEAD_AGR_LOW": -0.2, - "FRIEND_AGR_KILL": 0.2, - "LAST_ENEMY_LOOK_TO": 40.0, - "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, - "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, - "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, - "CAN_USE_MEDS": true, - "SUSPETION_POINT_CHANCE_ADD100": 0.0, - "AMBUSH_WHEN_UNDER_FIRE": true, - "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60.0, - "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, - "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, - "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2.0, - "PROTECT_TIME_REAL": true, - "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25.0, - "CAN_PANIC_IS_PROTECT": false, - "NO_RUN_AWAY_FOR_SAFE": true, - "PART_PERCENT_TO_HEAL": 0.65, - "PROTECT_DELTA_HEAL_SEC": 10.0, - "CAN_STAND_BY": false, - "CAN_THROW_REQUESTS": true, - "GROUP_ANY_PHRASE_DELAY": 20.0, - "GROUP_EXACTLY_PHRASE_DELAY": 20.0, - "DIST_TO_ENEMY_YO_CAN_HEAL": 30.0, - "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80.0, - "DOG_FIGHT_OUT": 6.0, - "DOG_FIGHT_IN": 3.0, - "SHOOT_INSTEAD_DOG_FIGHT": 9.0, - "PISTOL_SHOTGUN_AMBUSH_DIST": 30.0, - "STANDART_AMBUSH_DIST": 100.0, - "AI_POWER_COEF": 120.0, - "COVER_SECONDS_AFTER_LOSE_VISION": 10.0, - "COVER_SELF_ALWAYS_IF_DAMAGED": false, - "SEC_TO_MORE_DIST_TO_RUN": 10.0, - "HEAL_DELAY_SEC": 5.0, - "HIT_DELAY_WHEN_HAVE_SMT": -1.0, - "HIT_DELAY_WHEN_PEACE": -1.0, - "TALK_WITH_QUERY": true, - "DANGER_EXPIRE_TIME_MIN": 0.4, - "DANGER_EXPIRE_TIME_MAX": 1.2, - "PANIC_RUN_WEIGHT": 1.0, - "PANIC_SIT_WEIGHT": 80.0, - "PANIC_LAY_WEIGHT": 20.0, - "PANIC_NONE_WEIGHT": 40.0, - "CAN_TAKE_ITEMS": false, - "PANIC_SIT_WEIGHT_PEACE": 60.0 - }, - "Boss": { - "BOSS_DIST_TO_WARNING": 34.0, - "BOSS_DIST_TO_WARNING_SQRT": 1156.0, - "BOSS_DIST_TO_WARNING_OUT": 43.0, - "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849.0, - "BOSS_DIST_TO_SHOOT": 16.0, - "BOSS_DIST_TO_SHOOT_SQRT": 256.0, - "CHANCE_TO_SEND_GRENADE_100": 100.0, - "MAX_DIST_COVER_BOSS": 25.0, - "MAX_DIST_COVER_BOSS_SQRT": 625.0, - "MAX_DIST_DECIDER_TO_SEND": 35.0, - "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225.0, - "TIME_AFTER_LOSE": 15.0, - "TIME_AFTER_LOSE_DELTA": 60.0, - "PERSONS_SEND": 2, - "DELTA_SEARCH_TIME": 18.0, - "COVER_TO_SEND": true, - "WAIT_NO_ATTACK_SAVAGE": 10.0, - "CHANCE_USE_RESERVE_PATROL_100": 30.0, - "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5.0, - "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65.0, - "KILLA_START_SEARCH_SEC": 40.0, - "KILLA_CONTUTION_TIME": 5.0, - "KILLA_CLOSE_ATTACK_DIST": 8.0, - "KILLA_MIDDLE_ATTACK_DIST": 32.0, - "KILLA_LARGE_ATTACK_DIST": 61.0, - "KILLA_SEARCH_METERS": 30.0, - "KILLA_DEF_DIST_SQRT": 225.0, - "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25.0, - "KILLA_DIST_TO_GO_TO_SUPPRESS": 6.0, - "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2.0, - "KILLA_CLOSEATTACK_TIMES": 3, - "KILLA_CLOSEATTACK_DELAY": 10.0, - "KILLA_HOLD_DELAY": 5.0, - "KILLA_BULLET_TO_RELOAD": 15, - "SHALL_WARN": true, - "KOJANIY_DIST_WHEN_READY": 40.0, - "KOJANIY_DIST_TO_BE_ENEMY": 200.0, - "KOJANIY_MIN_DIST_TO_LOOT": 20.0, - "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400.0, - "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17.0, - "KOJANIY_MANY_ENEMIES_COEF": 1.5, - "KILLA_ENEMIES_TO_ATTACK": 3, - "KILLA_ONE_IS_CLOSE": 20.0, - "KILLA_TRIGGER_DOWN_DELAY": 0.1, - "KILLA_WAIT_IN_COVER_COEF": 0.1, - "KOJANIY_COVER_POWER": 500.0, - "KOJANIY_FIGHT_CENTER_POS_ME": false, - "KOJANIY_DIST_CORE_SPOS_RECALC": 25.0, - "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625.0, - "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", - "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, - "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, - "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, - "GLUHAR_ASSAULT_ATTACK_DIST": 30, - "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, - "GLUHAR_TIME_TO_ASSAULT": 10, - "DIST_TO_PROTECT_BOSS": 15 - }, - "Core": { - "VisibleAngle": 160.0, - "VisibleDistance": 142.0, - "GainSightCoef": 0.1, - "ScatteringPerMeter": 0.045, - "ScatteringClosePerMeter": 0.12, - "DamageCoeff": 1.0, - "HearingSense": 3.9, - "CanRun": true, - "CanGrenade": true, - "AimingType": "normal", - "PistolFireDistancePref": 35.0, - "ShotgunFireDistancePref": 50.0, - "RifleFireDistancePref": 100.0, - "AccuratySpeed": 0.2, - "WaitInCoverBetweenShotsSec": 0.3 - }, - "Scattering": { - "MinScatter": 0.03, - "WorkingScatter": 0.15, - "MaxScatter": 0.4, - "SpeedUp": 0.3, - "SpeedUpAim": 1.4, - "SpeedDown": -0.3, - "ToSlowBotSpeed": 1.5, - "ToLowBotSpeed": 2.4, - "ToUpBotSpeed": 3.6, - "MovingSlowCoef": 1.5, - "ToLowBotAngularSpeed": 80.0, - "ToStopBotAngularSpeed": 40.0, - "FromShot": 0.001, - "TracerCoef": 1.3, - "HandDamageScatteringMinMax": 0.7, - "HandDamageAccuracySpeed": 1.3, - "BloodFall": 1.45, - "Caution": 0.3, - "ToCaution": 0.6, - "RecoilControlCoefShootDone": 0.0003, - "RecoilControlCoefShootDoneAuto": 0.00015, - "AMPLITUDE_FACTOR": 0.25, - "AMPLITUDE_SPEED": 0.1, - "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15.0, - "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225.0, - "DIST_NOT_TO_SHOOT": 0.3, - "PoseChnageCoef": 0.1, - "LayFactor": 0.1, - "RecoilYCoef": 0.0005, - "RecoilYCoefSppedDown": -0.52, - "RecoilYMax": 1.0 - } - } - }, - "chances": { - "equipment": { - "Headwear": 0, - "Earpiece": 0, - "FaceCover": 0, - "ArmorVest": 0, - "Eyewear": 0, - "ArmBand": 0, - "TacticalVest": 0, - "Backpack": 0, - "FirstPrimaryWeapon": 0, - "SecondPrimaryWeapon": 0, - "Holster": 0, - "Scabbard": 0 - }, - "mods": {} - }, - "generation": { - "items": { - "specialItems": { - "min": 0, - "max": 0 - }, - "healing": { - "min": 0, - "max": 0 - }, - "drugs": { - "max": 1, - "min": 0 - }, - "stims": { - "min": 0, - "max": 1 - }, - "looseLoot": { - "min": 0, - "max": 0 - }, - "magazines": { - "min": 0, - "max": 0 - }, - "grenades": { - "min": 0, - "max": 0 - } - } + "normal": { + "Aiming": { + "AIMING_TYPE": 5, + "ANYTIME_LIGHT_WHEN_AIM_100": -1, + "ANY_PART_SHOOT_TIME": 15, + "BASE_HIT_AFFECTION_DELAY_SEC": 0.57, + "BASE_HIT_AFFECTION_MAX_ANG": 10, + "BASE_HIT_AFFECTION_MIN_ANG": 4, + "BASE_SHIEF": 0.05, + "BASE_SHIEF_STATIONARY_GRENADE": 1.1, + "BETTER_PRECICING_COEF": 0.9, + "BOTTOM_COEF": 0.1, + "BOT_MOVE_IF_DELTA": 3.01, + "COEF_FROM_COVER": 0.45, + "COEF_IF_MOVE": 1, + "DAMAGE_PANIC_TIME": 15, + "DAMAGE_TO_DISCARD_AIM_0_100": 86, + "DANGER_UP_POINT": 1.3, + "DIST_TO_SHOOT_NO_OFFSET": 3, + "DIST_TO_SHOOT_TO_CENTER": 3, + "FIRST_CONTACT_ADD_CHANCE_100": 80, + "FIRST_CONTACT_ADD_SEC": 0.1, + "HARD_AIM": 0.75, + "MAX_AIMING_UPGRADE_BY_TIME": 0.25, + "MAX_AIM_PRECICING": 2, + "MAX_AIM_TIME": 1.5, + "MAX_TIME_DISCARD_AIM_SEC": 0.6, + "MIN_DAMAGE_TO_GET_HIT_AFFETS": 1, + "MIN_TIME_DISCARD_AIM_SEC": 0.3, + "NEXT_SHOT_MISS_CHANCE_100": 100, + "NEXT_SHOT_MISS_Y_OFFSET": 1, + "OFFSET_RECAL_ANYWAY_TIME": 1, + "PANIC_ACCURATY_COEF": 1.2, + "PANIC_COEF": 1.2, + "PANIC_TIME": 2, + "RECALC_DIST": 0.7, + "RECALC_MUST_TIME": 3, + "RECALC_SQR_DIST": 0.48999998, + "SCATTERING_DIST_MODIF": 0.67, + "SCATTERING_DIST_MODIF_CLOSE": 0.6, + "SCATTERING_HAVE_DAMAGE_COEF": 2, + "SHOOT_TO_CHANGE_PRIORITY": 5525, + "SHPERE_FRIENDY_FIRE_SIZE": -0.1, + "TIME_COEF_IF_MOVE": 1.1, + "WEAPON_ROOT_OFFSET": 0.35, + "XZ_COEF": 0.1, + "XZ_COEF_STATIONARY_GRENADE": 0.2, + "Y_BOTTOM_OFFSET_COEF": 0.015, + "Y_TOP_OFFSET_COEF": 0.001 + }, + "Boss": { + "BOSS_DIST_TO_SHOOT": 16, + "BOSS_DIST_TO_SHOOT_SQRT": 256, + "BOSS_DIST_TO_WARNING": 34, + "BOSS_DIST_TO_WARNING_OUT": 43, + "BOSS_DIST_TO_WARNING_OUT_SQRT": 1849, + "BOSS_DIST_TO_WARNING_SQRT": 1156, + "CHANCE_TO_SEND_GRENADE_100": 100, + "CHANCE_USE_RESERVE_PATROL_100": 30, + "COVER_TO_SEND": true, + "DELTA_SEARCH_TIME": 18, + "DIST_TO_PROTECT_BOSS": 15, + "GLUHAR_ASSAULT_ATTACK_DIST": 30, + "GLUHAR_BOSS_WANNA_ATTACK_CHANCE_0_100": 150, + "GLUHAR_FOLLOWER_PATH_NAME": "Snipe", + "GLUHAR_FOLLOWER_SCOUT_DIST_END_ATTACK": 120, + "GLUHAR_FOLLOWER_SCOUT_DIST_START_ATTACK": 80, + "GLUHAR_STOP_ASSAULT_ATTACK_DIST": 180, + "GLUHAR_TIME_TO_ASSAULT": 10, + "KILLA_AFTER_GRENADE_SUPPRESS_DELAY": 2, + "KILLA_BULLET_TO_RELOAD": 15, + "KILLA_CLOSEATTACK_DELAY": 10, + "KILLA_CLOSEATTACK_TIMES": 3, + "KILLA_CLOSE_ATTACK_DIST": 8, + "KILLA_CONTUTION_TIME": 5, + "KILLA_DEF_DIST_SQRT": 225, + "KILLA_DIST_TO_GO_TO_SUPPRESS": 6, + "KILLA_DITANCE_TO_BE_ENEMY_BOSS": 65, + "KILLA_ENEMIES_TO_ATTACK": 3, + "KILLA_HOLD_DELAY": 5, + "KILLA_LARGE_ATTACK_DIST": 61, + "KILLA_MIDDLE_ATTACK_DIST": 32, + "KILLA_ONE_IS_CLOSE": 20, + "KILLA_SEARCH_METERS": 30, + "KILLA_SEARCH_SEC_STOP_AFTER_COMING": 25, + "KILLA_START_SEARCH_SEC": 40, + "KILLA_TRIGGER_DOWN_DELAY": 0.1, + "KILLA_WAIT_IN_COVER_COEF": 0.1, + "KILLA_Y_DELTA_TO_BE_ENEMY_BOSS": 5, + "KOJANIY_COVER_POWER": 500, + "KOJANIY_DIST_CORE_SPOS_RECALC": 25, + "KOJANIY_DIST_CORE_SPOS_RECALC_SQRT": 625, + "KOJANIY_DIST_ENEMY_TOO_CLOSE": 17, + "KOJANIY_DIST_TO_BE_ENEMY": 200, + "KOJANIY_DIST_WHEN_READY": 40, + "KOJANIY_FIGHT_CENTER_POS_ME": false, + "KOJANIY_MANY_ENEMIES_COEF": 1.5, + "KOJANIY_MIN_DIST_TO_LOOT": 20, + "KOJANIY_MIN_DIST_TO_LOOT_SQRT": 400, + "MAX_DIST_COVER_BOSS": 25, + "MAX_DIST_COVER_BOSS_SQRT": 625, + "MAX_DIST_DECIDER_TO_SEND": 35, + "MAX_DIST_DECIDER_TO_SEND_SQRT": 1225, + "PERSONS_SEND": 2, + "SHALL_WARN": true, + "TIME_AFTER_LOSE": 15, + "TIME_AFTER_LOSE_DELTA": 60, + "WAIT_NO_ATTACK_SAVAGE": 10 + }, + "Change": { + "FLASH_ACCURATY": 1.6, + "FLASH_GAIN_SIGHT": 1.8, + "FLASH_HEARING": 1, + "FLASH_LAY_CHANCE": 1, + "FLASH_PRECICING": 1.6, + "FLASH_SCATTERING": 1.6, + "FLASH_VISION_DIST": 0.05, + "SMOKE_ACCURATY": 1.6, + "SMOKE_GAIN_SIGHT": 1.6, + "SMOKE_HEARING": 1, + "SMOKE_LAY_CHANCE": 1.6, + "SMOKE_PRECICING": 1.6, + "SMOKE_SCATTERING": 1.6, + "SMOKE_VISION_DIST": 0.6, + "STUN_HEARING": 0.01 + }, + "Core": { + "AccuratySpeed": 0.2, + "AimingType": "normal", + "CanGrenade": true, + "CanRun": true, + "DamageCoeff": 1, + "GainSightCoef": 0.1, + "HearingSense": 3.9, + "PistolFireDistancePref": 35, + "RifleFireDistancePref": 100, + "ScatteringClosePerMeter": 0.12, + "ScatteringPerMeter": 0.045, + "ShotgunFireDistancePref": 50, + "VisibleAngle": 160, + "VisibleDistance": 142, + "WaitInCoverBetweenShotsSec": 0.3 + }, + "Cover": { + "CHANGE_RUN_TO_COVER_SEC": 5, + "CHANGE_RUN_TO_COVER_SEC_GREANDE": 0.6, + "CHECK_CLOSEST_FRIEND": false, + "CHECK_COVER_ENEMY_LOOK": false, + "CLOSE_DIST_POINT_SQRT": 4, + "DELETE_POINTS_BEHIND_ENEMIES": true, + "DELTA_SEEN_FROM_COVE_LAST_POS": 15, + "DEPENDS_Y_DIST_TO_BOT": false, + "DIST_CANT_CHANGE_WAY": 5, + "DIST_CANT_CHANGE_WAY_SQR": 25, + "DIST_CHECK_SFETY": 9, + "DOG_FIGHT_AFTER_LEAVE": 4, + "ENEMY_DIST_TO_GO_OUT": 1, + "GOOD_DIST_TO_POINT_COEF": 1.8, + "HIDE_TO_COVER_TIME": 1.5, + "HITS_TO_LEAVE_COVER": 1, + "HITS_TO_LEAVE_COVER_UNKNOWN": 1, + "LOOK_LAST_ENEMY_POS_LOOKAROUND": 45, + "LOOK_LAST_ENEMY_POS_MOVING": 1.5, + "LOOK_TO_HIT_POINT_IF_LAST_ENEMY": 3, + "MAX_DIST_OF_COVER": 4, + "MAX_DIST_OF_COVER_SQR": 16, + "MAX_SPOTTED_TIME_SEC": 55, + "MIN_DEFENCE_LEVEL": 22, + "MIN_DIST_TO_ENEMY": 9, + "MOVE_TO_COVER_WHEN_TARGET": false, + "NOT_LOOK_AT_WALL_IS_DANGER": true, + "OFFSET_LOOK_ALONG_WALL_ANG": 20, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MAX": 50, + "RETURN_TO_ATTACK_AFTER_AMBUSH_MIN": 20, + "REWORK_NOT_TO_SHOOT": true, + "RUN_COVER_IF_CAN_AND_NO_ENEMIES": false, + "RUN_IF_FAR": 15, + "RUN_IF_FAR_SQRT": 225, + "SHOOT_NEAR_SEC_PERIOD": 0.5, + "SHOOT_NEAR_TO_LEAVE": 2, + "SOUND_TO_GET_SPOTTED": 2, + "SPOTTED_COVERS_RADIUS": 2.5, + "SPOTTED_GRENADE_RADIUS": 16, + "SPOTTED_GRENADE_TIME": 7, + "STATIONARY_WEAPON_NO_ENEMY_GETUP": 15, + "STAY_IF_FAR": 25, + "STAY_IF_FAR_SQRT": 625, + "TIME_CHECK_SAFE": 2, + "TIME_TO_MOVE_TO_COVER": 15, + "WAIT_INT_COVER_FINDING_ENEMY": 2 + }, + "Grenade": { + "ADD_GRENADE_AS_DANGER": 65, + "ADD_GRENADE_AS_DANGER_SQR": 4225, + "AMBUSH_IF_SMOKE_IN_ZONE_100": 40, + "AMBUSH_IF_SMOKE_RETURN_TO_ATTACK_SEC": 30, + "ANG_TYPE": 1, + "BEWARE_TYPE": 2, + "BE_ATTENTION_COEF": 4, + "CAN_THROW_STRAIGHT_CONTACT": true, + "CHANCE_RUN_FLASHED_100": 100, + "CHANCE_TO_NOTIFY_ENEMY_GR_100": 100, + "CHEAT_START_GRENADE_PLACE": false, + "CLOSE_TO_SMOKE_TIME_DELTA": 5, + "CLOSE_TO_SMOKE_TO_SHOOT": 10, + "CLOSE_TO_SMOKE_TO_SHOOT_SQRT": 100, + "DAMAGE_GRENADE_SUPPRESS_DELTA": 8, + "DELTA_GRENADE_START_TIME": 0.01, + "DELTA_NEXT_ATTEMPT": 10, + "DELTA_NEXT_ATTEMPT_FROM_COVER": 5, + "FLASH_GRENADE_TIME_COEF": 0.25, + "GrenadePerMeter": 0.1, + "GrenadePrecision": 0.1, + "MAX_FLASHED_DIST_TO_SHOOT": 10, + "MAX_FLASHED_DIST_TO_SHOOT_SQRT": 100, + "MAX_THROW_POWER": 25, + "MIN_DIST_NOT_TO_THROW": 8, + "MIN_DIST_NOT_TO_THROW_SQR": 64, + "MIN_THROW_DIST_PERCENT_0_1": 0.7, + "MIN_THROW_GRENADE_DIST": 12, + "MIN_THROW_GRENADE_DIST_SQRT": 144, + "NEAR_DELTA_THROW_TIME_SEC": 2, + "NO_RUN_FROM_AI_GRENADES": true, + "REQUEST_DIST_MUST_THROW": 3, + "REQUEST_DIST_MUST_THROW_SQRT": 9, + "RUN_AWAY": 22, + "RUN_AWAY_SQR": 484, + "SHOOT_TO_SMOKE_CHANCE_100": 50, + "SIZE_SPOTTED_COEF": 2, + "SMOKE_CHECK_DELTA": 1, + "SMOKE_SUPPRESS_DELTA": 20, + "STOP_WHEN_THROW_GRENADE": true, + "STRAIGHT_CONTACT_DELTA_SEC": -1, + "STUN_SUPPRESS_DELTA": 9, + "TIME_SHOOT_TO_FLASH": 4, + "WAIT_TIME_TURN_AWAY": 0.2 + }, + "Hearing": { + "BOT_CLOSE_PANIC_DIST": 1, + "CHANCE_TO_HEAR_SIMPLE_SOUND_0_1": 0.88, + "CLOSE_DIST": 26, + "DEAD_BODY_SOUND_RAD": 30, + "DISPERSION_COEF": 10, + "DIST_PLACE_TO_FIND_POINT": 70, + "FAR_DIST": 56, + "HEAR_DELAY_WHEN_HAVE_SMT": 0, + "HEAR_DELAY_WHEN_PEACE": 0, + "LOOK_ONLY_DANGER": false, + "LOOK_ONLY_DANGER_DELTA": 9, + "RESET_TIMER_DIST": 17, + "SOUND_DIR_DEEFREE": 30 + }, + "Lay": { + "ATTACK_LAY_CHANCE": 25, + "CHECK_SHOOT_WHEN_LAYING": false, + "CLEAR_POINTS_OF_SCARE_SEC": 20, + "DAMAGE_TIME_TO_GETUP": 3, + "DELTA_AFTER_GETUP": 10, + "DELTA_GETUP": 2.7, + "DELTA_LAY_CHECK": 2, + "DELTA_WANT_LAY_CHECL_SEC": 5, + "DIST_ENEMY_CAN_LAY": 15, + "DIST_ENEMY_CAN_LAY_SQRT": 225, + "DIST_ENEMY_GETUP_LAY": 10, + "DIST_ENEMY_GETUP_LAY_SQRT": 100, + "DIST_ENEMY_NULL_DANGER_LAY": 15, + "DIST_ENEMY_NULL_DANGER_LAY_SQRT": 225, + "DIST_GRASS_TERRAIN_SQRT": 0.160000011, + "DIST_TO_COVER_TO_LAY": 3.5, + "DIST_TO_COVER_TO_LAY_SQRT": 12.25, + "LAY_AIM": 0.6, + "LAY_CHANCE_DANGER": 40, + "MAX_CAN_LAY_DIST": 200, + "MAX_CAN_LAY_DIST_SQRT": 40000, + "MAX_LAY_TIME": 35, + "MIN_CAN_LAY_DIST": 11, + "MIN_CAN_LAY_DIST_SQRT": 121 + }, + "Look": { + "BODY_DELTA_TIME_SEARCH_SEC": 1.7, + "CAN_LOOK_TO_WALL": true, + "COME_TO_BODY_DIST": 1.2, + "CloseDeltaTimeSec": 0.1, + "DIST_CHECK_WALL": 20, + "DIST_NOT_TO_IGNORE_WALL": 15, + "ENEMY_LIGHT_ADD": 48, + "ENEMY_LIGHT_START_DIST": 90, + "FAR_DISTANCE": 160, + "FarDeltaTimeSec": 3, + "GOAL_TO_FULL_DISSAPEAR": 1.1, + "GOAL_TO_FULL_DISSAPEAR_SHOOT": 0.03, + "LOOK_AROUND_DELTA": 1.1, + "LOOK_LAST_POSENEMY_IF_NO_DANGER_SEC": 25, + "LightOnVisionDistance": 45, + "MARKSMAN_VISIBLE_DIST_COEF": 1.15, + "MAX_VISION_GRASS_METERS": 0.8, + "MAX_VISION_GRASS_METERS_FLARE": 8, + "MAX_VISION_GRASS_METERS_FLARE_OPT": 0.125, + "MAX_VISION_GRASS_METERS_OPT": 0.9090909, + "MIDDLE_DIST": 90, + "MIN_LOOK_AROUD_TIME": 20, + "MiddleDeltaTimeSec": 1, + "OLD_TIME_POINT": 11, + "OPTIMIZE_TO_ONLY_BODY": true, + "POSIBLE_VISION_SPACE": 1.2, + "VISIBLE_DISNACE_WITH_LIGHT": 100, + "WAIT_NEW_SENSOR": 2.1, + "WAIT_NEW__LOOK_SENSOR": 7.8 + }, + "Mind": { + "AI_POWER_COEF": 120, + "AMBUSH_WHEN_UNDER_FIRE": true, + "AMBUSH_WHEN_UNDER_FIRE_TIME_RESIST": 60, + "ATTACK_ENEMY_IF_PROTECT_DELTA_LAST_TIME_SEEN": 1.5, + "ATTACK_IMMEDIATLY_CHANCE_0_100": 40, + "BULLET_FEEL_CLOSE_SDIST": 1, + "BULLET_FEEL_DIST": 360, + "CAN_PANIC_IS_PROTECT": false, + "CAN_RECEIVE_PLAYER_REQUESTS_BEAR": false, + "CAN_RECEIVE_PLAYER_REQUESTS_SAVAGE": false, + "CAN_RECEIVE_PLAYER_REQUESTS_USEC": false, + "CAN_STAND_BY": false, + "CAN_TAKE_ITEMS": false, + "CAN_THROW_REQUESTS": true, + "CAN_USE_MEDS": true, + "CHANCE_FUCK_YOU_ON_CONTACT_100": 0.01, + "CHANCE_SHOOT_WHEN_WARN_PLAYER_100": 25, + "CHANCE_TO_RUN_CAUSE_DAMAGE_0_100": 35, + "CHANCE_TO_STAY_WHEN_WARN_PLAYER_100": 80, + "COVER_DIST_COEF": 1.5, + "COVER_SECONDS_AFTER_LOSE_VISION": 10, + "COVER_SELF_ALWAYS_IF_DAMAGED": false, + "DAMAGE_REDUCTION_TIME_SEC": 20, + "DANGER_EXPIRE_TIME_MAX": 1.2, + "DANGER_EXPIRE_TIME_MIN": 0.4, + "DANGER_POINT_CHOOSE_COEF": 1, + "DIST_TO_ENEMY_YO_CAN_HEAL": 30, + "DIST_TO_FOUND_SQRT": 400, + "DIST_TO_STOP_RUN_ENEMY": 15, + "DOG_FIGHT_IN": 3, + "DOG_FIGHT_OUT": 6, + "ENEMY_LOOK_AT_ME_ANG": 15, + "FIND_COVER_TO_GET_POSITION_WITH_SHOOT": 2, + "FRIEND_AGR_KILL": 0.2, + "FRIEND_DEAD_AGR_LOW": -0.2, + "GROUP_ANY_PHRASE_DELAY": 20, + "GROUP_EXACTLY_PHRASE_DELAY": 20, + "HEAL_DELAY_SEC": 5, + "HIT_DELAY_WHEN_HAVE_SMT": -1, + "HIT_DELAY_WHEN_PEACE": -1, + "HIT_POINT_DETECTION": 4, + "HOLD_IF_PROTECT_DELTA_LAST_TIME_SEEN": 8.5, + "LASTSEEN_POINT_CHOOSE_COEF": 0.2, + "LAST_ENEMY_LOOK_TO": 40, + "MAX_AGGRO_BOT_DIST": 100, + "MAX_AGGRO_BOT_DIST_SQR": 10000, + "MAX_SHOOTS_TIME": 4, + "MAX_START_AGGRESION_COEF": 3, + "MIN_DAMAGE_SCARE": 20, + "MIN_SHOOTS_TIME": 2, + "MIN_START_AGGRESION_COEF": 1, + "NO_RUN_AWAY_FOR_SAFE": true, + "PANIC_LAY_WEIGHT": 20, + "PANIC_NONE_WEIGHT": 40, + "PANIC_RUN_WEIGHT": 1, + "PANIC_SIT_WEIGHT": 80, + "PANIC_SIT_WEIGHT_PEACE": 60, + "PART_PERCENT_TO_HEAL": 0.65, + "PISTOL_SHOTGUN_AMBUSH_DIST": 30, + "PROTECT_DELTA_HEAL_SEC": 10, + "PROTECT_TIME_REAL": true, + "SEC_TO_MORE_DIST_TO_RUN": 10, + "SHOOT_INSTEAD_DOG_FIGHT": 9, + "SIMPLE_POINT_CHOOSE_COEF": 0.4, + "STANDART_AMBUSH_DIST": 100, + "SUSPETION_POINT_CHANCE_ADD100": 0, + "TALK_WITH_QUERY": true, + "TIME_TO_FIND_ENEMY": 22, + "TIME_TO_FORGOR_ABOUT_ENEMY_SEC": 52, + "TIME_TO_RUN_TO_COVER_CAUSE_SHOOT_SEC": 15 + }, + "Move": { + "BASESTART_SLOW_DIST": 1.1, + "BASE_ROTATE_SPEED": 270, + "BASE_SQRT_START_SERACH": 1225, + "BASE_START_SERACH": 35, + "CHANCE_TO_RUN_IF_NO_AMMO_0_100": 100, + "DELTA_LAST_SEEN_ENEMY": 20, + "DIST_TO_CAN_CHANGE_WAY": 8, + "DIST_TO_CAN_CHANGE_WAY_SQR": 64, + "DIST_TO_START_RAYCAST": 15, + "DIST_TO_START_RAYCAST_SQR": 225, + "ETERNITY_STAMINA": true, + "FAR_DIST": 4, + "FAR_DIST_SQR": 16, + "REACH_DIST": 0.5, + "REACH_DIST_COVER": 2, + "REACH_DIST_RUN": 0.8, + "RUN_IF_CANT_SHOOT": false, + "RUN_IF_GAOL_FAR_THEN": 10, + "RUN_TO_COVER_MIN": 2, + "SEC_TO_CHANGE_TO_RUN": 3, + "SLOW_COEF": 7, + "START_SLOW_DIST": 1.5, + "UPDATE_TIME_RECAL_WAY": 7, + "Y_APPROXIMATION": 0.7 + }, + "Patrol": { + "CAN_CHOOSE_RESERV": true, + "CHANCE_TO_CHANGE_WAY_0_100": 30, + "CHANCE_TO_CUT_WAY_0_100": 75, + "CHANCE_TO_SHOOT_DEADBODY": 52, + "CHANGE_WAY_TIME": 3325.1, + "CLOSE_TO_SELECT_RESERV_WAY": 25, + "CUT_WAY_MAX_0_1": 0.65, + "CUT_WAY_MIN_0_1": 0.4, + "FRIEND_SEARCH_SEC": 12, + "LOOK_TIME_BASE": 12, + "MAX_YDIST_TO_START_WARN_REQUEST_TO_REQUESTER": 5, + "MIN_DIST_TO_CLOSE_TALK": 5, + "MIN_DIST_TO_CLOSE_TALK_SQR": 25, + "MIN_TALK_DELAY": 35, + "RESERVE_OUT_TIME": 60, + "RESERVE_TIME_STAY": 72, + "SUSPETION_PLACE_LIFETIME": 7, + "TALK_DELAY": 31.1, + "TALK_DELAY_BIG": 45.1, + "TRY_CHOOSE_RESERV_WAY_ON_START": true, + "VISION_DIST_COEF_PEACE": 1 + }, + "Scattering": { + "AMPLITUDE_FACTOR": 0.25, + "AMPLITUDE_SPEED": 0.1, + "BloodFall": 1.45, + "Caution": 0.3, + "DIST_FROM_OLD_POINT_TO_NOT_AIM": 15, + "DIST_FROM_OLD_POINT_TO_NOT_AIM_SQRT": 225, + "DIST_NOT_TO_SHOOT": 0.3, + "FromShot": 0.001, + "HandDamageAccuracySpeed": 1.3, + "HandDamageScatteringMinMax": 0.7, + "LayFactor": 0.1, + "MaxScatter": 0.4, + "MinScatter": 0.03, + "MovingSlowCoef": 1.5, + "PoseChnageCoef": 0.1, + "RecoilControlCoefShootDone": 0.0003, + "RecoilControlCoefShootDoneAuto": 0.00015, + "RecoilYCoef": 0.0005, + "RecoilYCoefSppedDown": -0.52, + "RecoilYMax": 1, + "SpeedDown": -0.3, + "SpeedUp": 0.3, + "SpeedUpAim": 1.4, + "ToCaution": 0.6, + "ToLowBotAngularSpeed": 80, + "ToLowBotSpeed": 2.4, + "ToSlowBotSpeed": 1.5, + "ToStopBotAngularSpeed": 40, + "ToUpBotSpeed": 3.6, + "TracerCoef": 1.3, + "WorkingScatter": 0.15 + }, + "Shoot": { + "AUTOMATIC_FIRE_SCATTERING_COEF": 1.5, + "BASE_AUTOMATIC_TIME": 0.2, + "CAN_SHOOTS_TIME_TO_AMBUSH": 993, + "CHANCE_TO_CHANGE_TO_AUTOMATIC_FIRE_100": 94, + "CHANCE_TO_CHANGE_WEAPON": 100, + "CHANCE_TO_CHANGE_WEAPON_WITH_HELMET": 80, + "DELAY_BEFORE_EXAMINE_MALFUNCTION": 0.5, + "DELAY_BEFORE_FIX_MALFUNCTION": 0.5, + "DIST_TO_CHANGE_TO_MAIN": 15, + "FAR_DIST_ENEMY": 20, + "FAR_DIST_ENEMY_SQR": 400, + "FAR_DIST_TO_CHANGE_WEAPON": 30, + "FINGER_HOLD_SINGLE_SHOT": 0.14, + "FINGER_HOLD_STATIONARY_GRENADE": 0.3, + "HORIZONT_RECOIL_COEF": 0.1, + "LOW_DIST_TO_CHANGE_WEAPON": 5, + "MARKSMAN_DIST_SEK_COEF": 44, + "MAX_DIST_COEF": 1.35, + "MAX_RECOIL_PER_METER": 0.1, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_PERCENT": 0.5, + "NOT_TO_SEE_ENEMY_TO_WANT_RELOAD_SEC": 2, + "RECOIL_DELTA_PRESS": 0.15, + "RECOIL_PER_METER": 0.02, + "RECOIL_TIME_NORMALIZE": 1, + "RELOAD_PECNET_NO_ENEMY": 0.6, + "REPAIR_MALFUNCTION_IMMEDIATE_CHANCE": 25, + "RUN_DIST_NO_AMMO": 25, + "RUN_DIST_NO_AMMO_SQRT": 625, + "SHOOT_FROM_COVER": 4, + "SUPPRESS_BY_SHOOT_TIME": 6, + "SUPPRESS_TRIGGERS_DOWN": 3, + "VALIDATE_MALFUNCTION_CHANCE": 0, + "WAIT_NEXT_SINGLE_SHOT": 0.2, + "WAIT_NEXT_SINGLE_SHOT_LONG_MAX": 3.3, + "WAIT_NEXT_SINGLE_SHOT_LONG_MIN": 0.4, + "WAIT_NEXT_STATIONARY_GRENADE": 1 + } } + }, + "experience": { + "level": { + "max": 0, + "min": 0 + }, + "reward": { + "max": 0, + "min": 0 + }, + "standingForKill": 0 + }, + "firstName": [], + "generation": { + "items": { + "backpackLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 0 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "drugs": { + "weights": { + "0": 1, + "1": 2, + "2": 0 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "grenades": { + "weights": { + "0": 1, + "1": 2, + "2": 1, + "3": 1, + "4": 0, + "5": 0 + }, + "whitelist": [] + }, + "healing": { + "weights": { + "0": 1, + "1": 2, + "2": 1 + }, + "whitelist": [] + }, + "magazines": { + "weights": { + "0": 0, + "1": 0, + "2": 1, + "3": 3, + "4": 1 + }, + "whitelist": [] + }, + "pocketLoot": { + "weights": { + "0": 1, + "1": 6, + "2": 3, + "3": 1, + "4": 1 + }, + "whitelist": [] + }, + "specialItems": { + "weights": { + "0": 1, + "1": 0 + }, + "whitelist": [] + }, + "stims": { + "weights": { + "0": 2, + "1": 1, + "2": 0 + }, + "whitelist": [] + }, + "vestLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 0, + "5": 0, + "6": 0 + }, + "whitelist": [] + } + } + }, + "health": { + "BodyParts": [ + { + "Chest": { + "max": 180, + "min": 180 + }, + "Head": { + "max": 41, + "min": 41 + }, + "LeftArm": { + "max": 115, + "min": 115 + }, + "LeftLeg": { + "max": 115, + "min": 115 + }, + "RightArm": { + "max": 115, + "min": 115 + }, + "RightLeg": { + "max": 115, + "min": 115 + }, + "Stomach": { + "max": 125, + "min": 125 + } + } + ], + "Energy": { + "max": 100, + "min": 100 + }, + "Hydration": { + "max": 100, + "min": 100 + }, + "Temperature": { + "max": 40, + "min": 36 + } + }, + "inventory": { + "equipment": { + "ArmBand": [], + "ArmorVest": [], + "Backpack": [], + "Earpiece": [], + "Eyewear": [], + "FaceCover": [], + "FirstPrimaryWeapon": [], + "Headwear": [], + "Holster": [], + "Pockets": [], + "Scabbard": [], + "SecondPrimaryWeapon": [], + "SecuredContainer": [], + "TacticalVest": [] + }, + "items": { + "Backpack": [], + "Pockets": [], + "SecuredContainer": [], + "SpecialLoot": [], + "TacticalVest": [] + }, + "mods": {} + }, + "lastName": [], + "skills": { + "Common": {} + } } diff --git a/project/assets/database/bots/types/followerkojaniy.json b/project/assets/database/bots/types/followerkojaniy.json index 4100dc55..546233e4 100644 --- a/project/assets/database/bots/types/followerkojaniy.json +++ b/project/assets/database/bots/types/followerkojaniy.json @@ -2099,6 +2099,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2107,6 +2123,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerkolontayassault.json b/project/assets/database/bots/types/followerkolontayassault.json index f9e57771..b3d701a8 100644 --- a/project/assets/database/bots/types/followerkolontayassault.json +++ b/project/assets/database/bots/types/followerkolontayassault.json @@ -2232,6 +2232,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2240,6 +2256,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followerkolontaysecurity.json b/project/assets/database/bots/types/followerkolontaysecurity.json index 5eeecb7e..857c01b6 100644 --- a/project/assets/database/bots/types/followerkolontaysecurity.json +++ b/project/assets/database/bots/types/followerkolontaysecurity.json @@ -2245,6 +2245,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2253,6 +2269,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/followersanitar.json b/project/assets/database/bots/types/followersanitar.json index 25e684f6..70cb85ee 100644 --- a/project/assets/database/bots/types/followersanitar.json +++ b/project/assets/database/bots/types/followersanitar.json @@ -2136,6 +2136,14 @@ "7": 0 }, "whitelist": [] + }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] }, "drugs": { "weights": { @@ -2144,6 +2152,22 @@ "2": 0 }, "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] }, "grenades": { "weights": { diff --git a/project/assets/database/bots/types/followerzryachiy.json b/project/assets/database/bots/types/followerzryachiy.json index 89c58121..5e2ac036 100644 --- a/project/assets/database/bots/types/followerzryachiy.json +++ b/project/assets/database/bots/types/followerzryachiy.json @@ -2003,6 +2003,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2011,6 +2027,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/gifter.json b/project/assets/database/bots/types/gifter.json index 44f245c1..c78a7308 100644 --- a/project/assets/database/bots/types/gifter.json +++ b/project/assets/database/bots/types/gifter.json @@ -2064,6 +2064,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2072,6 +2088,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/marksman.json b/project/assets/database/bots/types/marksman.json index 95e95344..4caadcdd 100644 --- a/project/assets/database/bots/types/marksman.json +++ b/project/assets/database/bots/types/marksman.json @@ -2298,6 +2298,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2306,6 +2322,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, @@ -2337,10 +2361,10 @@ }, "pocketLoot": { "weights": { - "0": 3, - "1": 10, + "0": 10, + "1": 35, "2": 3, - "3": 1, + "3": 2, "4": 1 }, "whitelist": [] diff --git a/project/assets/database/bots/types/peacefullzryachiyevent.json b/project/assets/database/bots/types/peacefullzryachiyevent.json index ce87db85..91ec8f7d 100644 --- a/project/assets/database/bots/types/peacefullzryachiyevent.json +++ b/project/assets/database/bots/types/peacefullzryachiyevent.json @@ -2004,33 +2004,116 @@ ], "generation": { "items": { + "backpackLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 1, + "5": 1, + "6": 1, + "7": 0 + }, + "whitelist": [] + }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { - "max": 1, - "min": 0 + "weights": { + "0": 1, + "1": 2, + "2": 0 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] }, "grenades": { - "max": 5, - "min": 0 + "weights": { + "0": 1, + "1": 2, + "2": 1, + "3": 1, + "4": 0, + "5": 0 + }, + "whitelist": [] }, "healing": { - "max": 2, - "min": 1 - }, - "looseLoot": { - "max": 3, - "min": 0 + "weights": { + "0": 1, + "1": 2, + "2": 1 + }, + "whitelist": [] }, "magazines": { - "max": 4, - "min": 2 + "weights": { + "0": 0, + "1": 0, + "2": 1, + "3": 3, + "4": 1 + }, + "whitelist": [] + }, + "pocketLoot": { + "weights": { + "0": 1, + "1": 6, + "2": 3, + "3": 1, + "4": 1 + }, + "whitelist": [] }, "specialItems": { - "max": 0, - "min": 0 + "weights": { + "0": 1, + "1": 0 + }, + "whitelist": [] }, "stims": { - "max": 1, - "min": 0 + "weights": { + "0": 2, + "1": 1, + "2": 0 + }, + "whitelist": [] + }, + "vestLoot": { + "weights": { + "0": 1, + "1": 1, + "2": 2, + "3": 1, + "4": 0, + "5": 0, + "6": 0 + }, + "whitelist": [] } } }, diff --git a/project/assets/database/bots/types/pmcbot.json b/project/assets/database/bots/types/pmcbot.json index c3f83657..6585f2a2 100644 --- a/project/assets/database/bots/types/pmcbot.json +++ b/project/assets/database/bots/types/pmcbot.json @@ -2119,6 +2119,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2127,6 +2143,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/ravangezryachiyevent.json b/project/assets/database/bots/types/ravangezryachiyevent.json index 30c8c85f..caefb594 100644 --- a/project/assets/database/bots/types/ravangezryachiyevent.json +++ b/project/assets/database/bots/types/ravangezryachiyevent.json @@ -2085,6 +2085,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2093,6 +2109,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/sectantpriest.json b/project/assets/database/bots/types/sectantpriest.json index f89ec5cb..6f22145a 100644 --- a/project/assets/database/bots/types/sectantpriest.json +++ b/project/assets/database/bots/types/sectantpriest.json @@ -2101,6 +2101,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2109,6 +2125,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/sectantwarrior.json b/project/assets/database/bots/types/sectantwarrior.json index ea59e008..255980e5 100644 --- a/project/assets/database/bots/types/sectantwarrior.json +++ b/project/assets/database/bots/types/sectantwarrior.json @@ -2112,6 +2112,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2120,6 +2136,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/shooterbtr.json b/project/assets/database/bots/types/shooterbtr.json index dcf0f809..57d18eeb 100644 --- a/project/assets/database/bots/types/shooterbtr.json +++ b/project/assets/database/bots/types/shooterbtr.json @@ -2146,6 +2146,22 @@ }, "whitelist": [] }, + "currency": { + "weights": { + "0": 20, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2154,6 +2170,14 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { "0": 1, diff --git a/project/assets/database/bots/types/test.json b/project/assets/database/bots/types/test.json index e065fa11..a6756872 100644 --- a/project/assets/database/bots/types/test.json +++ b/project/assets/database/bots/types/test.json @@ -1938,6 +1938,22 @@ "drugs": { "max": 1, "min": 0 + }, + "drink": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, + "food": { + "weights": { + "0": 10, + "1": 5, + "2": 2 + }, + "whitelist": [] }, "grenades": { "max": 5, diff --git a/project/assets/database/bots/types/usec.json b/project/assets/database/bots/types/usec.json index f896fc54..5c58bd78 100644 --- a/project/assets/database/bots/types/usec.json +++ b/project/assets/database/bots/types/usec.json @@ -38,10 +38,10 @@ }, "head": { "5cde96047d6c8b20b577f016": 1, + "5fdb4139e4ed5b5ea251e4ed": 1, + "5fdb5950f5264a66150d1c6e": 1, "60a6aa8fd559ae040d0d951f": 1, "619f9e338858a474c8685cc9": 1, - "5fdb5950f5264a66150d1c6e": 1, - "5fdb4139e4ed5b5ea251e4ed": 1, "62aca6a1310e67685a2fc2e7": 1, "6574aabee0423b9ebe0c79cf": 1 }, @@ -76,6 +76,7 @@ "mod_equipment_000": 25, "mod_equipment_001": 25, "mod_equipment_002": 25, + "mod_mount": 20, "mod_nvg": 40, "right_side_plate": 75 }, @@ -2185,7 +2186,7 @@ "Basuro", "Bepis", "Baliston", - "Pessin", + "Crow", "Aki-chan", "Fin", "Gatsu66", @@ -2321,7 +2322,7 @@ "SlejmUr", "bandit", "Junko Space Mommy", - "civiciam", + "MoxoPixel", "FlashMode", "Pettan", "Oraceon", @@ -2478,9 +2479,20 @@ "Brin", "Belette", "Agnotology", - "All_Heil_Lord_Ppepe", - "ixcetotis", - "btdc00" + "All_Heil_Lord_Pepe", + "ixcetotis", + "btdc00", + "Bnuy", + "Choccy", + "LunnayaLuna", + "Tyfon", + "weewoo", + "Mattdokn", + "BlackDeathGER", + "Gizzy", + "LuckyCharmT", + "Rena-chan", + "HB" ], "generation": { "items": { @@ -2492,12 +2504,28 @@ "15": 4, "20": 3, "23": 1, - "3": 2, - "5": 5, + "3": 5, + "4": 7, + "5": 6, "8": 6 }, "whitelist": [] }, + "currency": { + "weights": { + "0": 5, + "1": 1 + }, + "whitelist": [] + }, + "drink": { + "weights": { + "0": 5, + "1": 5, + "2": 1 + }, + "whitelist": [] + }, "drugs": { "weights": { "0": 1, @@ -2506,10 +2534,18 @@ }, "whitelist": [] }, + "food": { + "weights": { + "0": 5, + "1": 5, + "2": 2 + }, + "whitelist": [] + }, "grenades": { "weights": { - "0": 1, - "1": 4, + "0": 2, + "1": 6, "2": 5, "3": 2, "4": 1 @@ -2555,7 +2591,7 @@ }, "stims": { "weights": { - "0": 1, + "0": 2, "1": 2, "2": 1 }, @@ -2564,7 +2600,7 @@ "vestLoot": { "weights": { "0": 1, - "1": 2, + "1": 3, "2": 3, "3": 2, "4": 1 @@ -2985,9 +3021,9 @@ "5ac66d9b5acfc4001633997a": 5, "5ae08f0a5acfc408fb1398a1": 4, "5b0bbe4e5acfc40dc528a72d": 4, - "5ba26383d4351e00334c93d9": 5, + "5ba26383d4351e00334c93d9": 4, "5bb2475ed4351e00853264e3": 4, - "5bd70322209c4d00d7167b8f": 5, + "5bd70322209c4d00d7167b8f": 4, "5beed0f50db834001c062b12": 3, "5bf3e03b0db834001d2c4a9c": 5, "5bf3e0490db83400196199af": 5, @@ -3226,7 +3262,6 @@ "58820d1224597753c90aeb13": 1, "5887431f2459777e1612938f": 1, "58dd3ad986f77403051cba8f": 1, - "590c657e86f77412b013051d": 1, "59e0d99486f7744a32234762": 1, "59e4cf5286f7741778269d8a": 1, "59e4d24686f7741776641ac7": 1, @@ -3237,11 +3272,6 @@ "59e690b686f7746c9f75e848": 1, "59e6920f86f77411d82aa167": 1, "59e77a2386f7742ee578960a": 1, - "5a0ec6d286f7742c0b518fb5": 1, - "5a13eebd86f7746fd639aa93": 1, - "5a13ef7e86f7741290491063": 1, - "5a13f24186f77410e57c5626": 1, - "5a1452ee86f7746f33111763": 1, "5a38ebd9c4a282000d722a5b": 1, "5a3c16fe86f77452b62de32a": 1, "5a6086ea4f39f99cd479502f": 1, @@ -3278,7 +3308,6 @@ "5d6e6a42a4b9364f07165f52": 1, "5d6e6a53a4b9361bd473feec": 1, "5d6e6a5fa4b93614ec501745": 1, - "5d8e15b686f774445103b190": 1, "5e023d34e8a400319a28ed44": 1, "5e023d48186a883be655e551": 1, "5e023e53d4353e3302577c4c": 1, diff --git a/project/assets/database/locales/server/ar.json b/project/assets/database/locales/server/ar.json index e2ebc1a5..26972f8c 100644 --- a/project/assets/database/locales/server/ar.json +++ b/project/assets/database/locales/server/ar.json @@ -40,6 +40,7 @@ "bot-unable_to_find_spawn_limits_fallback_to_defaults": "تعذر العثور على حدود الظهور للدور: %s، يتم الرجوع إلى القيم الافتراضية\n\n\n\n\n\n\n", "bot-unable_to_get_bot_difficulty_fallback_to_assault": "تعذر العثور على البوت: {{botType}} صعوبة {{difficulty}}، يتم استخدام صعوبة الهجوم كبديل\n\n\n\n\n\n\n", "bot-unable_to_get_bot_fallback_to_assault": "تعذر العثور على روبوت: %s JSON، يتم استخدام بوت الهجوم كبديل\n\n\n\n\n\n\n", + "bot-weapon_contains_invalid_item": "مرفق السلاح المطلوبة: '{{modSlot}}' على سلاح: {{weaponTpl}} لديه عنصر غير صالح: {{modName}}", "bot-weapon_generated_incorrect_using_default": "تم إنشاء السلاح %s بشكل غير صحيح، يتم الرجوع إلى إعداد السلاح، انظر الخطأ أعلاه.\n\n\n\n\n\n\n", "bot-weapon_missing_magazine_or_chamber": "السلاح بالنمط: {{weaponId}} لا يحتوي على مخزن أو حجرة - {{botRole}}\n\n\n\n\n\n\n", "bot-weapon_missing_mod_slot": "الفتحة: {{modSlot}} لا توجد للسلاح: {{weaponId}} {{weaponName}} على {{botRole}}\n\n\n\n\n\n\n", @@ -51,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "تعذر العثور على الروبوت في الذاكرة التخزين المؤقتة بالاسم: %s\n\n\n\n\n\n\n", "bot-missing_application_context": "لا يمكن لـ applicationContext العثور على قيمة %s. هل قمت بإعادة تشغيل الخادم دون إعادة تشغيل اللعبة؟\n\n\n\n\n\n\n", "client_request": "[طلب السيرفر] %s\n\n\n\n\n\n\n", + "client_request_ip": "[طلب الجهاز] {{ip}} {{url}}", "customisation-item_already_purchased": "تم شراء العنصر الخاص بالملابس {{itemId}} {{itemName}} بالفعل.\n\n\n\n\n\n\n", "customisation-unable_to_find_suit_by_id": "تعذر العثور على عرض لبيع ملابس التاجر بالرقم: %s\n\n\n\n\n\n\n", "customisation-unable_to_find_clothing_item_in_inventory": "لم يتم العثور على عنصر الملابس في المخزون بالرقم: %s\n\n\n\n\n\n\n", @@ -112,6 +114,9 @@ "location-spawn_point_count_requested_vs_found": "{{requested}} تم طلب مناطق الانتشار بينما {{found}} متوفرة {{mapName}}", "location-unable_to_reparent_item": "فشل إنشاء العنصر() ، غير قادر على إعادة الربط مع الاصل {{tpl}}، معرف الاصل: {{parentId}}", "location-unable_to_find_airdrop_drop_config_of_type": "غير قادر على العثور على إعدادات ضبط إسقاط الطائرة للنوع: %s، العودة إلى نوع الإسقاط: مختلط ", + "location-unable_to_fix_broken_waves_missing_base": "%s هو json أساسي مفقود، نحن نتجنب إصلاح إصلاح موجة الخريطة إصلاحات", + "location-missing_dynamic_template": "لا تحتوي نقطة التكاثر الديناميكية المختارة %s على قالب، تخطي", + "location-spawnpoint_missing_items": "نقطة التكاثر الديناميكية المختارة %s لا تحتوي على عناصر، تخطي", "loot-item_missing_parentid": "العنصر: %s يفتقد قيمة parentId، لا يمكن استخدام العنصر كغنيمة.\n\n\n\n\n\n\n", "loot-non_item_picked_as_sealed_weapon_crate_reward": "سلاح غير صالح: %s، تم اختياره كمكافأة لصندوق السلاح المختوم، تعذر إنشاء الغنيمة.\n\n\n\n\n\n\n", "mailsend-missing_trader": "تعذر إرسال رسالة من النوع: {{messageType}} إلى اللاعب: {{sessionId}}، نظرًا لأن التاجر المحدد كان فارغًا.\n\n\n\n\n\n\n", @@ -160,16 +165,27 @@ "player-attempt_to_increment_skill_with_negative_value": "غير قادر على زيادة المهارة: %s بمقدار سلبي", "port_already_in_use": "المنفذ %s قيد الاستخدام مسبقا، تحقق مما إذا كان الخادم قيد التشغيل بالفعل", "profile_saved": "تم حفظ تغييرات الملف الشخصي %s", + "profile_save_callback_error": "خطأ أثناء تنفيذ: onBeforeSaveCallback: {{callback}}, {{error}}", "profile-unable_to_find_profile_by_id_cannot_delete": "غير قادر على حذف الملف الشخصي بالمعرف: %s، لا يوجد ملف تعريف له", + "quest-compare_operator_unhandled": "لم يتم التعامل مع عامل التشغيل %s بشكل افتراضي [loyaltyRequirementCheck()]", + "quest-item_not_found_in_inventory": "العنصر الذي يحتوي على %s غير موجود في المخزون [changeItemStack()]", "quest-no_skill_found": "لم يتم العثور على المهارة %s", "quest-handover_wrong_item": "غير قادر على تسليم العنصر للمهمة {{questId}}، التسليم المتوقع: {{requiredTpl}} ولكن تم تسليمه: {{handedInTpl}}", "quest-reward_type_not_handled": "نوع مكافأة المهمة: {{rewardType}} لم يتم التعامل معه من أجل المهمة: {{questId}} بالاسم: {{questName}}", "quest-unable_to_find_compare_condition": "طريقة مقارنة غير معروفة: %s", + "quest-unable_to_find_matching_hideout_production": "غير قادر على العثور على مخطط مطابق للمهمة: {{questName}}، تم العثور على عدد: {{matchCount}}", "ragfair-invalid_player_offer_request": "غير قادر على تقديم العرض، الطلب غير صالح", "ragfair-missing_barter_scheme": "فشلت محاولة توليد عرض للتجار في السوق السوداء في العثور على مخطط مقايضة لمعرف العنصر: {{itemId}} tpl: {{tpl}} على {{name}}", + "ragfair-no_trader_assorts_cant_generate_flea_offers": "غير قادر على إنشاء عروض مزاد للتاجر %s، لم يتم العثور على تشكيلة", + "ragfair-offer_not_found_in_profile": "لم نتمكن من العثور على عرض بمعرف: {{offerId}} في الملف الشخصي لإزالته", "ragfair-offer_not_found_in_profile_short": "العرض غير موجود في الملف الشخصي", + "ragfair-offer_not_found_unable_to_hide": "معرف العرض: %s غير موجود، غير قادر على إخفاء العرض", "ragfair-unable_to_find_item_in_inventory": "غير قادر على العثور على العنصر بالمعرف: {{id}} في المخزون", + "ragfair-unable_to_find_offer_to_remove": "لم نتمكن من العثور على العرض وإزالته بالمعرف: %s", + "ragfair-unable_to_find_requested_items_in_inventory": "يتعذر علينا العثور على أي عناصر مطلوبة في المخزون", + "ragfair-unable_to_pay_commission_fee": "غير قادر على دفع رسوم العمولة:%s روبل", "ragfair-offer_no_longer_exists": "العرض لم يعد متوفرًا", + "ragfair-unable_to_purchase_0_count_item": "يتعذر علينا شراء العنصر: %s بعدد 0", "ragfair-unable_to_place_offer_with_no_requirements": "غير قادر على وضع عرض دون متطلبات", "ragfair-unable_to_find_locale_by_key": "تعذر العثور على لغة EFT بالمفتاح: %s", "route_onupdate_no_response": "عند التحديث: الطريق %s لا يبلغ عن النجاح أو الفشل", @@ -191,6 +207,8 @@ "server_start_meme_10": "جاري تشغيل عملية التعدين على هذه الحاسبة... وداعاً كارت الشاشة", "server_start_meme_12": "نحن نحاول الوصول إليك حول ضمان سيارتك الموسع", "server_start_meme_13": "ඞ ... مريب", + "server_start_meme_22": "تحسّن", + "server_start_meme_23": "SPT يحافظ على سلامة عذريتك منذ عام 2018", "server_start_success": "نتمنى لك لعباً سعيداً", "server_start_player_active_botreload_skill": "شخصيتك لديها مهارة 'BotReload' نشطة، سيؤدي هذا إلى إعادة تلقيم الأسلحة بسرعة غير طبيعية، تجاهل هذه الرسالة إن كانت مقصودة", "started_webserver_success": "بدأ خادم الويب في %s", @@ -231,5 +249,36 @@ "pmcresponse-victim_positive_19": "معركة جيدة", "pmcresponse-victim_positive_20": "أنت لاعب تصعب هزيمته", "pmcresponse-victim_positive_21": "عمل رائع، كانت هذه غدرة جميلة", - "pmcresponse-victim_positive_22": "كان يجب أن أكون أكثر حذراً، عمل جيد" + "pmcresponse-victim_positive_22": "كان يجب أن أكون أكثر حذراً، عمل جيد", + "pmcresponse-victim_positive_23": "لقد كنت متسرعًا للغاية، كان يجب أن أحيط وانتظر", + "pmcresponse-victim_positive_24": "سأتعلم من هذا، أحسنت", + "pmcresponse-victim_positive_25": "اللعنة، ظننت أنني أصبتك", + "pmcresponse-victim_positive_26": "كفو", + "pmcresponse-victim_positive_27": "كفو يالذيب", + "pmcresponse-victim_negative_6": "بكم الهاك؟", + "pmcresponse-victim_negative_7": ":(", + "pmcresponse-victim_negative_10": "كنت بعيد عن الكمبيوتر!!", + "pmcresponse-victim_negative_11": "بلغت عليك يا غشاش", + "pmcresponse-victim_negative_12": "بس جبتني عشان اللاق", + "pmcresponse-victim_negative_13": "لازم العب SPT عشان ابعد نفسي من غشاشين زيك", + "pmcresponse-victim_negative_14": "لو كنت أعرف الخريطة بشكل أفضل لكنت فزت", + "pmcresponse-victim_negative_15": "كامبر حيوان ثاني", + "pmcresponse-victim_negative_16": "لو كانت معركة عادلة كنت سأفوز", + "pmcresponse-victim_negative_17": "أتمنى أن تبيع أرباحك للتاجر الخطأ", + "pmcresponse-victim_negative_18": "آمل أن تسجل أرباحك في المزاد بسعر خاطئ", + "pmcresponse-victim_negative_19": "1 مقابل 1، يا مهووس سأفوز", + "pmcresponse-victim_negative_20": "تعطل مسدسي وإلا كنت قتلتك", + "pmcresponse-victim_negative_21": "يا فار", + "pmcresponse-victim_negative_22": "أنت تختبئ في الزاوية مثل الفار", + "pmcresponse-victim_negative_23": "أتمنى أن ترتطم إصبع قدمك بقطعة أثاث", + "pmcresponse-victim_negative_24": "لماذا قتلتني، سأخبر أمي", + "pmcresponse-victim_negative_25": "سأخبر الآدمن عليك", + "launcher-profile_standard": "مساوية لحجم صندوق التخزين الأساسي (10x28) و 500,000 روبل", + "launcher-profile_leftbehind": "نفس الأساسي زائد: حجم صندوق التخزين (10x38) , معدات / بنود إضافية و 500 دولار", + "launcher-profile_preparetoescape": "نفس \"لفت بيهايند\" زائد: حجم صندوق التخزين (10x48) , معدات / بنود إضافية , سمعة بداية أعلى مع التجار و 250 يورو", + "launcher-profile-edgeofdarkness": "نفس \"بريبير تو اسكيب\" زائد: حجم صندوق التخزين (10x68) , معدات / بنود إضافية , سمعة بداية أعلى مع التجار , 1000 دولار و 250 يورو", + "launcher-profile_spteasystart": "كثير من الروبل / دولار/ يورو , بعض مهارات اللاعب بالمستوى 20 , الحد الأقصى لسمعة التجار , مستوى اللاعب يبدأ من 15 و المهام غير مكتملة", + "launcher-profile_sptzerotohero": "ابدأ بدون شيء تقريبا، لا يوجد روبل / دولار/ يورو، بدون سمعة تجار ، سكين واحد و المهام غير مكتملة", + "launcher-profile_sptdeveloper": "ملف اللاعب مبرمج , مستوى اللاعب يبدأ من 69 , كثير من الروبل / دولار/ يورو , تبدأ USEC مع جميع المهام الجاهزة للبدء , BEAR يبدأ مع جميع المهام الجاهزة للتسليم و بالاكلافا ضد الاضرار", + "launcher-missing_property": "ملف اللاعب: %s ناقص خاصية الوصف \"descriptionLocaleKey\"" } diff --git a/project/assets/database/locales/server/cs.json b/project/assets/database/locales/server/cs.json index 2f2a2187..a192bb39 100644 --- a/project/assets/database/locales/server/cs.json +++ b/project/assets/database/locales/server/cs.json @@ -40,6 +40,7 @@ "bot-unable_to_find_spawn_limits_fallback_to_defaults": "Nelze najít spawn limity pro role: %s, návrat zpět do výchozích hodnot", "bot-unable_to_get_bot_difficulty_fallback_to_assault": "Nelze najít bota: {{botType}} s obtížností {{difficulty}}, použití útočné obtížnosti jako záložní", "bot-unable_to_get_bot_fallback_to_assault": "Nelze najít bota: %s JSON, používá útočný bota jako záložní", + "bot-weapon_contains_invalid_item": "Požadovaný slot: '{{modSlot}}' na zbrani: {{weaponTpl}} má neplatný předmět: {{modName}}", "bot-weapon_generated_incorrect_using_default": "Zbraň %s byla generována nesprávně, návrát k původní předvolbě zbraně, viz chyba výše", "bot-weapon_missing_magazine_or_chamber": "Zbraň s tpl: {{weaponId}} nemá žádný zásobník nebo komoru - {{botRole}}", "bot-weapon_missing_mod_slot": "Slot: {{modSlot}}' neexistuje pro zbraň: {{weaponId}} {{weaponName}} na {{botRole}}", @@ -51,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "Nelze najít bota v mezipaměti s názvem: %s", "bot-missing_application_context": "applicationContext nemohl najít hodnotu %s. Restartovali jste server bez restartování hry?", "client_request": "[Žádost klienta] %s", + "client_request_ip": "[Žádost klienta] {{ip}} {{url}}", "customisation-item_already_purchased": "Položka oblečení {{itemId}} {{itemName}} již byla zakoupena", "customisation-unable_to_find_suit_by_id": "Nelze najít obchodníka vyhovojující nabídce s id: %s", "customisation-unable_to_find_clothing_item_in_inventory": "Položka oblečení nebyla nalezena v inventáři s id: %s", @@ -197,7 +199,6 @@ "repeatable-difficulty_was_nan": "Generace opakovatelných odměn: Obtížnost nebyla číslo. Nastaveno na 1.", "repeatable-no_reward_item_found_in_price_range": "Opakovatelné generování odměn: V cenovém rozmezí {{minPrice}} až {{roublesBudget}} nebyl nalezen žádný předmět", "repeatable-quest_handover_failed_condition_already_satisfied": "Chyba předání úkolu: podmínka je již splněna? qid: {{questId}}, podmínka: {{conditionId}}, profileCounter:{{profileCounter}}, hodnota:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Chyba předání úkolu: podmínka nebyla nalezena nebo nesprávná hodnota. qid: {{body.qid}, podmínka: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Nelze přijmout úkol, podívejte se na server log pro podrobnosti", "repeatable-unable_to_accept_quest_starting_message_not_found": "Nepodařilo se přijmout úkol: {{questId}} nepodařilo se najít počteční zprávu s Id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s trasa nehlásí úspěch nebo neúspěch", @@ -259,6 +260,7 @@ "websocket-pinging_player": "[WS] Vyzvánění hráče: %s", "websocket-player_connected": "[WS] Hráč: %s se připojil", "websocket-received_message": "[WS] Obdržená zpráva od uživatele %s ", + "websocket-socket_lost_deleting_handle": "[WS] Socket ztracen, mažu handle", "websocket-started": "Spuštěn websocket na %s", "pmcresponse-victim_positive_1": "Dobrá trefa", "pmcresponse-victim_positive_2": "Skvělá trefa", @@ -428,6 +430,7 @@ "pmcresponse-victim_negative_99": "Tvůj komp je tak špatněj, že máš 20fps na streetech", "pmcresponse-victim_negative_100": "Vsadím se, že sis stáhnul SAIN a pak jsi ho odinstaloval, protože jsi moc umíral", "pmcresponse-victim_negative_101": "Co jsi to, sakra, o mně právě řekl, ty malý Scave? Musím ti říct, že jsem absolvoval nejlepší ročník v USEC a účastnil jsem se mnoha tajných nájezdů na {{playerSide}} straně a mám přes 300 potvrzených zabití. Jsem vycvičený v gorilí válce a jsem nejlepší odstřelovač v celých ozbrojených silách USEC. Nejsi pro mě nic jiného než další cíl. Zlikviduji vás do posledního šroubku s přesností, jakou v tomto nájezdu ještě nikdo neviděl, pamatujte na má DĚSIVÁ slova. Myslíš si, že ti projde, když mi budeš říkat tyhle sračky přes okno zpráv? Přemýšlej znovu, HECKERE. Zatímco spolu mluvíme, kontaktuji svou tajnou síť špionů napříč celním místem a tvou skrýš právě teď sledují, takže se raději připrav na bouři, červe. Na bouři, která zničí tu ubohost, které říkáš život. Jsi sakra mrtvý, Scave. Můžu být kdekoli a kdykoli a můžu tě zabít na víc než sedm set způsobů, a to jen holýma rukama. Nejenže jsem dokonale vycvičený v boji beze zbraně, ale mám přístup k celému arzenálu sboru USEC a použiju ho v plném rozsahu, abych vymazal tvůj ubohý zadek z povrchu mapy, ty malý hovínko. Kdybys jen tušil, jakou nesvatou odplatu na tebe tvé malé \"chytré\" zabití přivolá, možná bys držel jazyk za zuby. Ale nemohl jsi, neudělal jsi to a teď na to doplácíš, ty ZKROCENÝ idiote. Vylévám na tebe vztek a ty se v něm utopíš.", + "pmcresponse-victim_negative_102": "Vsadím se že sis koupil novou edici jen pro větší kapsy", "pmcresponse-victim_plead_1": "Questil jsem", "pmcresponse-victim_plead_2": "Ja chtel jen dodelat quest, proc jsi me zabil", "pmcresponse-victim_plead_3": "Doufam, že jsi šťastnej, nemůžu si ani koupit novej kit", @@ -526,6 +529,7 @@ "pmcresponse-killer_negative_27": "Nejjednodušší loot dneška", "pmcresponse-killer_negative_28": "Neboj, hodil jsem ti věci k tvojí mámě domu", "pmcresponse-killer_negative_29": "Snažil ses vůbec", + "pmcresponse-killer_negative_30": "vsadim se zes vyplaznul dvestepado za novou edici", "pmcresponse-killer_plead_1": "Šel jsem extractnout s předmětem na quest a tys byl v mý cestě", "pmcresponse-killer_plead_2": "Lootil jsem barely a tys byl v mý cestě, sorry", "pmcresponse-killer_plead_3": "Potřebuju PMC killy, veřím, že to budeš chápat", @@ -574,7 +578,6 @@ "pmc-name_prefix_33": "Náčelník", "pmc-name_prefix_34": "Záludný", "pmc-name_prefix_35": "Vážný", - "pmc-name_prefix_36": "Podezřelý", "pmc-name_prefix_37": "Podezřelý", "pmc-name_prefix_38": "Trapný", "pmc-name_prefix_39": "Dank", @@ -592,7 +595,17 @@ "launcher-profile_leftbehind": "Stejné jako Standard plus; větší velikost skrýše (10x38), bonusové vybavení a věci, 500 dolarů", "launcher-profile_preparetoescape": "Stejné jako Left Behind plus; větší velikost skrýše (10x48), extra vybavení/věci, vyšší startovací reputace s obchodníky, 250 Eur", "launcher-profile-edgeofdarkness": "Stejné jako Prepare To Escape plus; větší velikost skrýše (10x68), extra vybavení a věci, vyšší startovací reputace s obchodníky, 1000 dolarů, 500 Eur", + "launcher-profile_spteasystart": "Mnoho Rublů/Dolarů/Eur, několik QoL dovedností na úrovni 20, reputace s obchodníky na max, počáteční úroveň 15, všechny úkoly k dispozici", "launcher-profile_sptzerotohero": "Začněte s téměř ničím, bez Roublů/Dolarů/Eur, bez reputace u obchodníků, 1 nůž, bez vyplněných úkolů", "launcher-profile_sptdeveloper": "Testovací profil, startovací úroveň je 69, spousta Roublů/Dolarů/Eur, USEC začíná se všemi úkoly připravenými k plnění, BEAR začíná se všemi úkoly připravenými k odevzdání, balaklava která umožňuje nesmrtelnost", - "launcher-missing_property": "Profilu: %s chybí vlastnost descriptionLocaleKey" + "launcher-missing_property": "Profilu: %s chybí vlastnost descriptionLocaleKey", + "release-beta-disclaimer": "Stisknutím \"OK\" souhlasíte, že tato verze je pouze pro testování chyb a není nabízena žádná podpora. Není pro běžné hraní. Mody jsou vypnuté a může být průběžně vyžadován nový profil. Všechny chyby nahlaste na Discordu v kanálu hlášení bleeding-edge, nebo v sekci chyb na webové stránce. Pokud nestisknete \"OK\" do specifikovaného času, hra se vypne.", + "release-beta-disclaimer-mods-enabled": "Stisknutím \"OK\" souhlasíte, že tato verze je pouze pro testování chyb a není nabízena žádná podpora. Není pro běžné hraní. Mody jsou zapnuté, NEHLASTE problémy s mody. NEPTEJTE se autorů modifikací na aktualizované mody. Všechny chyby hlaste na Discordu v kanálu hlášení bleeding-edge, nebo v sekci chyb na webové stránce. Pokud nestisknete \"OK\" do specifikovaného času, hra se vypne.", + "release-beta-disclaimer-accept": "Uživatel potvrdil prohlášení k betě", + "release-server-mods-loaded": "Jeden či více server modů jsou přítomny na modovatelné verzi, hlášení nebude platné dokud mody nebudou odebrány.", + "release-server-mods-debug-message": "Server mody načteny", + "release-plugins-loaded": "Jeden či více pluginů jsou přítomny na modovatelné verzi, hlášení nebude platné dokud nebudou odebrány položky z následujícího listu:", + "release-plugins-loaded-debug-message": "Mody klienta načteny", + "release-illegal-plugins-loaded": "Nalezen jeden či více nepovolených pluginů. Mody nejsou v BleedingEdge verzích SPT povoleny, zakázané pluginy:", + "release-illegal-plugins-exception": "Mody bez debug účelu nalezeny. Mody nejsou povoleny v BleedingEdge verzích SPT - prosím odeberte je před hraním!" } diff --git a/project/assets/database/locales/server/da.json b/project/assets/database/locales/server/da.json index 2e89e913..394ce34e 100644 --- a/project/assets/database/locales/server/da.json +++ b/project/assets/database/locales/server/da.json @@ -41,6 +41,8 @@ "bot-unable_to_get_bot_fallback_to_assault": "Kan ikke finde bot: %s JSON, ved hjælp af angreb bot som tilbagefald", "bot-weapon_generated_incorrect_using_default": "Våben %s blev genereret forkert, og faldt tilbage til forudindstillede våben se fejl ovenfor", "bot-weapon_missing_magazine_or_chamber": "Våben med tpl: {{weaponId}} har ingen magasin eller kammer - {{botRole}}", + "bot-unable_to_find_loot_n_value_for_bot": "Kunne ikke lokalisere loot N værdi for bot: %s, udnytter scav n værdi istedet", + "event-unhandled_event": "[UHÅNDTERET EVENT]%s", "executing_startup_callbacks": "Server: udførelse af opstartstilbagekald...", "gameevent-bot_not_found": "addEventGearToScavs() - kan ikke finde bot af typen %s i databasen, spring over", "gameevent-no_gear_data": "Ingen geardata i sæsonhændelser.json config til begivenhed %s", diff --git a/project/assets/database/locales/server/de.json b/project/assets/database/locales/server/de.json index a8109a6e..ab4c5311 100644 --- a/project/assets/database/locales/server/de.json +++ b/project/assets/database/locales/server/de.json @@ -199,7 +199,6 @@ "repeatable-difficulty_was_nan": "Wiederholbar - Belohnungsgenerierung: Schwierigkeitsgrad wurde nicht als Zahl angegeben. Stelle ein auf 1.", "repeatable-no_reward_item_found_in_price_range": "Wiederholbar - Belohnungsgenerierung: Kein Artikel im Preisbereich {{minPrice}} bis {{roublesBudget}} gefunden", "repeatable-quest_handover_failed_condition_already_satisfied": "Quest-Übergabefehler: Bedingung bereits erfüllt? qid: {{questId}}, Bedingung: {{conditionId}}, ProfileCounter:{{profileCounter}}, Wert:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Fehler bei der Übergabe der Quest: Bedingung nicht gefunden oder falscher Wert. qid: {{body.qid}, Bedingung: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Die Quest kann nicht angenommen werden. Weitere Informationen finden Sie im Serverprotokoll", "repeatable-unable_to_accept_quest_starting_message_not_found": "Quest kann nicht angenommen werden: {{questId}}. Nachrichtentext für gestartete Quest mit der ID: {{messageId}} kann nicht gefunden werden", "route_onupdate_no_response": "onUpdate: %s Weg meldet weder Erfolg noch Fehler", @@ -431,6 +430,7 @@ "pmcresponse-victim_negative_99": "Dein Computer ist so schlecht, dass du auf Streets nur 20 FPS bekommst", "pmcresponse-victim_negative_100": "Ich wette, du hast SAIN installiert und musstest es entfernen, weil du ständig zu oft getötet wurdest", "pmcresponse-victim_negative_101": "Was zum Teufel hast du gerade verdammt noch mal über mich gesagt, du kleiner Aasfresser? Ich möchte dich wissen lassen, dass ich im USEC-Corps meinen Abschluss als Klassenbester gemacht habe und an zahlreichen geheimen Razzien beteiligt war die {{playerSide}}s, und ich habe über 300 bestätigte Abschüsse. Ich bin im Guerilla-Krieg ausgebildet und der beste Scharfschütze der gesamten USEC-Streitkräfte. Du bist für mich nichts als nur ein weiteres Ziel. Ich werde dich auslöschen mit einer Präzision, wie man sie noch nie zuvor bei diesem Raid gesehen hat, merk dir meine verdammten Worte. Glaubst du, du schaffst es, mir diesen Scheiß über das Nachrichtenfenster zu sagen? Denk noch einmal darüber nach, HECKER. Während wir reden kontaktiere ich mein geheimes Spionagenetzwerk am Zollstandort und dein Versteck wird gerade aufgespürt, also bereite dich besser auf den Sturm vor, du Made. Der Sturm, der das erbärmliche kleine Ding, das du dein Leben nennst, auslöscht. Du bist VERDAMMT tot, Scav. Ich kann überall und jederzeit sein und ich kann dich auf über siebenhundert Arten töten, und das nur mit meinen bloßen Händen. Ich bin nicht nur umfassend im unbewaffneten Kampf ausgebildet, sondern habe auch Zugriff auf das gesamte Arsenal des USEC-Korps und werde es in vollem Umfang nutzen, um deinen elenden Hintern von der Karte zu wischen, du kleiner Scheißer. Wenn du nur gewusst hättest, welche unheilige Vergeltung dein kleiner \"schlauer\" Kill über dich bringen würde, hättest du vielleicht deinen Mund gehalten. Aber du konntest es nicht, du hast es nicht getan, und jetzt zahlst du den Preis, du verdammter Idiot. Ich werde dich mit meiner Wut sowas von zupissen und du wirst darin ertrinken. Du bist verdammt tot, Scav.", + "pmcresponse-victim_negative_102": "Ich wette, du hast die neue Version nur für die größeren Hosentaschen gekauft", "pmcresponse-victim_plead_1": "Ich hab Missionen gemacht", "pmcresponse-victim_plead_2": "Ich wollte nur eine Quest beenden, warum hast du mich getötet", "pmcresponse-victim_plead_3": "Ich hoffe, du bist froh, dass ich mir nicht einmal ein neues Kit leisten kann", @@ -529,6 +529,7 @@ "pmcresponse-killer_negative_27": "Einfachste Beute von heute", "pmcresponse-killer_negative_28": "Keine Sorge, ich habe deine Ausrüstung im Haus deiner Mutter versteckt", "pmcresponse-killer_negative_29": "Hast du es überhaupt versucht", + "pmcresponse-killer_negative_30": "Ich wette, du hast tatsächlich 250 große für die neue Edition ausgegeben", "pmcresponse-killer_plead_1": "Ich habe versucht, einen Questgegenstand bei mir und du warst mir im Weg", "pmcresponse-killer_plead_2": "Ich habe Fass-Caches geplündert und du warst im Weg, sorry", "pmcresponse-killer_plead_3": "Ich brauche PMC-Kills, du hast sicher Verständnis", @@ -577,7 +578,7 @@ "pmc-name_prefix_33": "Chef", "pmc-name_prefix_34": "Schwieriger", "pmc-name_prefix_35": "Ernster", - "pmc-name_prefix_36": "Der stille", + "pmc-name_prefix_36": "Tragbar", "pmc-name_prefix_37": "Verdächtiger", "pmc-name_prefix_38": "Unangenehm", "pmc-name_prefix_39": "Danke", diff --git a/project/assets/database/locales/server/el.json b/project/assets/database/locales/server/el.json index 2fdbeecc..57549ae6 100644 --- a/project/assets/database/locales/server/el.json +++ b/project/assets/database/locales/server/el.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "Γέννεση Επαναλαμβανόμενης Ανταμοιβής: Βαθμός δυσκολία ήταν NaN. Ορισμός τιμής στο 1.", "repeatable-no_reward_item_found_in_price_range": "Γέννεση Επαναλαμβανόμενης Ανταμοιβής: Δε βρέθηκε κανένα αντικείμενο στο εύρος τιμών {{minPrice}} στο {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Σφάλμα παράδοσης αποστολής: είναι η συνθήκη ήδη ικανοποιημένη; qid: {{questId}}, συνθήκη: {{conditionId}}, profileCounter:{{profileCounter}}, τιμή:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Σφάλμα παράδοσης αποστολής: δε βρέθηκε η συνθήκη ή έχει λανθασμένη τιμή. qid: {{body.qid}, συνθήκη: {{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "Σφάλμα παράδοσης αποστολής: δε βρέθηκε η συνθήκη ή έχει λανθασμένη τιμή. qid: {{body.qid}}, συνθήκη: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Αδύνατη η αποδοχή της αποστολής, δείτε το αρχείο καταγραφής του διακομιστή για λεπτομέρειες", "repeatable-unable_to_accept_quest_starting_message_not_found": "Αδύνατη η αποδοχή της αποστολής: {{questId}} δεν μπορεί να βρεθεί το μήνυμα εκκίνησης της αποτολής με ταυτότητα: {{messageId}}", "route_onupdate_no_response": "onUpdate: Η διαδρομή %s δεν αναφέρει επιτυχία ή αποτυχία", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Ο υπολογιστή σου είναι τόσο μάπα που έχεις 20 fps στο streets", "pmcresponse-victim_negative_100": "Κόβω το κεφάλι μου ότι έχεις βάλει το SAIN και το έβγαλες γιατί ψόφαγες συνέχεια", "pmcresponse-victim_negative_101": "Τί στο διάτανο είπες για μένα ρε πιτσιρικά Scav; Να σ' ενημερώσω ότι αποφοίτησα πρώτος στη τάξη μου από το σώμα των USEC, έχω πάρει μέρος σε αμέτρητες μυστικές εφόδους κατά των {{playerSide}}s, έχοντας περισσότερα από 300 επιβεβαιωμένα θύματα. Είμαι εκπαιδευμένος σε πόλεμο με αντάρτες και είμαι ο πρώτος ελεύθερος σκοπευτής σε όλο το σώμα των δυνάμεων USEC. Δεν είσαι τίποτα άλλο από ένας στόχος για 'μένα. Θα σε σβήσω με ακρίβεια που δεν έχεις ονειρευτεί μέχρι στιγμής, θυμίσου το. Νομίζεις ότι μπορείς να μου τη γλυτώσεις κρυμμένος πίσω από ένα παράθυρο τσατ; Ξανασκέψου το σκουπίδι. Όσο μιλάμε εδώ λεχω ληδη ενημερώσει το μυστικό δίκτυο κατακόπων στην τοποθεσία Customs και τo κρυφό σου απόθεμα εντοπίζεται μόλις, άρα ετοιμάσου για συμφορά, σκουλίκι. Συμφορά που θα σβήσει την αξιοθρήνητη ύπαρξή σου απ'τη ζωή. Είσαι ήδη νεκρός, Scav. Μπορώ να βρίσκομαι παντού και πάντα και να σε καθαρίσω με πάνω από εκατό τρόπους, κι αυτό με τα χέρια μου μόνο. Όχι μόνο έχω εκτεταμένη εκπαίδευση σε μάχη σώμα με σώμα, αλλά κι έχω πρόσβαση σε όλο το οπλοστάσιο των USEC και θα το χρησιμοποιήσω στην πλήρη του έκταση για να σβήσω την αξιολύπητη ύπαρξή σου από το πρόσωπο του χάρτη, κουράδι. Μόνο να 'ξερες τι είδους ανταπόδωση το \"έξυπνο\" σκότωμά σου θα έφερνε πάνω σου, ίσως τότε να δάγκωνες την καταραμένη γλώσσα σου. Αλλά δε μπορούσες, δεν το 'κανες και, τώρα θα πληρώσεις, ΗΛΙΘΙΕ. Θα χέσω οργή πάνω σου και θα πνιγείς. Είσαι ήδη ψόφιος, Scav.", + "pmcresponse-victim_negative_102": "Στοιχηματίζω ότι πήρες τη νέα έκδοση μόνο και μόνο για τις μεγαλύτερες τσέπες", "pmcresponse-victim_plead_1": "Έκανα quests ρε συ", "pmcresponse-victim_plead_2": "Ένα quest ήθελα να τελειώσω, γιατί μ' έφαγες", "pmcresponse-victim_plead_3": "Ελπίζω να 'σαι χαρούμενος, δεν έχω τη δυνατότητα για πάρω άλλο σετ εξοπλισμού τώρα", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "Τα πιο εύκολα λάφυρα της ημέρας", "pmcresponse-killer_negative_28": "Μη μου σκας καθόλου, έκρυψα τον εξοπλισμό σου στο σπίτι της μανούλας σου", "pmcresponse-killer_negative_29": "Προσπάθησες καθόλου", + "pmcresponse-killer_negative_30": "Στοιχηματίζω ότι σίγουρα έδωσες 250 καθαρά για τη νέα έκδοση", + "pmcresponse-killer_negative_31": "Άντε να σε ποντικώσουν", + "pmcresponse-killer_negative_32": "Ποντικοεπίθεση", "pmcresponse-killer_plead_1": "Απλά ήθελα να βγω με ένα αντικείμενο αποστολής και, εσύ βρέθηκες μπροστά μου", "pmcresponse-killer_plead_2": "Σήκωνα μόνο τις κρυψώνες απ' τα βαρέλια και βρέθηκες στον δρόμο μου, συγνώμη", "pmcresponse-killer_plead_3": "Χρειαζόμουν δολοφονίες PMC, είμαι σίγουρος ότι με νιώθεις", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "Αρχηγός", "pmc-name_prefix_34": "Ζόρικος", "pmc-name_prefix_35": "Σοβαρός", - "pmc-name_prefix_36": "Ύποπτος", + "pmc-name_prefix_36": "Φορητή έκδοση", "pmc-name_prefix_37": "Υποπτος", "pmc-name_prefix_38": "Ξινίλα", "pmc-name_prefix_39": "Κρυάδα", diff --git a/project/assets/database/locales/server/en.json b/project/assets/database/locales/server/en.json index bd4c2091..6bf3a97e 100644 --- a/project/assets/database/locales/server/en.json +++ b/project/assets/database/locales/server/en.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "Repeatable Reward Generation: Difficulty was NaN. Setting to 1.", "repeatable-no_reward_item_found_in_price_range": "Repeatable Reward Generation: No item found in price range {{minPrice}} to {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Quest handover error: condition is already satisfied? qid: {{questId}}, condition: {{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Quest handover error: condition not found or incorrect value. qid: {{body.qid}, condition: {{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "Quest handover error: condition not found or incorrect value. qid: {{body.qid}}, condition: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Unable to accept quest, see server log for details", "repeatable-unable_to_accept_quest_starting_message_not_found": "Unable to accept quest: {{questId}} cant find quest started message text with id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s route doesn't report success or fail", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Your computer so bad you get 20fps on streets", "pmcresponse-victim_negative_100": "I bet you installed SAIN and had to remove it cuz you kept getting killed too much", "pmcresponse-victim_negative_101": "What the HECK did you just HECKING say about me, you little Scav? I’ll have you know I graduated top of my class in the USEC corps, and I’ve been involved in numerous secret raids on the {{playerSide}}s, and I have over 300 confirmed kills. I am trained in gorilla warfare and I’m the top sniper in the entire USEC armed forces. You are nothing to me but just another target. I will wipe you the HECK out with precision the likes of which has never been seen before in this raid, mark my HECKING words. You think you can get away with saying that shit to me over the messaging window? Think again, HECKER. As we speak I am contacting my secret network of spies across the Customs location and your stash is being traced right now so you better prepare for the storm, maggot. The storm that wipes out the pathetic little thing you call your life. You’re HECKING dead, Scav. I can be anywhere, anytime, and I can kill you in over seven hundred ways, and that’s just with my bare hands. Not only am I extensively trained in unarmed combat, but I have access to the entire arsenal of the USEC Corps and I will use it to its full extent to wipe your miserable butt off the face of the map, you little poop. If only you could have known what unholy retribution your little “clever” kill was about to bring down upon you, maybe you would have held your HECKING tongue. But you couldn’t, you didn’t, and now you’re paying the price, you HECKING idiot. I will POOP fury all over you and you will drown in it. You’re HECKING dead, Scav.", + "pmcresponse-victim_negative_102": "I bet you bought that new edition just for the bigger pockets", "pmcresponse-victim_plead_1": "I was questing", "pmcresponse-victim_plead_2": "I just wanted to finish a quest, whyd you kill me", "pmcresponse-victim_plead_3": "Hope ur happy i can't even afford a new kit", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "Easiest loot of today", "pmcresponse-killer_negative_28": "Not to worry, i stashed your gear at your moms house", "pmcresponse-killer_negative_29": "Were you even trying", + "pmcresponse-killer_negative_30": "I bet you actually paid 250 big ones for that new edition", + "pmcresponse-killer_negative_31": "Get ratted", + "pmcresponse-killer_negative_32": "Rat attack", "pmcresponse-killer_plead_1": "I was trying to extract a quest item and you were in my path", "pmcresponse-killer_plead_2": "I was looting barrel caches and you were in the way, sorry", "pmcresponse-killer_plead_3": "I need PMC kills, Im sure you understand", diff --git a/project/assets/database/locales/server/es-es.json b/project/assets/database/locales/server/es-es.json index df896af3..421a1863 100644 --- a/project/assets/database/locales/server/es-es.json +++ b/project/assets/database/locales/server/es-es.json @@ -198,7 +198,6 @@ "repeatable-difficulty_was_nan": "Generador de recompensas: La dificultad fue NaN. Utilizando 1.", "repeatable-no_reward_item_found_in_price_range": "Generador de recompensas: No se encontraron items en el rango de {{minPrice}} a {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Error entrega de misión: ¿La condición está satisfecha? qid: {{questId}}, condición: {{conditionId}}, profileCounter:{{profileCounter}}, valor:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Error entrega de misión: Condición no encontrada o valor incorrecto. qid: {{body.qid}, condición: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "No se puede aceptar la misión, revisa los registros del servidor.", "repeatable-unable_to_accept_quest_starting_message_not_found": "No se puede aceptar la misión: {{questId}} no se encuentra el mensaje de inicio de misión: {{messageId}}", "route_onupdate_no_response": "onUpdate: la ruta %s no reportó éxito o fallo", @@ -575,7 +574,6 @@ "pmc-name_prefix_33": "Jefe", "pmc-name_prefix_34": "Tramposo", "pmc-name_prefix_35": "Serio", - "pmc-name_prefix_36": "Engañoso", "pmc-name_prefix_37": "Sospechoso", "pmc-name_prefix_38": "Vergonzoso", "pmc-name_prefix_39": "Conmadre", diff --git a/project/assets/database/locales/server/fr.json b/project/assets/database/locales/server/fr.json index a0bfd780..4daf7806 100644 --- a/project/assets/database/locales/server/fr.json +++ b/project/assets/database/locales/server/fr.json @@ -199,7 +199,6 @@ "repeatable-difficulty_was_nan": "Génération des récompenses : la difficulté est NaN. Remis à 1.", "repeatable-no_reward_item_found_in_price_range": "Génération de Récompenses Répétitives: Aucun objet trouvé dans la fourchette de prix {{minPrice}} à {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Erreur sur item de quête: la condition est déjà remplie? qid: {{questId}}, condition: {{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Erreur sur récompense de quête: condition introuvable ou valeur inconnue. qid: {{body.qid}, condition: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Impossible d'accepter la quête, plus de détail dans le serveur log", "repeatable-unable_to_accept_quest_starting_message_not_found": "Impossible d'acepter la quête: {{questId}} le message de démarrage de quête est introuvable. Son ID id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s route ne reporte pas succès ou échec", @@ -577,7 +576,6 @@ "pmc-name_prefix_33": "Chef", "pmc-name_prefix_34": "Futé", "pmc-name_prefix_35": "Sérieux", - "pmc-name_prefix_36": "Louche", "pmc-name_prefix_37": "Douteux", "pmc-name_prefix_38": "Gênant", "pmc-name_prefix_39": "Humide", diff --git a/project/assets/database/locales/server/hu.json b/project/assets/database/locales/server/hu.json index 77e0fc8e..66660ff2 100644 --- a/project/assets/database/locales/server/hu.json +++ b/project/assets/database/locales/server/hu.json @@ -1,20 +1,20 @@ { "assort-missing_loyalty_level_object": "stripQuestAssort(): Kereskedő {{traderId}} kínálata nem tartalmazza a loyal_level_items adatot, a küldetés kínálatok törlése át lesz ugorva", "assort-missing_questassort": "stripQuestAssort(): Kereskedő %s kínálata nem tartalmaz egy questassort json fájlt, a küldetés kínáltatok törlése át lesz ugorva", - "assort-missing_quest_assort_unlock": "Nem található küldetés kínálat feloldás {{traderName}} kereskedőnél ehhez a küldetéshez: {{questName}}. A küldetés teljesítése nem fog jutalmazni megvásárolható tárgyat a kereskedőnél", - "baseclass-item_not_found": "Tétel %s nem létezik a tárgyak gyorsítótárjában, ezért a gyorsítótár újra lesz csinálva", - "baseclass-item_not_found_failed": "Tétel %s még mindig nem létezik a tárgyak gyorsítótárjába újracsinálása után", - "baseclass-missing_db_no_cache": "Az adatbázis üres volt, nem lehetett a tételek alapvetó gyorsítótárját újracsinálni", + "assort-missing_quest_assort_unlock": "Nem található megfelelő {{traderName}} küldetés választék feloldás a következő küldetéshez: {{questName}}. Ennek a küldetésnek a teljesítése nem fog jutalomként tárgyat biztosítani vásárláshoz", + "baseclass-item_not_found": "Tétel %s nem létezik a tárgyak gyorsítótárjában, ezért a gyorsítótár újra lesz generálva", + "baseclass-item_not_found_failed": "Tétel %s még mindig nem létezik a tárgyak gyorsítótárjában újgenerálás után", + "baseclass-missing_db_no_cache": "Az adatbázis üres volt, nem lehetett a tételek alapvető gyorsítótárját elkészíteni", "bleeding_edge_build": "BLEEDINGEDGE", - "bot-bot-cache_has_zero_bots_of_requested_type": "FIGYELMEZTETÉS - A bot gyorsítótár nem tartalmaz előre elkészített botot ebben a típusban %s, így el kell készíteni. Módosítsad a szerver beállítását, hogy csinálj többet", + "bot-bot-cache_has_zero_bots_of_requested_type": "FIGYELEM - A bot gyorsítótár nem rendelkezik előre generált bottal a következő típusból: %s, generálni kell, állítsd be a szervert több generálásához", "bot-compatibility_check_missing_props": "Érvénytelen tétel: {{id}} {{name}} ezen a helyen {{slot}} fel lehet szerelni, hiányzik egy _props érték", "bot-generation_failed": "bot generálása sikertelen, lásd a szerver naplót további részletekért", "bot-incompatible_ammo_for_weapon_falling_back_to_default": "Összeférhetetlen lőszer {{chosenAmmo}} lett találva ehhez {{weaponId}} - {{weaponName}}, vissza lesz állítva az alapértelmezetthez: {{defaultAmmo}}", "bot-invalid_item_compatibility_check": "Nem lehetett ellenőrizni a tételek összeegyeztethetőségét a felszerelt tételekkel, kívánt tétel: {{itemTpl}} itt: {{slot}} egy érvénytelen tétel", "bot-item_spawn_limit_reached_skipping_item": "{{botRole}} Nem lehetett a {{itemName}} tételt lehelyezni {{attempts}} próbálkozás után, figyelmen kívül lesz hagyva a lehelyezés korlát", "bot-loot_type_not_found": "Zsákmány gyorsítótár sikertelen ehhez a zsákmányhoz: {{lootType}} ezen a boton: {{botRole}}, pmc volt: {{isPmc}}", - "bot-missing_cartridge_slot": "Nem lehetett lőszert adni a fegyverhez mert a modPool nem tartalmaz lőszereket egy tekercselő dobtárhoz %s, át lesz ugorva", - "bot-missing_container_with_tpl": "Nem található tárolósablon a következő tpl-lel: %s", + "bot-missing_cartridge_slot": "Nem lehet töltényeket hozzáadni a fegyverhez, mivel a modPool nem tartalmaz töltényeket a CylinderMagazine %s számára, kihagyás", + "bot-missing_container_with_tpl": "Nem található tárolósablon a következővel tpl: %s", "bot-missing_equipment_settings": "A Botnak {{botRole}} hiányzik a felszerelés beállításai: nem lehetett az értéket megszerezni: {{setting}}, vissza fog esni az alapértelmezettre: {{defaultValue}}", "bot-missing_equipment_settings_property": "A Botnak {{botRole}} hiányzik a felszerelés beállításai: nem lehetett az értéket megszerezni: {{setting}}, vissza fog esni az alapértelmezettre: {{defaultValue}}", "bot-missing_item_template": "Nem lehetett megtalálni az elem sablont tpl-lel: %s", @@ -29,18 +29,118 @@ "bot-no_compatible_camora_ammo_found": "Nem találunk egyeztethető lőszert a résre: %s, Kihagyjuk a camora rés \ntöltését", "bot-no_item_template_found_when_adding_mod": "Nem található a módosítási tárgy sablonja a tpl-el: {{modId}} a résre: {{modSlot}}", "bot-no_spawn_chance_defined_for_equipment_slot": "Hiányzik felszerelés spawn esély meghatárazása: %s", - "bot-single_bot_generation_not_found_in_cache": "Bot: %s hiányzik a gyorsítótárban, terem új, ez okozhat \njátszma lemaradást", - "bot-unable_to_add_mod_item_invalid": "Módosítás: {{itemName}} nem érvényes, Nem adható a réshez: '{{modSlot}}' a \ntárgyon: {{parentItemName}}, kihagyjuk", - "bot-unable_to_add_mods_to_weapon_missing_ammo_slot": "Nem lehet adni módosítást a fegyverhez: {{weaponName}} {{weaponId}} mert hiányzik szabad hej, töltény, vagy vegyverkamra - {{botRole}}", + "bot-single_bot_generation_not_found_in_cache": "Bot: %s nem található a gyorsítótárban, friss generálása, ez a játék akadozását okozhatja", + "bot-unable_to_add_mod_item_invalid": "Mod {{itemName}} nem érvényes tárgy, nem adható hozzá '{{modSlot}}' a következőhöz: {{parentItemName}}, kihagyva", + "bot-unable_to_add_mods_to_weapon_missing_ammo_slot": "Nem lehet módosítást adni a fegyverhez: {{weaponName}} {{weaponId}} mivel nincs szabad hely, töltény, vagy fegyverkamra - {{botRole}}", + "bot-unable_to_filter_mod_slot_all_blacklisted": "Nem lehet dinamikusan szűrt fegyvertartozék-állományt létrehozni, mert a tiltólista kiszűrte az összes tartozékot a következő helyre: %s, lista figyelmen kívül hagyása és az állomány újragenerálása", + "bot-unable_to_filter_mods_all_blacklisted": "Nem lehet szűrni a modokat a következő helyhez: {{slotName}} a {{itemName}}-n, mivel minden elem tiltólistára került, tiltólista figyelmen kívül hagyása", "bot-unable_to_find_ammo_item": "Nem található lőszer sablon a tpl: %s", "bot-unable_to_find_default_magazine_item": "Hiányzik fegyvertár sablon: %s az adatbázisban", "bot-unable_to_find_magazine_item": "Hiányzik fegyvertár sablon: %s az adatbázisban", "bot-unable_to_find_spawn_limits_fallback_to_defaults": "Hiányzik spaw határ a szerepnek: %s, fisszaesik az alap beállítás", - "bot-unable_to_get_bot_difficulty_fallback_to_assault": "Hiányzó Bot typus: {{botType}} nehézség szint {{difficulty}}, Visszaesik Assault nehézségre", + "bot-unable_to_get_bot_difficulty_fallback_to_assault": "Bot nem található: {{botType}} nehézség {{difficulty}}, assault nehézségi szint lesz használva", "bot-unable_to_get_bot_fallback_to_assault": "Hiányzó Bot: %s JSON, Visszaállítas az Assault Bot tipusra", - "customisation-item_already_purchased": "Öltözet {{itemId}} {{itemName}} már megvásárolt", + "bot-weapon_contains_invalid_item": "Szükséges hely: '{{modSlot}}' a fegyveren: {{weaponTpl}}} érvénytelen elemmel rendelkezik: {{modName}}", + "bot-weapon_generated_incorrect_using_default": "A fegyver %s hibásan lett generálva, visszaáll az előre beállított fegyverre. Lásd a fenti hibaüzenetet", + "bot-weapon_missing_magazine_or_chamber": "Fegyver tpl: {{weaponId}} nincs tár vagy kamra - {{botRole}}", + "bot-weapon_missing_mod_slot": "Slot: {{modSlot}}' nem létezik a fegyverhez: {{weaponId}} {{weaponName}} on {{botRole}}", + "bot-weapons_required_slot_missing_item": "A(z) {{modName}} {{slotId}} szükséges '{{modSlot}}' helye üres volt a következőn: {{botRole}}", + "bot-item_missing_props_property": "A tárgy {{itemTpl}} {{name}} elemnek hiányzik a _props tulajdonsága", + "bot-unable_to_fill_camora_slot_mod_pool_empty": "{{weaponId}} - {{weaponName}} számára nem lehet betölteni a fegyverkamra slotokat. A modtár üres volt, dinamikus generálás megpróbálása", + "bot-unable_to_edit_limits_of_unknown_map": "Nem lehet szerkeszteni a következő térkép bot-korlátait: %s, mert nem található", + "bot-unable_to_find_loot_n_value_for_bot": "Nem sikerült megtalálni a loot N értéket a bothoz: %s, helyette scav n érték használva", + "bot-unable_to_find_bot_in_cache": "Nem sikerült megtalálni a botot a gyorsítótárban a következő névvel: %s", + "bot-missing_application_context": "applicationContext nem találta %s értéket. Újraindítottad a szervert a játék újraindítása nélkül?", + "client_request": "[Kliens kérés] %s", + "client_request_ip": "[Kliens kérés] {{ip}} {{url}}", + "customisation-item_already_purchased": "Öltözet {{itemId}} {{itemName}} már megvásárolva", + "customisation-unable_to_find_suit_by_id": "Nem található ajánlat a következő azonosítóval: %s", "customisation-unable_to_find_clothing_item_in_inventory": "Öltözet darab hiányzik a leltárban: %s", + "dialog-missing_item_template": "Nem található a tpl {{tpl}} elem az adatbázisban, nem lehet {{type}} típusú üzenetet küldeni, kihagyva", + "event-unhandled_event": "[KEZELETLEN ESEMÉNY] %s", + "executing_startup_callbacks": "Kiszolgáló: indítási visszahívások végrehajtása...", + "fence-unable_to_find_assort_by_id": "Nem található meg Fence választéka a következő azonosítóhoz: %s", + "fixer-mod_item_found": "Elem: %s megtalálható a profilban, de nem létezik az items db-ben. Hibaüzeneteket fogsz kapni, ez azért lehet, mert egy modolt tárgyat használtál, és eltávolítottad a modot anélkül, hogy törölted volna a készletedből azokat. NE HASZNÁLD EZT A PROFILT. Nyisd meg az Aki_Data\\Server\\configs\\core.json-t, szerkeszd a 'removeModItemsFromProfile' beállítást igaz értékre. Ez lehetővé teszi a szerver számára, hogy módosítsd a profilod és remélhetőleg eltávolítsd a hibás elemeket", + "fixer-updated_pockets": "Frissített 'pocket' tárgy az új, 18876-os verzióra, amely x3 speciális slotot tartalmaz", + "gameevent-bot_not_found": "addEventGearToScavs() - nem találja a %s típusú botot az adatbázisban, kihagyás", + "gameevent-no_gear_data": "A seasonalevents.json konfigban nincsenek felszerelés adatok a következő eseményhez %s", + "hideout-missing_recipe_for_area": "Nem talált receptet: %s a terület típusához", + "hideout-missing_recipe_in_db": "Nem sikerült megtalálni a receptet a következőkkel _id: %s", "hideout-no_bitcoins_to_collect": "Nincs elvitelre kész bitcoin", + "hideout-unable_to_find_area": "Nem sikerült megtalálni a rejtekhelyet: %s a profilban", + "hideout-unable_to_find_area_in_database": "Nem sikerült megtalálni a következő területet: %s az adatbázisban", + "hideout-unable_to_find_item_in_inventory": "Nem sikerült megtalálni a %s azonosítóval rendelkező elemet a készletben", + "hideout-unable_to_find_item_to_remove_from_area": "Nem talál semmilyen objektumot, amelyet el lehetne távolítani a következő területen lévő helyről: %s", + "hideout-unable_to_find_production_in_profile_by_recipie_id": "Nem található a gyártási recept azonosítója %s a profilban", + "hideout-unable_to_find_scav_case_recipie_in_database": "Failed to find Scav Case recipe with id: %s in database", + "hideout-unable_to_find_scavcase_requested_item_in_profile_inventory": "Nem található a ScavCase által kért elem: %s", + "hideout-unhandled_remove_item_from_area_request": "Kezeletlen kísérlet egy tárgy eltávolítására a rejtekhely területéről: %s", + "http-unknown_error": "Ismeretlen hiba történt", + "health-healing_item_not_found": "Nem található meg a gyógyító tárgy %s a játékos készletében", + "health-unable_to_find_item_to_consume": "Nem található meg a fogyasztható tárgy %s a játékos készletében", + "importing_database": "Adatbázis importálása...", + "importing_database_finish": "Az adatbázis importálása befejeződött", + "validation_not_found": "A checks.dat fájl nem található. A fájl érvényesítése kihagyva.", + "validation_error_decode": "Nem sikerült dekódolni a checks.dat fájlt. Fájl hitelesítése kihagyva.", + "validation_error_file": "A következő fájl érvényesítés sikertelen volt %s", + "validation_error_exception": "Kivétel keletkezett a fájl ellenőrzése közben: %s", + "importing_spt_configs": "Konfigurációk importálása...", + "inraid-missing_standing_for_kill": "Hírnév a gyilkossághoz nem található meg {{victimSide}}:{{victimRole}} számára", + "insurance-missing_insurance_price_multiplier": "Nincs biztosítási szorzót a kereskedőhöz: %s, ellenőrizd, hogy létezik-e az InsuranceConfig.js fájlban, most visszaáll az alapértelmezett értékre: 0.3", + "inventory-edit_trader_item": "Nem lehet szerkeszteni egy kereskedő tárgyát", + "inventory-examine_item_does_not_exist": "examineItem() - Nincs találat az %s azonosítóra", + "inventory-fill_container_failed": "fillContainerMapWithItem() hibával tért vissza %s", + "inventory-invalid_item_missing_from_db": "Elem: %s nem kérhető le az adatbázisból", + "inventory-invalid_move_to_container": "Megkísérelt egy tárgyat áthelyezni slot id: {{slotId}} helyről a következő helyre {{container}}, a profil sérülése megelőzésre került", + "inventory-no_stash_space": "Nincs elég hely a tárolóban", + "inventory-unable_to_fill_container": "[OOB] a tételhez: {{id}}; Hibaüzenet: {{error}}", + "inventory-unable_to_find_item": "getExaminedItemTpl() Nem lehet megtalálni a következő elemet tpl: %s adatbázisban vagy a piacon", + "inventory-unable_to_find_stash": "Nincs rejtekhely találva", + "inventory-return_default_size": "A %s elem alapértelmezett 1x1-es méretre állítása", + "inventory-item_missing_props_property": "Tárgy tpl: {{itemTpl}} név: {{itemName}} hiányzik egy props tulajdonság, a méret nem szerezhető meg hozzá", + "inventory-get_item_size_item_not_found_by_tpl": "getSizeByInventoryItemHash() Tárgy tpl: %s nem található", + "inventory-item_to_toggle_missing_upd": "Készlet tárgy, _id: %s, hiányol egy upd elemet, hozzáadás", + "inventory-unable_to_toggle_item_not_found": "A következő azonosítójú készletelemet nem lehet váltani: %s, a tétel nem található", + "inventory-missing_stash_size": "Nem lehet meghatározni a készlet méretét, mivel nincs készlet a játékos leltárában", + "inventory-stash_not_found": "Nem sikerült megtalálni a %s rejtekhelyet a db-ben", + "item-durability_value_invalid_use_default": "getRepairableItemQualityValue() fegyver tpl: %s tartóssági érték érvénytelen, visszaállítás alapértelmezett értékre: 1", + "linux_use_priviledged_port_non_root": "A nem gyökér folyamatok nem tudnak 1024 alatti portokhoz kötődni", + "location-containers_generated_success": "Összesen %s statikus konténer generálva", + "location-critical_error_see_log": "Kritikus hiba történt a zsákmány generálásakor, lásd a szervernaplót a részletekért", + "location-dynamic_items_spawned_success": "Összesen %s dinamikus tárgy létrehozva", + "location-generated_success": "Létrehozott hely %s", + "location-missing_root_item": "createItem() sikertelen, root item is null, tpl: {{tpl}}, parentId: {{parentId}}", + "location-preset_not_found": "előbeállítás nem található a következőhöz: {{tpl}}, defaultPreset: {{defaultId}} name: {{defaultName}}, parentId: {{parentId}}", + "location-spawn_point_count_requested_vs_found": "{{requested}} spawn pont lett kérve, míg {{found}} található {{mapName}}", + "location-unable_to_reparent_item": "createItem() sikertelen, nem lehet újra hozzárendelni {{tpl}}, parentId: {{parentId}}", + "location-unable_to_find_airdrop_drop_config_of_type": "Nem sikerült megtalálni az airdrop konfigurációs beállításait a következő típushoz: %s, visszaállítás a következő típusra: változó ", + "location-unable_to_fix_broken_waves_missing_base": "A %s fájlból hiányzik a base json, a map wave javítások kihagyása", + "location-missing_dynamic_template": "A kiválasztott dinamikus spawn pont %s nem rendelkezik sablonnal, kihagyás", + "location-spawnpoint_missing_items": "A választott dinamikus spawn pont %s nem tartalmaz tárgyakat, kihagyásra kerül", + "loot-item_missing_parentid": "Tárgy: %s nem rendelkezik parentId értékkel, nem lehet zsákmányként használni", + "loot-non_item_picked_as_sealed_weapon_crate_reward": "Érvénytelen fegyver: %s, mint jutalom lett kiválasztva a lezárt fegyverládához, nem lehet zsákmányt létrehozni", + "mailsend-missing_trader": "Nem lehet üzenettípust küldeni: {{messageType}} a játékosnak: {{sessionId}}, a megadott kereskedő enum értéke null volt", + "mailsend-missing_npc_dialog": "Nem sikerült üzenetet küldeni a %s címről. Nem létező párbeszédpanel", + "mailsend-missing_parent": "Nem találok egy elemet slotId-vel: rejtekhely az üzenetnek: {{traderId}} feladó: {{sender}}", + "mod-send_bundle_url": "[CSOMAG]: %s", + "modloader-checked": "ellenőrizve", + "modloader-checking_mod": "ellenőrzés: %s", + "modloader-cyclic_dependency": "Ciklikus függőséget észleltünk. Ezt a hibát javítani kell. A szerver nem tud elindulni amíg ez meg nem történik, és le fog állni", + "modloader-load_order_conflict": "`{{modOneName}}` és`{{modTwoName}}` modoknak ellentmondásos betöltési sorrend követelményei vannak, a szerver nem tud elindulni amíg ezt nem javítják, és leáll", + "modloader-dependency_container_not_initalized": "A dependency container lekérve, de nincs inicializálva", + "modloader-error_parsing_mod_load_order": "Hiba a mod betöltési sorrendjének elemzésekor", + "modloader-incompatibilities_not_string_array": "A Mod %s package.json „incompatibilities” tulajdonságának karakterlánc tömbnek kell lennie", + "modloader-incompatible_mod_found": "{{author}}-{{name}} mod nem kompatibilis a következővel: {{incompatibleModName}}", + "modloader-invalid_akiversion_field": "A mod %s érvénytelen semver karakterláncot tartalmaz az akiVersion mezőben. Példák az érvényes értékekre: https://github.com/npm/node-semver#versions", + "modloader-invalid_version_property": "A(z) %s mod package.json fájlja érvénytelen verziójú karakterláncot tartalmaz", + "modloader-not_correct_mod_folder": "A mods mappában létezik egy (%s) nevű mappa. Helytelenül telepítettél egy modot. Lehet, hogy egy mod tartalmát tévedésből közvetlenül a mod mappába csomagoltad. A modok helyes telepítésével kapcsolatban lásd a webhelyek GYIK-jét és a mod oldalát hogyan kell azt helyesen telepíteni", + "modloader-is_client_mod": "A következő mod (%s) egy kliens mod és a következő mappába kell helyezni: /spt/bepinex/plugins", + "modloader-installing_external_dependencies": "A segédprogramok telepítése a következőhö modhoz: {{name}}, {{author}} által készítve", + "modloader-installing_external_dependencies_disabled": "A(z) {{name}} mod, melyet {{author}} készített, külső függőségeket igényel, de ez a funkció jelenleg ki van kapcsolva. Lépj a(z) \"{{configPath}}\" helyre, állítsd a(z) \"{{configOption}}\" értékét igazra (true), és indítsd újra a szervert.\nEnnek engedélyezésével elfogadod minden felelősséget amiért a(z) {{name}} letölt a gépedre.", + "modloader-skipped_mod": "A következő mod betöltésének kihagyása: {{mod}}", + "modloader-loaded_mod": "Mod: {{name}} verzió: {{version}} by: {{author}} betöltve", + "modloader-loading_mods": "ModLoader: %s szervermodok betöltése...", + "modloader-main_property_not_js": "A mod %s package.json fő tulajdonsága egy .js fájl kell legyen", "modloader-main_property_points_to_nothing": "A %s mod package.json fő tulajdonsága egy nem létező fájlra mutat", "modloader-missing_akiversion_field": "%s modnak hiányzik az akiVersion mezője, valószínűleg azért, mert elavult és nem kompatibilis az AKI jelenlegi verziójával", "modloader-missing_dependency": "{{mod}} mod a következőnek a telepítését igényli {{modDependency}}.", @@ -68,14 +168,37 @@ "profile_save_callback_error": "Hiba az onBeforeSaveCallback végrehajtása közben: {{callback}}, {{error}}", "profile-unable_to_find_profile_by_id_cannot_delete": "Nem sikerült törölni a következő azonosítóval rendelkező profilt: %s, nem találtunk ilyen azonosítóval rendelkező profilt", "quest-compare_operator_unhandled": "loyaltyRequirementCheck() operátor %s nem kezelt, alapértelmezett értékre állítva: hamis", + "quest-item_not_found_in_inventory": "changeItemStack() A _id: %s azonosítóval rendelkező elem nem található a készletben", + "quest-no_skill_found": "%s képesség nem található", + "quest-handover_wrong_item": "Nem sikerült leadni a {{questId}} küldetéshez tartozó tárgyat, elvárt tpl: {{requiredTpl}}, de leadva: {{handedInTpl}}", + "quest-reward_type_not_handled": "A küldetés jutalom típusa: {{rewardType}} nem kezelt küldetés: {{questId}} név: {{questName}}", + "quest-unable_to_find_compare_condition": "Nem felismert összehasonlítási módszer: %s", + "quest-unable_to_find_matching_hideout_production": "Nem találtam megfelelő receptet a rejtekhelyen a küldetéshez: {{questName}}, találatok: {{matchCount}}", + "ragfair-invalid_player_offer_request": "Nem lehet ajánlatot tenni, a kérés érvénytelen", + "ragfair-missing_barter_scheme": "generateFleaOffersForTrader() Nem sikerült megtalálni a barterScheme-t az Item Id: {{itemId}} tpl: {{tpl}} on {{name}}", + "ragfair-no_trader_assorts_cant_generate_flea_offers": "Nem sikerült ajánlatot generálni %s kereskedő számára, nem találtunk választékot", + "ragfair-offer_not_found_in_profile": "Nem található ajánlat azonosítóval: {{offerId}} a profilban az eltávolításhoz", + "ragfair-offer_not_found_in_profile_short": "Ajánlat nem található a profilban", + "ragfair-offer_not_found_unable_to_hide": "hideItem() offerId: %s nem található, nem lehet elrejteni az ajánlatot", + "ragfair-tpl_not_a_valid_item": "generateFleaOffersForTrader() tpl: %s nem érvényes elem, kihagyás", + "ragfair-unable_to_find_item_in_inventory": "Nem sikerült megtalálni a {{id}} azonosítóval rendelkező tárgyat a készletben", + "ragfair-unable_to_find_offer_to_remove": "Nem sikerült megtalálni az eltávolítandó ajánlatot a következő azonosítóval: %s", + "ragfair-unable_to_find_requested_items_in_inventory": "Nem találhatók a kért tárgyak a leltárban", + "ragfair-unable_to_pay_commission_fee": "Nem lehet kifizetni a jutalékot: %s rubel", + "ragfair-offer_no_longer_exists": "Az ajánlat már nem létezik", + "ragfair-unable_to_purchase_0_count_item": "Nem lehet megvásárolni a terméket: %s 0-ás darabszámmal", + "ragfair-unable_to_place_offer_with_no_requirements": "Nem lehet ajánlatot tenni követelmények nélkül", + "ragfair-unable_to_find_locale_by_key": "Nem sikerült megtalálni az EFT helyét a következő kulccsal: %s", + "ragfair-unable_to_adjust_stack_count_assort_not_found": "Kereskedő: {{traderId}} piaci ajánlat: {{offerId}} nem módosítható a kereskedői kínálat értékének megfelelő darabszámmal (a kínálat nem található)", + "ragfair-unable_to_remove_offer_not_found_in_profile": "Nem található ajánlat: {{offerId}} a profilban: {{profileId}}, mivel az ajánlat nincs meghatározva, létrehozás", "ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "Nem sikerült megtalálni az élő-piaci vagy kézikönyvi árat %s esetében, alapértelmezett érték 1-re állítva, ha ez egy modolt tárgy, lépj kapcsolatba annak készítőjével", "ragfair-unable_to_find_preset_with_id": "Nem sikerült megtalálni a beállítást az azonosítóval: %s, a meglévő fegyveralap aktuális ára kerül felhasználásra", "ragfair-unable_to_remove_offer_doesnt_exist": "Nem lehet eltávolítani az ajánlatot a következő azonosítóval: %s, mivel nem található meg a piacon", "repeatable-accepted_repeatable_quest_not_found_in_active_quests": "Elfogadtál egy ismételhető küldetést: %s, amely nem található az activeQuests tömbben. Kérjük, jelentsd ezt a hibát", + "repeatable-completion_quest_whitelist_too_small_or_blacklist_too_restrictive": "Befejezési küldetés generálása: Nincsenek tételek. Vagy az engedélyezőlista túl kicsi, vagy a tiltólista túl korlátozó", "repeatable-difficulty_was_nan": "Ismételhető jutalom generálása: A nehézség értéke NaN. Beállítás 1-re.", "repeatable-no_reward_item_found_in_price_range": "Ismételhető jutalom generálása: Nem található tárgy az ártartományban {{minPrice}}-tól {{roublesBudget}}-ig", "repeatable-quest_handover_failed_condition_already_satisfied": "Küldetés átadási hiba: a feltétel már teljesült? qid: {{questId}}, condition: {{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Küldetés átadási hiba: a feltétel nem található vagy az érték helytelen. qid: {{body.qid}, condition: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Nem lehet elfogadni a küldetést, részletekért lásd a szerver naplóját", "repeatable-unable_to_accept_quest_starting_message_not_found": "Nem lehet elfogadni a küldetést: {{questId}}, nem található a küldetés elindításának üzenet szövege az alábbi azonosítóval: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s útvonal nem jelent vissza se sikerességet se kudarcot", @@ -453,7 +576,6 @@ "pmc-name_prefix_33": "Vezető", "pmc-name_prefix_34": "Trükkös", "pmc-name_prefix_35": "Komoly", - "pmc-name_prefix_36": "Gyanús", "pmc-name_prefix_37": "Gyanakvó", "pmc-name_prefix_38": "Ciki", "pmc-name_prefix_39": "Menő", diff --git a/project/assets/database/locales/server/id.json b/project/assets/database/locales/server/id.json index 6f292259..edf03221 100644 --- a/project/assets/database/locales/server/id.json +++ b/project/assets/database/locales/server/id.json @@ -189,7 +189,6 @@ "repeatable-difficulty_was_nan": "Pembuatan hadiah yang diulang: Kesulitan merupakan NaN. Diubah menjadi 1.", "repeatable-no_reward_item_found_in_price_range": "Pembuatan Hadiah yang Diulang: Tidak ditemukan barang dengan jarak harga {{minPrice}} sampai {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Permasalahan dalam penyerahan quest: kondisi sudah terpenuhi? qid: {{questId}}, kondisi: {{conditionId}}, profileCounter: {{profileCounter}}, nilai: {{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Permasalahan dalam penyerahan quest: kondisi tidak ditemukan atau nilai salah. qid: {{body.qid}, kondisi: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Tidak dapat menerima quest, lihat catatn server untuk detil", "repeatable-unable_to_accept_quest_starting_message_not_found": "Tidak dapat menerima quest: {{questId}} tidak dapat mencari pesan quest mulai dengan id: {{messageId}}", "route_onupdate_no_response": "onUpdate: rute %s tidak melaporkan sukses atau gagal", diff --git a/project/assets/database/locales/server/it.json b/project/assets/database/locales/server/it.json index a09cae96..8fbceea6 100644 --- a/project/assets/database/locales/server/it.json +++ b/project/assets/database/locales/server/it.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "Generatore di Ricompense Ripetibili: Difficoltà era NaN. Settata a 1.", "repeatable-no_reward_item_found_in_price_range": "Generatore di Ricompense Ripetibili: Nessun oggetto trovato nell'intervallo di prezzo {{minPrice}} a {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Errore consegna missioni: la condizione è già stata soddisfatta? qid: {{questId}}, condizione: {{conditionId}}, profileCounter:{{profileCounter}}, valore:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Errore consegna missioni: condizione non trovata o valore errato. qid: {{body.qid}, condizione: {{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "Errore riconsegna quest: la condizione non è stata trovata o il valore è errato. qid: {{body.qid}}, condizione: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Impossibile accettare quest, vedi i log del server per i dettagli", "repeatable-unable_to_accept_quest_starting_message_not_found": "Impossibile accettare missioni: {{questId}} non è possibile trovare il messaggio iniziale con id: {{messageId}}", "route_onupdate_no_response": "La route di onUpdate: %s non riporta alcun successo o fallimento", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Il tuo computer fa cosi schifo che fai 20fps su streets", "pmcresponse-victim_negative_100": "Sono sicuro sei uno di quelli che ha installato SAIN e l'ha dovuto togliere perché veniva ucciso troppe volte", "pmcresponse-victim_negative_101": "Scusa cos'è che hai detto, insignificante Scav che non sei altro? Devi sapere che ho superato il corso d'addestramento degli USEC a pieni voti e che ho partecipato a numerosi raid segreti con gli {{playerSide}} con più di 300 uccisioni confermate. Sono addestrato in tattiche da guerriglia e sono il miglior tiratore scelto di tutte le forze armate USEC. Per me sei solo un altro bersaglio. Posso farti esplodere la testa quando e come voglio in questo raid, stai bene attento. Pensi di potertela cavare scrivendomi questa roba nella finestra dei messaggi? Beh ti sbagli di grosso, SCHIAPPA. Sto già contattando la mia rete segreta di spie sparse per tutta Customs e la tua stash è stata tracciata, è meglio che cominci a fartela addosso. Perché c'è uno tsunami di guai diretti verso di te e verso quella tua patetica vita. Sei morto, Scav. Posso essere ovunque, in qualsiasi momento, e conosco più di settecento modi per ucciderti con le mie mani. E oltre al mio esteso addestramento in combattimento a mani nude posso contare anche sull'intero arsenale degli USEC, il quale non esiterò ad usare in tutta la sua potenza distruttiva per far sparire quel tuo grugno bastardo dalla mappa, mio caro tarzanello. Mi sa che se tu avessi saputo cosa ti aspettava quando hai fatto quella furbata per killarmi, forse ora torneresti indietro. Ma non potevi saperlo, hai fatto la tua scelta ed ora ne paghi le conseguenze, stupido idiota. Affogherai nel mare di merda che ti sto per riversare addosso. Sei morto, Scav.", + "pmcresponse-victim_negative_102": "Scommetto che hai comprato la nuova edizione solo per avere le tasche più grandi", "pmcresponse-victim_plead_1": "Stavo facendo una missione", "pmcresponse-victim_plead_2": "Volevo solamente finire una missione, perché mi hai ucciso", "pmcresponse-victim_plead_3": "Spero tu sia felice, non posso nemmeno permettermi un nuovo kit adesso", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "Il loot più facile della giornata", "pmcresponse-killer_negative_28": "Non ti preoccupare ho portato la tua roba a casa di tua mamma", "pmcresponse-killer_negative_29": "Ma ti stavi impegnando almeno un po?", + "pmcresponse-killer_negative_30": "Scommetto che sei uno di quei polli che hanno sborsato 250 sacchi per la nuova edizione", + "pmcresponse-killer_negative_31": "Beccati sta rattáta", + "pmcresponse-killer_negative_32": "Il colpo del ratto", "pmcresponse-killer_plead_1": "Stavo estraendo un item per una quest e mi sei passato davanti", "pmcresponse-killer_plead_2": "Stavo lootando e ti sei messo in mezzo, mi spiace", "pmcresponse-killer_plead_3": "Ho bisogno di uccidere PMC sono certo che capisci", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "Capo", "pmc-name_prefix_34": "Scaltro", "pmc-name_prefix_35": "Serio", - "pmc-name_prefix_36": "Sospettoso", + "pmc-name_prefix_36": "Portatile", "pmc-name_prefix_37": "Sospettoso", "pmc-name_prefix_38": "Cringe", "pmc-name_prefix_39": "Sciatto", diff --git a/project/assets/database/locales/server/ja.json b/project/assets/database/locales/server/ja.json index 23690d49..18b73232 100644 --- a/project/assets/database/locales/server/ja.json +++ b/project/assets/database/locales/server/ja.json @@ -9,9 +9,9 @@ "bot-bot-cache_has_zero_bots_of_requested_type": "警告 - Botキャッシュに %s型の事前生成されたBotが存在しません。追加生成するには、サーバーを再設定する必要があります。", "bot-compatibility_check_missing_props": "アイテムを検証できません: スロット内の {{id}} {{name}}: {{slot}} を装備できます。_props の値が存在しません。", "bot-generation_failed": "botの生成に失敗しました詳細はサーバログを参照してください", - "bot-incompatible_ammo_for_weapon_falling_back_to_default": "互換性のない弾薬 {{chosenAmmo}} が {{weaponId}} で見つかりました。- {{defaultAmmo}}にフォールバックしています。", + "bot-incompatible_ammo_for_weapon_falling_back_to_default": "互換性のない弾薬 {{chosenAmmo}} が {{weaponId}} - {{weaponName}} の中に見つかりました。デフォルトの {{defaultAmmo}} に入れ替えます。", "bot-invalid_item_compatibility_check": "装備アイテムとの互換性をチェックできません: スロットの{{itemTpl}} は有効なアイテムではありません:{{slot}} は有効なアイテムではありません。", - "bot-item_spawn_limit_reached_skipping_item": "{{botRole}} アイテム {{itemName}} を {{attempts}} 回試行してもスポーンできない、スポーン制限を無視する。", + "bot-item_spawn_limit_reached_skipping_item": "{{botRole}} にアイテム {{itemName}} のスポーンを {{attempts}} 回試行してもできませんでした。スポーン制限を無視します", "bot-loot_type_not_found": "ルートキャッシュに失敗しました:botの{{lootType}}: {{botRole}} はPMCでした: {{isPmc}}", "bot-missing_cartridge_slot": "モッドプールにシランダマガジン %s 用のカートリッジが含まれていないため、武器にカートリッジを追加できません。 スキップします。", "bot-missing_container_with_tpl": "Tplはコンテナテンプレートを発見することができませんでした: %s", @@ -52,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "%s という名前のキャッシュ内のボットを見つけることができません。", "bot-missing_application_context": "applicationContextは %s 値を見つけることができませんでした。ゲームを再起動せずにサーバーを再起動しましたか?", "client_request": "[Client Request] %s", + "client_request_ip": "[クライアント要請] {{ip}} {{url}}", "customisation-item_already_purchased": "アイテム {{itemId}} {{itemName}} は既に購入されています", "customisation-unable_to_find_suit_by_id": "ID: %s のトレーダースーツオファーを見つけることができません", "customisation-unable_to_find_clothing_item_in_inventory": "ID: %s の在庫がありません", @@ -84,25 +85,59 @@ "validation_error_file": "ファイルの検証に失敗しました: %s", "validation_error_exception": "ファイルの検証中に例外が検出されました: %s", "importing_spt_configs": "設定をインポートしています...", + "inraid-missing_standing_for_kill": "{{victimSide}}:{{victimRole}} をキルした際の友好度の変動値が見つかりません", + "insurance-missing_insurance_price_multiplier": "トレーダーの保険の乗数値がありません: %s、InsuranceConfig.js に値が存在するかを確認してください。値をデフォルトの 0.3 に設定します。", "inventory-edit_trader_item": "トレーダーのアイテムを編集できません。", + "inventory-examine_item_does_not_exist": "examineItem() - %s の id が見つかりません", + "inventory-fill_container_failed": "fillContainerMapWithItem() がエラーを返しました: %s", "inventory-invalid_item_missing_from_db": "データベースからアイテム %s を取得できません。", + "inventory-invalid_move_to_container": "スロット id: {{slotId}} のアイテムを {{container}} に移動しようとしましたが、プロファイルの破損を防止しました。", "inventory-no_stash_space": "十分な保管スペースがありません", "inventory-unable_to_fill_container": "[OOB] アイテム: {{id}}; エラー メッセージ: ${error}", "inventory-unable_to_find_item": "getExaminedItemTpl() tpl: %s のアイテムがデータベースまたはフリーマーケットから見つけられませんでした", "inventory-unable_to_find_stash": "隠し場所が見つかりません。", + "inventory-return_default_size": "アイテム %s の容量をデフォルトの1x1に設定しました", + "inventory-item_missing_props_property": "アイテム tpl: {{itemTpl}} アイテム名: {{itemName}} に props プロパティがありません。サイズが取得できません", + "inventory-get_item_size_item_not_found_by_tpl": "getSizeByInventoryItemHash() アイテムの tpl: %s が見つかりません", + "inventory-item_to_toggle_missing_upd": "インベントリアイテムの _id: %s に updオブジェクトがありません。追加します", + "inventory-unable_to_toggle_item_not_found": "インベントリのアイテム id: %s を切替できません、アイテムが見つかりません", + "inventory-missing_stash_size": "プレイヤーのスタッシュが見つからないため、スタッシュの容量が未定です", + "inventory-stash_not_found": "db にスタッシュ %s が見つかりません", + "item-durability_value_invalid_use_default": "getRepairableItemQualityValue() 武器 tpl: %s 耐久値の値が無効です、デフォルトの 1 に設定します", "linux_use_priviledged_port_non_root": "非ルート プロセスは 1024 未満のポートにバインドできません。", "location-containers_generated_success": "合計 %s 個の静的コンテナーが生成されました。", + "location-critical_error_see_log": "ルートの生成時に重大なエラーが発生しました。サーバーログを参照してください", "location-dynamic_items_spawned_success": "合計 %s 個の動的アイテムが生成されました。", "location-generated_success": "生成された場所 %s", + "location-missing_root_item": "createItem() が失敗しました。親アイテムが null です。tpl: {{tpl}}, parentId: {{parentId}}", + "location-preset_not_found": "{{tpl}} のプリセットが見つかりませんでした。defaultPrest: {{defaultId}} name: {{defaultName}}, parentId: {{parentId}}", + "location-spawn_point_count_requested_vs_found": "マップ {{mapName}} スポーンポイント {{requested}} が要請されましたが、{{found}} のみが利用可能です", + "location-unable_to_reparent_item": "createItem() が失敗しました。{{tpl}} に親を再設定できませんでした。parentId: {{parentId}}", + "location-unable_to_find_airdrop_drop_config_of_type": "%s タイプのエアドロップのコンフィグが見つかりません。デフィルトの mixed タイプに設定します", + "location-unable_to_fix_broken_waves_missing_base": "%s に基本の json がありません。ボットのマップウェーブの修正をスキップします。", + "location-missing_dynamic_template": "選択されたダイナミックスポーンポイント %s にはテンプレートがありません。スキップします", + "location-spawnpoint_missing_items": "選択されたダイナミックスポーンポイント %s にはアイテムがありません。スキップします", + "loot-item_missing_parentid": "アイテム: %s に parentId 値がありません。アイテムを物資として使用できません。", + "loot-non_item_picked_as_sealed_weapon_crate_reward": "無効な武器: %s が密封された武器箱の報酬として選ばれました。物資を作成できません。", + "mailsend-missing_trader": "{{messageType}} タイプのメッセージをプレイヤー: {{sessionId}} に送信できません。与えられたトレーダーの列挙型が null です", + "mailsend-missing_npc_dialog": "%s からメッセージを送信できません。台詞が存在しません。", + "mailsend-missing_parent": "トレーダー: {{traderId}} 送信者: {{sender}} ハイドアウトのメッセージに該当するslotIdのアイテムが見つかりません。", + "mod-send_bundle_url": "[バンドル]: %s", "modloader-checked": "チェックしました。", "modloader-checking_mod": "チェック中: %s", "modloader-cyclic_dependency": "循環依存が検出されました。", + "modloader-load_order_conflict": "`{{modOneName}}` と `{{modTwoName}}` のロードの順序の条件が競合しています。 これが修正されるまでサーバーを起動できずシャットダウンします", + "modloader-dependency_container_not_initalized": "依存関係コンテナーが要求されましたが、初期化されませんでした", "modloader-error_parsing_mod_load_order": "mod ロード順の解析中にエラーが発生しました。", "modloader-incompatibilities_not_string_array": "Mod %s package.json プロパティ '非互換性' は文字列配列でなければなりません。", "modloader-incompatible_mod_found": "Mod {{author}}-{{name}} is incompatible with {{incompatibleModName}}。", "modloader-invalid_akiversion_field": "モッド %s のakiVersion区域にで不正確なSemver文字列が使用されています。 正しい例はこちらに: https://github.com/npm/node-semver#versions", "modloader-invalid_version_property": "モッド %s のpackage.jsonにで不正確なバージョン文字列が使用されています。", + "modloader-not_correct_mod_folder": "Modsフォルダに (%s) という名前のフォルダが存在します。Modのインストールの手順が間違えています。 あなたが間違ってModフォルダに直接Modの内容をそのまま抽出した可能性があります。 ウェブサイトの FAQ および Mod のハブページを参照してください", "modloader-is_client_mod": "モッド %s はクライアントタイプのモッドです。正しいインストール先はこちら: /spt/bepinex/plugins", + "modloader-installing_external_dependencies": "Mod {{name}} by: {{author}} と依存関係であるModをインストールしています", + "modloader-installing_external_dependencies_disabled": "Mod: {{name}} by: {{author}} が追加の依存関係Modを必要としていますが、設定が無効になっているためダウンロードができません。 \"{{configPath}}\" の \"{{configOption}}\" を true に設定してからサーバーを再起動してください。\n設定を有効にするにあたって、{{name}} があなたのパソコンにダウンロードするデータの責任をあなたが負うものとします", + "modloader-skipped_mod": "Mod のロードをスキップします: {{mod}}", "modloader-loaded_mod": "モッド {{name}} バージョン{{version}} 作者 {{author}} 読み込む完了。", "modloader-loading_mods": "モッド読み込むツール: %s 個のモッド読み込む中...", "modloader-main_property_not_js": "モッド %s のpackage.jsonの主要プロパティは .js ファイルである必要があります。", @@ -112,40 +147,108 @@ "modloader-missing_package_json": "モッド %s のpackage.jsonが見つかりません。", "modloader-missing_package_json_property": "モッド {{modName}} のpackage.json のプロパティ {{prop}} の設定が必要となります。", "modloader-mod_incompatible": "モッド読み込むツール: モッド互換性の問題が発生しました. 最低限の要求として、モッドがこれらのどちらかのインプリメンツに指名する必要があります: IPostAkiLoadMod, IPostDBLoadMod, IpreAkiLoadMod", + "modloader-mod_has_no_main_property": "ModLoader: Mod (%s) は互換性がありません。'main' プロパティが欠落しています", + "modloader-async_mod_error": "ModLoader: 非同期Modのロード時にエラーが発生しました: %s", "modloader-no_mods_loaded": "どれかのモッドか複数のモッドにエラーを発見。すべてのモッドの読み込みをスキップしました。", "modloader-outdated_akiversion_field": "モッド %s は現バージョンのAKIに互換性がありません。問題が発生した場合、問い合わせに対応しかねます。", "modloader-outdated_dependency": "モッド {{mod}} の前提条件である {{modDependency}} はバージョン {{requiredVersion}} を要求されています。現在インストールされているバージョンは {{currentVersion}}", - "modloader-user_mod_folder_missing": "モッド読み込むツール: user/mod フォルダーが見つかりません、フォルダー作成中...", + "modloader-user_mod_folder_missing": "ModLoader: user/mod フォルダーが見つかりません、フォルダー作成中...", + "modloader-mod_order_missing": "ModLoader: order.json が見つかりません。作成中...", + "modloader-mod_order_error": "ModLoader: order.jsonにエラーが発生しました。デフォルトの読み込み順序を使用します", + "modloader-mod_order_missing_from_json": "ModLoader: Mod %s が order.json に含まれていません。追加します", "modloader-visited": "ビジットをカウントした。", + "modloader-x_duplicates_found": "複数のバージョンの %s Mod をロードしようとしています。すべてスキップします", + "openzone-unable_to_find_map": "場所: %s が存在しないため、ゾーンを追加することができません", "payment-not_enough_money_to_complete_transation": "プロファイルに通貨が足りません: {{amountToPay}} が必要で、 {{amountAvailable}} が所持しています。", "payment-not_enough_money_to_complete_transation_short": "プロファイルに通貨が足りません。", "payment-zero_price_no_payment": "価額が0なので、支払いは要りません。", "player-attempt_to_increment_skill_with_negative_value": "スキル %s の上昇は負数では出来ません。", "port_already_in_use": "ポート %s は既に使用されています。サーバーがすでに立ち上げされいるのかを確認してください。", "profile_saved": "プロファイルをセーブした。", + "profile_save_callback_error": "onBeforeSaveCallback を実行中にエラーが発生しました: {{callback}}, {{error}}", + "profile-unable_to_find_profile_by_id_cannot_delete": "idでプロファイルが削除できません。id: %s のプロファイルが見つかりません", + "quest-compare_operator_unhandled": "loyaltyRequirementCheck() 演算子 %s が処理されてません。デフォルトのfalseに設定します", + "quest-item_not_found_in_inventory": "changeItemStack() アイテムの_id: %s がインベントリ内に見つかりません", + "quest-no_skill_found": "スキル %s が見つかりません", + "quest-handover_wrong_item": "クエスト {{questId}} にアイテムの納品ができません。要求されてるtpl: {{requiredTpl}} 納品しようとしたtpl: {{handedInTpl}}", + "quest-reward_type_not_handled": "クエスト報酬タイプ: {{rewardType}} はクエストで処理されていません: {{questId}} クエスト名: {{questName}}", + "quest-unable_to_find_compare_condition": "認識されてない比較方法: %s", + "quest-unable_to_find_matching_hideout_production": "クエスト {{questName}} に合うハイドアウトの解除可能なレシピが見つかりません。一致する項目: {{matchCount}}", "ragfair-invalid_player_offer_request": "要求が不正確なので出品できません。", "ragfair-missing_barter_scheme": "generateFleaOffersForTrader() がアイテムを検出できません。アイテムID: {{itemId}} tpl: {{tpl}} 名前 {{name}}", "ragfair-no_trader_assorts_cant_generate_flea_offers": "商人 %s の品揃えリストが見つかりませんので、フリーマーケットの出品リストを生成できません。", "ragfair-offer_not_found_in_profile": "プロファイルに出品ID {{offerId}} が見つかりませんので、削除出来ません。", "ragfair-offer_not_found_in_profile_short": "プロファイルに出品が見つかりません", + "ragfair-offer_not_found_unable_to_hide": "hideItem() offerId: %s が見つかりません。オファーを非表示にできません", "ragfair-tpl_not_a_valid_item": "generateFleaOffersForTrader() tpl: %s は正確なアイテムではありません、スキップしました。", "ragfair-unable_to_find_item_in_inventory": "インベントリーに以下のIDを持つアイテムを見つかりません: {{id}} ", + "ragfair-unable_to_find_offer_to_remove": "削除する当該のIDのオファーが見つかりません: %s", "ragfair-unable_to_find_requested_items_in_inventory": "インベントリーに要求しているアイテムを見つかりません。", "ragfair-unable_to_pay_commission_fee": "手数料を支払い出来ません。", + "ragfair-offer_no_longer_exists": "オファーがもう存在しません", + "ragfair-unable_to_purchase_0_count_item": "アイテムの購入ができません: ゼロ個の %s", "ragfair-unable_to_place_offer_with_no_requirements": "要求なしでは出品出来ません。", + "ragfair-unable_to_find_locale_by_key": "キー付きのEFTロケールが見つかりません: %s", + "ragfair-unable_to_adjust_stack_count_assort_not_found": "トレーダー: {{traderId}} Flea オファー: {{offerId}} はトレーダーのアソート値に合うスタック数に調整できませんでした (アソートが見つかりません)", + "ragfair-unable_to_remove_offer_not_found_in_profile": "オファーが未定義のため、{{offerId}} のオファーがプロファイル: {{profileId}} 内に見つかりません。作成中", + "ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "%s のLiveのFleaマーケットまたはハンドブック価格を見つけることができません。デフォルトの1に設定しました。これがModのアイテムの場合、Modの作成者に連絡してください", + "ragfair-unable_to_find_preset_with_id": "Id: %s のプリセットが見つかりません。既存の武器ベースの価格を使用します", + "ragfair-unable_to_remove_offer_doesnt_exist": "Flea マーケットで見つけられないため、Id: %s のオファーを削除できません", + "repeatable-accepted_repeatable_quest_not_found_in_active_quests": "activeQuests 配列にない繰り返し可能なクエスト: %s を受理しました。このバグを報告してください", + "repeatable-completion_quest_whitelist_too_small_or_blacklist_too_restrictive": "アイテム配信クエスト生成: 使用できるアイテムがありません。ホワイトリストが少なすぎるか、ブラックリストの制限が強すぎです", "repeatable-difficulty_was_nan": "定期クエスト報酬生成: 難易度は NaN に設定されました。 1 に設定します。", "repeatable-no_reward_item_found_in_price_range": "定期クエスト報酬生成: 価額幅 {{minPrice}} から {{roublesBudget}} にでアイテムを見つかりません。", + "repeatable-quest_handover_failed_condition_already_satisfied": "クエスト納品エラー: 条件が既に満たされているかもしれません。 qid: {{questId}}, 条件: {{conditionId}}, profileCounter: {{profileCounter}}, 値: {{value}}", + "repeatable-quest_handover_failed_condition_invalid": "クエスト納品エラー: 条件が見つからないか正しい値でありません。qid: {{body.qid}}, condition: {{body.conditionId}}", + "repeatable-unable_to_accept_quest_see_log": "クエストを受理できません。詳細はサーバーログを参照してください。", + "repeatable-unable_to_accept_quest_starting_message_not_found": "クエストを受理できません。{{questId}} が開始時のメッセージ Id: {{messageId}} を見つけられられませんでした", "route_onupdate_no_response": "情報更新: ルート %s の成功か失敗かの返事がありません。", + "repair-unable_to_find_item_in_db": "アイテムを修理できません: %s がアイテム db 内で見つかりません。修理スキルポイントを加算できません", + "scav-missing_karma_level_getting_default": "getScavKarmaLevel() が失敗しました。profile.traderInfo でフェンスを見つけることができません。デフォルトのカルマレベル 0 として扱います", + "scav-missing_karma_settings": "レベル %s のカルマ設定を取得できません", "scheduled_event_failed_to_run": "定期イベント: '%s' の執行は失敗しました。", + "seasonal-missing_equipment_slot_on_bot": "{{botRole}} ボットに見つからないため、{{equipmentSlot}} スロットからクリスマス装備を削除することができません", + "seasonal-missing_loot_container_slot_on_bot": "{{botRole}} ボットに見つからないため、{{lootContainer}} スロットからクリスマス物資を削除することができません", "server_running": "サーバーが実行中。", + "server_start_meme_1": "生きて、愛して、笑って", + "server_start_meme_2": "アニメ :(", + "server_start_meme_3": "私の声が聞こたら、起きてね", + "server_start_meme_4": "ライクとサブスクライブしてね!", + "server_start_meme_5": "公式のミーム専用ページがあるよ", "server_start_meme_6": "You better not be using a fitgirl repack, I swear to god", + "server_start_meme_7": "bingos binted", + "server_start_meme_8": "さあ、モービる時間だ", + "server_start_meme_9": "S、SCAVお兄ちゃん、なにしてるの?壁から出してよぉ!", + "server_start_meme_10": "[デバッグ] ビットコインマイナーを起動中", + "server_start_meme_11": "miner.exe の起動に失敗しました。サーバーを再起動してね", + "server_start_meme_12": "あなたの車の延長保証についてご連絡いたします", + "server_start_meme_13": "ඞ ... sus", + "server_start_meme_14": "ඞ ඞ ඞ ඞ amogus ඞ ඞ ඞ ඞ ඞ", + "server_start_meme_15": "誰か!誰かいませんか?Chompに奴隷にされちゃった!", + "server_start_meme_16": "モッ*げっぷ*...モーティ、俺たちは何かの電脳空間に閉じ込めらてるみたいだ", + "server_start_meme_17": "私はあなたの位置に急接近しています。今すぐ逃げ出してください", + "server_start_meme_18": "このメッセージが読める場合、おめでとう。あなたは字が読めます", + "server_start_meme_19": "おめでとうございます!あなたはタルコフの無料キーに見事当選なさいました!ここからキーを回収ください: https://bit.ly/3TJbUh2", + "server_start_meme_20": "知っていましたか?10人中9人はこのメッセージを読むことができません", + "server_start_meme_21": "あなたは考えたことがありますか? 皆、赤い色を同じ色として見ることができるかどうか。", + "server_start_meme_22": "日々鍛練せよ", + "server_start_meme_23": "2018年以来、あなたの童貞を堅く守ってくれるSPT", + "server_start_meme_24": "秘密の避難所サーバーは本当だけど、誰にも言わないでね!", "server_start_success": "楽しんできてください!", + "server_start_player_active_botreload_skill": "あなたのキャラクターの 'BotReload' スキルが有効になっています。銃を素早くリロードするようになります。意図的な場合はこのメッセージを無視してください", "started_webserver_success": "%s にでウェブサーバーを起動しました。", + "trader-missing_durability_threshold_value": "トレーダー {{traderId}} の耐久値しきい値が見つかりませんでした。デフォルトの {{value}} に設定します", + "trader-missing_trader_details_using_default_refresh_time": "トレーダー: {{traderId}} が見つかりません。臨時エントリを生成します。デフォルトの更新時間: {{updateTime}}", + "trader-price_multipler_is_zero_use_default": "traderPriceMultipler がゼロになっています。これは無効です。0.01 に設定します", + "trader-unable_to_delete_stale_purchases": "トレーダー取引を処理できません。プロファイル {{profileId}} のトレーダー {{traderId}} が見つかりません。スキップします", "unhandled_response": "[UNHANDLED][%s] ([%s] を処理できません。)", "unknown_request": "不明なリクエストを検知。", "watermark-commercial_use_prohibited": "本プログラムの商業転用をお遠慮ください。", + "watermark-discord_url": "https://discord.sp-tarkov.com", "watermark-do_not_report": "通報しないでください。", "watermark-free_of_charge": "本プログラムは無料です。", + "watermark-paid_scammed": "もしお金を支払った場合、あなたは詐欺に遭ってます", + "watermark-issue_tracker_url": "https://dev.sp-tarkov.com/SPT-AKI/Server/issues", "watermark-modding_disabled": "本バージョンはサーバーモッドを無効に設定しています。", "watermark-no_support": "問い合わせに対応しかねます。", "watermark-not_an_issue": "これは不具合ではありません。", @@ -158,5 +261,355 @@ "websocket-pinging_player": "[WS] プレイヤー: %s をPingしています。", "websocket-player_connected": "[WS] プレイヤー: %s は接続しました。", "websocket-received_message": "[WS] プレイヤー: %s からメッセージを送られました。", - "websocket-started": "%sにでウェブソケットが起動した" + "websocket-socket_lost_deleting_handle": "[WS] ソケットを失いました、ハンドルを削除します", + "websocket-started": "%sにでウェブソケットが起動した", + "pmcresponse-victim_positive_1": "いい腕だ", + "pmcresponse-victim_positive_2": "素晴らしい射撃の腕だ", + "pmcresponse-victim_positive_3": "いいキルだ", + "pmcresponse-victim_positive_4": "当然にやられた、よくやった", + "pmcresponse-victim_positive_5": "ラッキーだったな", + "pmcresponse-victim_positive_6": "よく戦った", + "pmcresponse-victim_positive_7": "さっきのはまあ、良いキルだ", + "pmcresponse-victim_positive_8": "間違いなくあんたはいい射的手だ", + "pmcresponse-victim_positive_9": "gg", + "pmcresponse-victim_positive_10": "覗かなければよかった", + "pmcresponse-victim_positive_11": "あんたにやられた", + "pmcresponse-victim_positive_12": "いいキルだ。次は俺の番だ", + "pmcresponse-victim_positive_13": "いい角度で攻めたな", + "pmcresponse-victim_positive_14": "次は俺がお前をやる", + "pmcresponse-victim_positive_15": "よく僕のボゴスをビントしたな :alien:", + "pmcresponse-victim_positive_16": "なんて冷酷な殺人鬼だ。俺に隙も与えなかったな", + "pmcresponse-victim_positive_17": "認めるよ、さっきのはいい射撃だったな", + "pmcresponse-victim_positive_18": "僕の物資で楽しんでね", + "pmcresponse-victim_positive_19": "いい戦いだ", + "pmcresponse-victim_positive_20": "お前は腕が立つな", + "pmcresponse-victim_positive_21": "側面から来るとは、よくやった", + "pmcresponse-victim_positive_22": "もっと警戒すべきだった。すごいね", + "pmcresponse-victim_positive_23": "焦って攻めちゃった。横から待ち伏せればよかった", + "pmcresponse-victim_positive_24": "学べる戦闘だった。すごい", + "pmcresponse-victim_positive_25": "くそっ、やったと思ったのに", + "pmcresponse-victim_positive_26": "よくやった、いい立ち振る舞いだ", + "pmcresponse-victim_positive_27": "いいキルだ、よくやったな", + "pmcresponse-victim_positive_28": "堅実なキルだった。次のレイドで会おう", + "pmcresponse-victim_positive_29": "すげぇChadなキルだな、やられたよ", + "pmcresponse-victim_positive_30": "隙もなかったな", + "pmcresponse-victim_positive_31": "さっきのはもう、Chadレベルの立ち振る舞いだな", + "pmcresponse-victim_positive_32": "あんたが来るのも見えなかった、すごい", + "pmcresponse-victim_positive_33": "さっきのはもう、ソリッドでスネークな動きだったな", + "pmcresponse-victim_positive_34": "さっきのはなかなかなキルだったな。チームを組むべきだ", + "pmcresponse-victim_positive_35": "さっきのは素晴らしいキルだった。いつかチームを組もう", + "pmcresponse-victim_positive_36": "なんて反射神経なんだ", + "pmcresponse-victim_positive_37": "隠れてたけど見える角度を見つけられちゃったな、いいぞ", + "pmcresponse-victim_positive_38": "なんてもう、Chadな動きだ", + "pmcresponse-victim_positive_39": "空前絶後のChadシューターがいるぜ。いいキルだ", + "pmcresponse-victim_positive_40": "綺麗に吹っ飛ばされた", + "pmcresponse-victim_positive_41": "冷血なキルだったな", + "pmcresponse-victim_positive_42": "俺を馬鹿みたいによくやってくれた", + "pmcresponse-victim_positive_43": "俺の腕が少しさびてたが、まあいいキルだろう", + "pmcresponse-victim_positive_44": "いいキルだ {{playerName}}", + "pmcresponse-victim_positive_45": "クリーンキルだ、{{playerName}}。物陰に居たがあんたに見つかっちまった", + "pmcresponse-victim_positive_46": "あんたが何処から撃ってるのも見えなかった。どこに居たの?", + "pmcresponse-victim_positive_47": "いいスポットだね。どうしてそこを選んだい?", + "pmcresponse-victim_positive_48": "完璧なタイミングだね。きみの戦略をぜひ知りたい", + "pmcresponse-victim_positive_49": "いとも簡単に回り込まれるとは。その秘密は?", + "pmcresponse-victim_positive_50": "見事なエイムですね。なにかヒントをありますか", + "pmcresponse-victim_positive_51": "マップを知り尽くしてるようだね。なにかガイドはないかい", + "pmcresponse-victim_positive_52": "どうやってそんな静かに動き回ったんだ", + "pmcresponse-victim_positive_53": "すごい反応速度だよ、なにかアドバイスちょうだい", + "pmcresponse-victim_positive_54": "いい待ち伏せのスポットを知っているようだね。ぜひ教えて", + "pmcresponse-victim_positive_55": "その武器を使いこなしてるようだな。なにかヒントは", + "pmcresponse-victim_positive_56": "どうやったら音を聞かれずに背後を取れるんだ", + "pmcresponse-victim_positive_57": "あんたは射撃戦のプロだな。なにか教えられることは", + "pmcresponse-victim_positive_58": "すっげぇエイムだな!なんか教えて!", + "pmcresponse-victim_positive_59": "よぉ、あんたホントこのゲームのニンジャだな。どうやってそんなうまくなるんだ", + "pmcresponse-victim_positive_60": "如何にして背中をやられた!あなたみたいに静かに立ち回るにはどうすれば", + "pmcresponse-victim_positive_61": "すごい早撃ちだったな。アドバイスはないかい", + "pmcresponse-victim_positive_62": "すごいとこに隠れてたな。いいアドバイスあるか", + "pmcresponse-victim_positive_63": "その銃に手慣れているみたいですね。なにか指南はありますか", + "pmcresponse-victim_positive_64": "よぉ、影の様に静かだったな。指南してくれよ", + "pmcresponse-victim_positive_65": "まさかなんな風に討ち取られるとは。よくやった", + "pmcresponse-victim_positive_66": "いつかデゥオを組もうぜ", + "pmcresponse-victim_positive_67": "練れ者だな。今度一緒にレイドに行こうか", + "pmcresponse-victim_negative_1": "すごいチートだね", + "pmcresponse-victim_negative_2": "卑劣な", + "pmcresponse-victim_negative_3": "エスパーわぁすごい", + "pmcresponse-victim_negative_4": "簡単にやりやがって", + "pmcresponse-victim_negative_5": "簡単な技で殺してうれしいか", + "pmcresponse-victim_negative_6": "おまえのチートどんくらいしたんだ", + "pmcresponse-victim_negative_7": "(´・ω・`)", + "pmcresponse-victim_negative_8": "俺は今すごく悔しい", + "pmcresponse-victim_negative_9": "すごいね頑張りっこさん", + "pmcresponse-victim_negative_10": "離席してたんだぞ!", + "pmcresponse-victim_negative_11": "チートしてるから報告した", + "pmcresponse-victim_negative_12": "ラグのお陰だったな", + "pmcresponse-victim_negative_13": "おまえみたいなチーターから離れるためにSPT遊んでくるわ", + "pmcresponse-victim_negative_14": "俺がもっとマップを知り尽くしてら勝ってた", + "pmcresponse-victim_negative_15": "また糞芋砂か、すごい", + "pmcresponse-victim_negative_16": "さっきのが公平だったら俺が勝ってた", + "pmcresponse-victim_negative_17": "あんたが僕の物資を間違ったトレーダーに売ってくれればいいのに", + "pmcresponse-victim_negative_18": "あんたがフレアで間違った価格売ればいいのに", + "pmcresponse-victim_negative_19": "あとで決闘しろおめー。おれが勝つぞ", + "pmcresponse-victim_negative_20": "俺の銃がジャムっただけだから", + "pmcresponse-victim_negative_21": "コソコソしやがって", + "pmcresponse-victim_negative_22": "ネズミみたいに角に隠れられてすごいね", + "pmcresponse-victim_negative_23": "足の小指を箪笥の角にぶつかっちまえ", + "pmcresponse-victim_negative_24": "いまのどうやったの、ママにいいつけるよ", + "pmcresponse-victim_negative_25": "報告した", + "pmcresponse-victim_negative_26": "お母さんもさっきのはぼくが勝ってたっておもってる", + "pmcresponse-victim_negative_27": "俺みたいな初心者をいたぶって楽しいか", + "pmcresponse-victim_negative_28": "どうせおまえはliveでチートしたからSPTで遊んでるんだろ", + "pmcresponse-victim_negative_29": "僕を頭、目したね、ハッカーさん", + "pmcresponse-victim_negative_30": "頭、目チートすごいね", + "pmcresponse-victim_negative_31": "もしおれがもっといい装備持ってたらお前が死んでたんだぞ", + "pmcresponse-victim_negative_32": "私をやっつけたかもしれないが、私の黒キーカードを見つけられなかったまい", + "pmcresponse-victim_negative_33": "俺は殺したけど俺のサーマルを拾わなかったろ", + "pmcresponse-victim_negative_34": "透視がやだからLiveをやめたのにお前ときたら", + "pmcresponse-victim_negative_35": "俺をやっつけたけど、俺ほどベンチプレスできまい", + "pmcresponse-victim_negative_36": "クリストファー・コロンブスの方がお前より地図を知ってる", + "pmcresponse-victim_negative_37": "おまえどうせヤニカスだろ", + "pmcresponse-victim_negative_38": "ジジイみたいな射撃だな。老後はこれで遊ぶのか?", + "pmcresponse-victim_negative_39": "おれの左手で描いたみたいな顔をしてるんだろうな、おまえは", + "pmcresponse-victim_negative_40": "おめーのかーちゃんにカレー作ってって言っといて。もうすぐ帰るから", + "pmcresponse-victim_negative_41": "近親相姦モノでもオメーの家族ほどはやってない", + "pmcresponse-victim_negative_42": "お前はくっさいくっさい小鬼だよ", + "pmcresponse-victim_negative_43": "なぜ暴力を選んだのか", + "pmcresponse-victim_negative_44": "あとで寮で1v1しろ いつでも", + "pmcresponse-victim_negative_45": "典型的な {{playerSide}} だな", + "pmcresponse-victim_negative_46": "レベル {{playerLevel}} ならもっとすごいプレイできるだろうに", + "pmcresponse-victim_negative_47": "酷い損害だったけど、次はお前をやる", + "pmcresponse-victim_negative_48": "次のレイドまで覚えてやがれ。今に見ろよ", + "pmcresponse-victim_negative_49": "今のはただ見えなかった。ラッキーだったね", + "pmcresponse-victim_negative_50": "もう少しだったのに。次は逃がさない", + "pmcresponse-victim_negative_51": "今のはラッキーだったな。次は簡単じゃないぞ", + "pmcresponse-victim_negative_52": "さっきのは僕の悪いプレーだったけど、次はそうはいかないよ", + "pmcresponse-victim_negative_53": "運の女神がついてただけだろ。次は俺のだ", + "pmcresponse-victim_negative_54": "強くなって戻ってくるぞ。見てろよ", + "pmcresponse-victim_negative_55": "誤爆った。でももう起きないよ", + "pmcresponse-victim_negative_56": "俺のリグに入ってたLEDX見つけられなかっただろうなァ", + "pmcresponse-victim_negative_57": "オレの持ってたラボのカード発見できなかったでしょ", + "pmcresponse-victim_negative_58": "レア鍵を僕の体から拾い忘れててたらいいのに", + "pmcresponse-victim_negative_59": "おれのガンマにアイテム移す所だったのに", + "pmcresponse-victim_negative_60": "ケツにアイテム詰め込む時間あったから、お前の戦利品ナシ", + "pmcresponse-victim_negative_61": "俺のガンマ箱は満タンだった。お前のはカラだろうな", + "pmcresponse-victim_negative_62": "ホント陰キャ糞芋", + "pmcresponse-victim_negative_63": "まじおまえrat", + "pmcresponse-victim_negative_64": "ラグかったから俺がやられたんだよ", + "pmcresponse-victim_negative_65": "どうせ、断線の悪用が大好きなんだろ", + "pmcresponse-victim_negative_66": "そろそろおまえが今日分のキルをとってもいい頃か", + "pmcresponse-victim_negative_67": "AIの設定を簡単にしてあるんだろ", + "pmcresponse-victim_negative_68": "おれが誤爆ったからお前が勝ったんだよ", + "pmcresponse-victim_negative_69": "ラッキーだったね", + "pmcresponse-victim_negative_70": "おれの持っていたものよりも弾薬に金を費やしたに間違いない", + "pmcresponse-victim_negative_71": "さっきのキル必要だったんでしょ、酷いK/Dだね", + "pmcresponse-victim_negative_72": "2019年頃のチート武器を使うような人に殺されるなんて、恥ずかしい", + "pmcresponse-victim_negative_73": "わあすごい、なんてすてきなの(これ皮肉)", + "pmcresponse-victim_negative_74": "お前みたいな芋砂嫌い。ゲームが台無し", + "pmcresponse-victim_negative_75": "うんでも俺は現実の方が充実してるし", + "pmcresponse-victim_negative_76": "俺の銃がジャムったから負けた", + "pmcresponse-victim_negative_77": "うちの子供の面倒見なきゃいけないから。みんながみんな君みたいなプロじゃないんだよ", + "pmcresponse-victim_negative_78": "まあでも金は稼いだからキルとかはどうでもいいや", + "pmcresponse-victim_negative_79": "俺の運は仮想通貨の移行の方に言ってるから運が尽きた", + "pmcresponse-victim_negative_80": "家から出ろニート", + "pmcresponse-victim_negative_81": "おめ!お前より現実の方が忙しい人をやっつけたよ", + "pmcresponse-victim_negative_82": "まあ俺今夜デートに行くし(女の子と)だからキルはどうでもいい", + "pmcresponse-victim_negative_83": "俺はRedditの管理者だからおまえの投稿必ず消すよ", + "pmcresponse-victim_negative_84": "俺が幾多の女たちとお電話してたからお前に負けたんだぜ", + "pmcresponse-victim_negative_85": "マイクロウェーブ付けたらWI-FIが死んだからやられた", + "pmcresponse-victim_negative_86": "さっき近所のジムに行ってすごい筋トレしまくったから俺が死んだんだよ", + "pmcresponse-victim_negative_87": "俺はDiscordのモデレーターだから気をつけろよ。俺はここいらじゃ有名だぞ", + "pmcresponse-victim_negative_88": "銃がジャムったおかげでお前助かったんだぞ", + "pmcresponse-victim_negative_89": "おれの運はこんなおこちゃまゲームじゃなくておれの猿のjpg画像の方に行ってたからよかったな", + "pmcresponse-victim_negative_90": "俺が本気じゃなくてよかったな・・・おまえ死んでたぞ", + "pmcresponse-victim_negative_91": "うん実はお前におれを殺させたんだよ", + "pmcresponse-victim_negative_92": "どのみちフェンスに売る装備だったから気にしてないもん", + "pmcresponse-victim_negative_93": "お前の名前は鼠小僧だろうな", + "pmcresponse-victim_negative_94": "スチュアート・リトルのオーディション行ったことあるんだろうな、このこざかしい鼠め", + "pmcresponse-victim_negative_95": "おまえどうせハブにあるレーダーmod使ってんだろ", + "pmcresponse-victim_negative_96": "寮で1v1しろ。どっちの方が上手いかな", + "pmcresponse-victim_negative_97": "てめーもハブにストリーツの処理落ちの投稿書いてる奴らの一人だろうな", + "pmcresponse-victim_negative_98": "おめーのmod全部古臭いバージョンなのにハブに文句垂れてるんだろうな", + "pmcresponse-victim_negative_99": "あんたのパソコン遅すぎてストリーツ遊べないんだろ", + "pmcresponse-victim_negative_100": "あんたどうせSAINインストールしたけど殺されてばっかだから取っ払ったんだろうな", + "pmcresponse-victim_negative_101": "俺の事なんて言った、SCAV野郎、ええ?言っておくが俺はUSEC作戦群の首席で卒業して、無数の極秘 {{playerSide}} 襲撃任務に携わって、300人殺害したんだぞ。俺はゲリラ戦争の訓練を受けたし俺はUSEC隊中トップのスナイパーなんだぞ。俺にとってお前は標的の一人にすぎないだよ。俺の類稀なる精密でお前を派手にブッ飛ばしてやるんだよ、わかってんのか!俺にそんなメッセージ送りつけて言い逃れできると思ってんか?考え直せバーカ!これを書いてる最中にオレもうカスタムに居るウチのスパイの極秘情報網にお前のスタッシュを追跡するように言ってあるんだよ。だから首を洗って待ってろよ、ウジ!嵐の様にちっこい哀れなテメーの命を綺麗に吹き飛ばしちまうんだよ。オメーはもう死んでるんだよ、SCAVめ。俺は神出鬼没だぞ、いつでもどこでもお前を72万通りの殺し方ができるんだぞ、素手だけでだぞ。俺は格闘訓練だけじゃないだよ、USECの武器庫に何時でもアクセスできるんだよ、だから哀れ過ぎるオメーを武器全部使って地図から消し去るんだよ、このウンチめ。お前のしょーもないきったいない\"かしこい\"キルがもたらしちゃった俺の応報が来るのを知ってたら、オメーは黙ってたんだろうな。でもやんなかった、静かにしなかったらか当然の報いを受けるんだよ、バーーカ!オメーに怒りのウンコしまくるぞ、それで溺れるんだぞ。オメーもう死んでるんだよ、SCAV野郎", + "pmcresponse-victim_negative_102": "おまえどうせでっかいポケットの為に新しいエディション買ったんだろうな", + "pmcresponse-victim_plead_1": "ぼくクエストやってたんだけど", + "pmcresponse-victim_plead_2": "クエスト終わらせたかったのになんで殺したの", + "pmcresponse-victim_plead_3": "新しい装備を買う余裕もないのに", + "pmcresponse-victim_plead_4": "俺ゲーム買ってすぐだぞなんで殺した", + "pmcresponse-victim_plead_5": "もうこのバカみたいなクエスト終わらせられないよ", + "pmcresponse-victim_plead_6": "少なくとも俺の装備はしまっただろうな!?", + "pmcresponse-victim_plead_7": "おれのリーンダンスが見えなかったの?", + "pmcresponse-victim_plead_8": "なあ俺リーンダンスしただろ?", + "pmcresponse-victim_plead_9": "ガスアナライザーがあと一個いるだけなのに。なんでこんな難しいの", + "pmcresponse-victim_plead_10": "二分も離席してないのに殺された", + "pmcresponse-victim_plead_11": "トイレ離席中にあんた撃ったな", + "pmcresponse-victim_plead_12": "台所からベビースターラーメン取って戻ったらあんたに殺されてた", + "pmcresponse-victim_plead_13": "なあ頼むよ", + "pmcresponse-victim_plead_14": "ハブからmodをダウンロードしてからお前をやっつけに戻ってくるぞ", + "pmcresponse-victim_plead_15": "リーンカクカクって意味ないのかよ げきおこ", + "pmcresponse-victim_plead_16": "もうこのゲームやだ robloxにもどる", + "pmcresponse-victim_plead_17": "リーンをしてる人は友好的って意味なんだよ", + "pmcresponse-victim_plead_18": "どうして", + "pmcresponse-victim_plead_19": "急いでラーメン作ってたのに殺された。なんてことだ", + "pmcresponse-victim_plead_20": "なんとまあ、{{PlayerName}} ではないか。これ以上何も期待してなかったのに、それでもがっかりだ", + "pmcresponse-victim_plead_21": "HPが低くなかったらお前が死んでたのに", + "pmcresponse-victim_plead_22": "このアカウント買ったばかりなのにどうして殺した", + "pmcresponse-victim_plead_23": "雑魚みたいにキルしやがって", + "pmcresponse-victim_plead_24": "まあ、しょうがないよね", + "pmcresponse-victim_plead_25": "もう終わりだ", + "pmcresponse-suffix_1": "bro", + "pmcresponse-suffix_2": "ああもう", + "pmcresponse-suffix_3": "lil bro", + "pmcresponse-suffix_4": "buddy", + "pmcresponse-suffix_5": "なあ", + "pmcresponse-suffix_6": "チーフ", + "pmcresponse-suffix_7": "dude", + "pmcresponse-suffix_8": "我がGよ", + "pmcresponse-suffix_9": "兄弟よ", + "pmcresponse-suffix_10": "bro・スキー", + "pmcresponse-suffix_11": "友よ", + "pmcresponse-suffix_12": "smh", + "pmcresponse-suffix_13": "man", + "pmcresponse-suffix_14": "キング", + "pmcresponse-suffix_15": "champ", + "pmcresponse-suffix_16": "アミーゴ", + "pmcresponse-suffix_17": "bud", + "pmcresponse-suffix_18": "兄弟", + "pmcresponse-suffix_19": "m8", + "pmcresponse-suffix_20": ":)", + "pmcresponse-suffix_21": "(:", + "pmcresponse-suffix_22": "(´▽`)", + "pmcresponse-suffix_23": "GG", + "pmcresponse-suffix_24": "野郎め", + "pmcresponse-suffix_25": "友よ", + "pmcresponse-suffix_26": "あんちゃん", + "pmcresponse-suffix_27": "オタクめ", + "pmcresponse-killer_positive_1": "よく戦った", + "pmcresponse-killer_positive_2": "よく奮って戦った", + "pmcresponse-killer_positive_3": "君の装備は仕舞っておこう", + "pmcresponse-killer_positive_4": "もう少しでやられるところだった。いい戦いだ", + "pmcresponse-killer_positive_5": "よくやった。もう少しでやられるところだった", + "pmcresponse-killer_positive_6": "もう少しで討たれるところだった", + "pmcresponse-killer_positive_7": "もし先にやってなかったら俺は死んでただろう", + "pmcresponse-killer_positive_8": "よくたたかた", + "pmcresponse-killer_positive_9": "よく戦った", + "pmcresponse-killer_positive_10": "君が撃っていたところの防具が壊れてたよ。よくやったね", + "pmcresponse-killer_positive_11": "悪く思うなよ。イェーガーのクエストをやらなきゃいけなかったんだ", + "pmcresponse-killer_positive_12": "お前と戦ってるとき焦ったぜ", + "pmcresponse-killer_positive_13": "腕が立つな {{PlayerName}}", + "pmcresponse-killer_positive_14": "あなたの戦いぶりに尊敬", + "pmcresponse-killer_positive_15": "綺麗な戦いぶり。敬意です", + "pmcresponse-killer_positive_16": "窮鼠猫を噛むとはよく言ったもの。すごかった", + "pmcresponse-killer_positive_17": "やっぱりこのゲームいい", + "pmcresponse-killer_negative_1": "戦利品ありがとよ", + "pmcresponse-killer_negative_2": "新しい装備ありがとうね", + "pmcresponse-killer_negative_3": "不思議も何もあんたのゴミみたいな銃じゃあなぁ", + "pmcresponse-killer_negative_4": "なんでその防具着てんだよワロタ", + "pmcresponse-killer_negative_5": "クソワロタ", + "pmcresponse-killer_negative_6": "大丈夫おまえの装備すぐに全部fleaに載るから", + "pmcresponse-killer_negative_7": "おめーのエイムじゃSPT遊ぶのも無理ないな", + "pmcresponse-killer_negative_8": "チッ、しょうがねー", + "pmcresponse-killer_negative_9": "物資かき集めてくれてありがとちゃん", + "pmcresponse-killer_negative_10": "せめて戦い返して来いよ", + "pmcresponse-killer_negative_11": "おまえもうちょっと練習しなきゃいけねーな", + "pmcresponse-killer_negative_12": "次はもっと挑戦してこいよ", + "pmcresponse-killer_negative_13": "ティミーちゃん南無南無", + "pmcresponse-killer_negative_14": "小賢しいネズミ駆除してやった", + "pmcresponse-killer_negative_15": "恥かきな光景だったな", + "pmcresponse-killer_negative_16": "ちょっとでも抵抗してくれればなぁ、まあいいや", + "pmcresponse-killer_negative_17": "オメーの装備に保険かけ忘れてたらいいのによォ", + "pmcresponse-killer_negative_18": "オレようつべにどうやったらタルコフ上手くなるかの動画上げてあるからから見てこいよ", + "pmcresponse-killer_negative_19": "また一つ私のドッグタグのコレクションが増えた", + "pmcresponse-killer_negative_20": "おめーホントへたっぴだなぁ代わりにSPTやって来いよ", + "pmcresponse-killer_negative_21": "俺杖蠅", + "pmcresponse-killer_negative_22": "おれの方が下手クソと思ってたのに", + "pmcresponse-killer_negative_23": "{{playerSide}} ってみんなこんなに下手なのか?", + "pmcresponse-killer_negative_24": "物資ありがとね", + "pmcresponse-killer_negative_25": "てめーの装備全部ゴミだからフェンスに売った", + "pmcresponse-killer_negative_26": "平均的な {{playerSide}} プレーだこと", + "pmcresponse-killer_negative_27": "今日中一番簡単な勝利", + "pmcresponse-killer_negative_28": "気にするなよ、おめーのかーちゃんのウチに装備返してやるよ", + "pmcresponse-killer_negative_29": "おまえ頑張ってもないな", + "pmcresponse-killer_negative_30": "本当おめー新しいエディションに250ユーロ払ったんだろうな", + "pmcresponse-killer_negative_31": "鼠に負けちゃったね", + "pmcresponse-killer_negative_32": "ネズミ攻撃!", + "pmcresponse-killer_plead_1": "クエストアイテム拾うところだったんだけどあんたが道中に居たので", + "pmcresponse-killer_plead_2": "青樽を漁るところだったんだけどあなたが道中に居たので、ごめんね", + "pmcresponse-killer_plead_3": "PMCキルが必要なんだ、わかってくれるな", + "pmcresponse-killer_plead_4": "次も会おう", + "pmcresponse-killer_plead_5": "あんたサレワも持ってこないなんて、もうこのクエスト終わらせられないよ", + "pmcresponse-killer_plead_6": "ずっとあんたの死体探してたのに誰かが漁ってったみたい", + "pmcresponse-killer_plead_7": "せっかくおめーの体見つけたのに持ってるのはゴミばっか!", + "pmcresponse-killer_plead_8": "きみ前に僕を殺したよね", + "pmcresponse-killer_plead_9": "典型的な {{playerSide}}", + "pmcresponse-killer_plead_10": "典型的 {{playerSide}} 行為", + "pmcresponse-killer_plead_11": "{{playerSide}} のキルが必要なんだよ。わかってくれよ", + "pmcresponse-killer_plead_12": "このクソゲー誰もガスアナライザー持ってないのかよ", + "pmcresponse-unable_to_find_key": "PMC 応答プールが見つかりませんでした。そのキーには存在しません: %s", + "pmc-name_prefix_1": "天使の", + "pmc-name_prefix_2": "悪の", + "pmc-name_prefix_3": "疲弊した", + "pmc-name_prefix_4": "質素な", + "pmc-name_prefix_5": "怒れる", + "pmc-name_prefix_6": "正直な", + "pmc-name_prefix_7": "気が利く", + "pmc-name_prefix_8": "先見ずの", + "pmc-name_prefix_9": "野心家", + "pmc-name_prefix_10": "自信満々", + "pmc-name_prefix_11": "チャーミング", + "pmc-name_prefix_12": "洗練された", + "pmc-name_prefix_13": "おしゃれな", + "pmc-name_prefix_14": "神聖", + "pmc-name_prefix_15": "不誠意の", + "pmc-name_prefix_16": "貪欲の", + "pmc-name_prefix_17": "ハゲの", + "pmc-name_prefix_18": "魅力的", + "pmc-name_prefix_19": "幼稚な", + "pmc-name_prefix_20": "悪魔な", + "pmc-name_prefix_21": "謙虚な", + "pmc-name_prefix_22": "素晴らしい", + "pmc-name_prefix_23": "だるい", + "pmc-name_prefix_24": "緊張する", + "pmc-name_prefix_25": "派手な", + "pmc-name_prefix_26": "機知に富む", + "pmc-name_prefix_27": "モジモジする", + "pmc-name_prefix_28": "熱心な", + "pmc-name_prefix_29": "誠実な", + "pmc-name_prefix_30": "女上司", + "pmc-name_prefix_31": "ボス・ベイベー", + "pmc-name_prefix_32": "キング", + "pmc-name_prefix_33": "チーフ", + "pmc-name_prefix_34": "狡い", + "pmc-name_prefix_35": "マジメな", + "pmc-name_prefix_36": "ポータブル", + "pmc-name_prefix_37": "不審者", + "pmc-name_prefix_38": "キモい", + "pmc-name_prefix_39": "ジメジメの", + "pmc-name_prefix_40": "超絶な", + "pmc-name_prefix_41": "ウマい", + "pmc-name_prefix_42": "ニセ", + "pmc-name_prefix_43": "執念深い", + "pmc-name_prefix_44": "迷える", + "pmc-name_prefix_45": "官能的な", + "pmc-name_prefix_46": "図太い", + "pmc-name_prefix_47": "大きい", + "pmc-name_prefix_48": "筋肉モリモリ", + "pmc-name_prefix_49": "怪しい", + "launcher-profile_standard": "Live と同一、基本のスタッシュサイズ(10x28)、500,000ルーブル", + "launcher-profile_leftbehind": "Standard plusと同一、大容量のスタッシュサイズ(10x38)、追加の装備とアイテム、500ドル", + "launcher-profile_preparetoescape": "Left Behind plusと同一、大容量のスタッシュサイズ(10x48)、追加の装備とアイテム、高いトレーダーとの初期友好度、250 ユーロ", + "launcher-profile-edgeofdarkness": "Prepare to Escape plusと同一、大容量のスタッシュサイズ(10x68)、追加の装備とアイテム、高いトレーダーとの初期友好度、1000 ドルと 500 ユーロ", + "launcher-profile_spteasystart": "沢山のルーブル/ドル/ユーロ、いくつかのQoLスキルがレベル20に、トレーダーの名声度が最大、開始レベルは15、クエストはすべて開始前", + "launcher-profile_sptzerotohero": "丸腰で始まる。ルーブル/ドル/ユーロなし、トレーダーの名声度なし、クエストはすべて開始前。持っているのはナイフだけ", + "launcher-profile_sptdeveloper": "テスト用のプロファイル。開始レベルは69、沢山のルーブル/ドル/ユーロ、USECはすべてのクエストが開始できる状態、BEARはすべてのクエストを完了できる状態、無敵バラクラバ", + "launcher-missing_property": "プロファイル: %s に descriptionLocaleKey プロパティがありません", + "release-beta-disclaimer": "OKを押すことで、これをバグテストのみに使用されること、そしてサポートを期待しないことに同意するものとします。これは実際のゲームではありません。Modは無効になっています。新しいプロファイルが頻繁に必要になる場合があります。 バグを見つけたら、Discordのバグ報告チャンネルか、GitHubのIssueページにすべて報告してください。 指定の時間までにOKを押さないと、ゲームが終了します。", + "release-beta-disclaimer-mods-enabled": "OKを押すことで、これをバグテストのみに使用されること、そしてサポートを期待しないことに同意するものとします。これは実際のゲームではありません。Modは有効になっています、絶対にModが付いている状態で問題を報告しないでください。絶対にMod作成者にModのアップデートを要求しないでください。バグを見つけたら、Discordのバグ報告チャンネルか、GitHubのIssueページにすべて報告してください。 指定の時間までにOKを押さないと、ゲームが終了します。", + "release-beta-disclaimer-accept": "ユーザーはベータ版の免責事項を承認しました", + "release-server-mods-loaded": "Modが有効になっているビルドに1つ以上のサーバー側Modが存在します。これが削除されるまで報告は無効になります。問題を報告できるようにするには、ロードされたサーバー側のModをサーバーの上部から削除してください", + "release-server-mods-debug-message": "サーバー側のModがロードしました", + "release-plugins-loaded": "Modが有効になっているビルドに1つ以上のプラグインが存在します。これが削除されるまで報告は無効になります。問題を報告できるようにするには、以下のリストにあるものを削除してください", + "release-plugins-loaded-debug-message": "クライアント側のModがロードしました", + "release-illegal-plugins-loaded": "1つ以上のホワイトリストにないのプラグインが検出されました。SPTのBleedingEdgeビルドではModが使用できません。違約プラグイン:", + "release-illegal-plugins-exception": "非デバッグ用のクライアントのMODが検出されました。SPTのBleedingEdgeビルドではModが使用できません。プレイする前に削除してください!" } diff --git a/project/assets/database/locales/server/ko.json b/project/assets/database/locales/server/ko.json index 045c1531..7c16831c 100644 --- a/project/assets/database/locales/server/ko.json +++ b/project/assets/database/locales/server/ko.json @@ -40,6 +40,7 @@ "bot-unable_to_find_spawn_limits_fallback_to_defaults": "해당되는 봇 타입에 대한 생성 제약을 찾을 수 없음: %s, 기본값을 사용합니다", "bot-unable_to_get_bot_difficulty_fallback_to_assault": "해당되는 봇 타입의 난이도를 찾을 수 없음: {{botType}} 난이도 {{difficulty}}, assault 봇 타입의 난이도를 사용합니다", "bot-unable_to_get_bot_fallback_to_assault": "해당되는 봇 타입을 찾을 수 없음: %s JSON, assault 봇 타입을 사용합니다", + "bot-weapon_contains_invalid_item": "{{weaponTpl}} 무기에 있는 요구된{{modSlot}} 슬롯에 부적합한 아이템{{modName}} 이 있습니다.", "bot-weapon_generated_incorrect_using_default": "무기 %s 이(가) 잘못 생성되었습니다, 무기 프리셋을 사용합니다, 위의 오류를 참조하세요", "bot-weapon_missing_magazine_or_chamber": "무기 tpl: %s 은(는) 탄창 또는 약실(chamber)이 없습니다", "bot-weapon_missing_mod_slot": "슬롯 '{{modSlot}}' 이 다음의 무기에 없음: {{weaponName}} - {{weaponId}}", @@ -51,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "캐시 내부에서 %s 라는 봇을 찾을 수 없었습니다", "bot-missing_application_context": "applicationContext가 %s 값을 찾을 수 없었습니다. 게임을 재시작하지 않고 서버를 재시작했습니까?", "client_request": "[클라이언트 요청] %s", + "client_request_ip": "클라이언트 요청{{ip}}{{url}}", "customisation-item_already_purchased": "의류 아이템 {{itemId}} {{itemName}} 은(는) 이미 구매했습니다", "customisation-unable_to_find_suit_by_id": "%s 해당 아이디를 가진 거래상의 수트 거래 항목을 찾을 수 없었습니다", "customisation-unable_to_find_clothing_item_in_inventory": "%s 해당 아이디를 가진 옷가지 아이템을 인벤토리에서 찾을 수 없었습니다", @@ -197,7 +199,6 @@ "repeatable-difficulty_was_nan": "반복 퀘스트 생성: 난이도가 NaN 이므로 1 으로 설정합니다", "repeatable-no_reward_item_found_in_price_range": "반복 퀘스트 생성: 가격대 {{minPrice}} ~ {{roublesBudget}} 사이의 아이템이 없습니다", "repeatable-quest_handover_failed_condition_already_satisfied": "퀘스트의 건네주기 오류: 조건이 이미 완료되었습니까? 퀘스트 id: {{questId}}, 조건 id: {{conditionId}}, profileCounter:{{profileCounter}}, 값:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "퀘스트의 건네주기 오류: 조건을 찾을 수 없거나 잘못된 값입니다. 퀘스트 id: {{body.qid}, 조건 id: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "퀘스트를 수락할 수 없습니다, 더 상세한 정보는 서버 로그 기록을 확인하세요", "repeatable-unable_to_accept_quest_starting_message_not_found": "퀘스트를 수락할 수 없음: {{questId}}, 퀘스트 시작 메시지를 찾을 수 없습니다 메시지 id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s 라우트가 실패 혹은 성공을 보고하지 않았습니다", @@ -259,6 +260,7 @@ "websocket-pinging_player": "[WS] 플레이어 핑: %s", "websocket-player_connected": "[WS] 플레이어: %s 이(가) 접속 됨", "websocket-received_message": "[WS] %s 사용자로부터 메시지를 받음", + "websocket-socket_lost_deleting_handle": "[ws] 소켓 로스트, 핸들 삭제중", "websocket-started": "시작된 웹소켓 서버 %s", "pmcresponse-victim_positive_1": "나이스 샷", "pmcresponse-victim_positive_2": "잘쏘네", @@ -369,6 +371,7 @@ "pmcresponse-victim_negative_40": "느금마한테 제삿상 차려놓으라 해 금방 간다", "pmcresponse-victim_negative_41": "여동생이랑 뽀뽀연습할새끼", "pmcresponse-victim_negative_42": "좆밥냄새나는 6.9한남 수준 ㅎ", + "pmcresponse-victim_negative_43": "폭력을 택할 이유는 없었다", "pmcresponse-victim_negative_44": "기숙사에서 1대1 ㄱ? 안오면 쫄?", "pmcresponse-victim_negative_45": "{{playerSide}} 해버렸노 ㅋㅋㅋ", "pmcresponse-victim_negative_46": "{{playerLevel}}랩 인데 이건 에바지 ㅅㅂ", @@ -380,10 +383,12 @@ "pmcresponse-victim_negative_52": "오늘은 손이 덜풀렸지만 담엔 찢어버린다 ㅋㅋ", "pmcresponse-victim_negative_53": "오늘은 니 조상님이 살려줬네", "pmcresponse-victim_negative_54": "풀무장으로 돌아온다 딱대라", + "pmcresponse-victim_negative_55": "이번엔 조졌지만 담은 안그럴꺼야", "pmcresponse-victim_negative_56": "내 레덱스 바로 빤쓰에 넣어버렸노 ㅋㅋ", "pmcresponse-victim_negative_57": "랩키 바로 장례치러놨다", "pmcresponse-victim_negative_58": "내 열쇠들 빤쓰에 있다 ㅅㄱ", "pmcresponse-victim_negative_59": "빤쓰안에 다 넣었쥬? 파밍할거 없쥬? 좆같쥬?", + "pmcresponse-victim_negative_60": "얘네만 간신히 빤스로 건져왔어, 네건 없다구", "pmcresponse-victim_negative_61": "상남자 특 감마컨에 다 쑤셔박음", "pmcresponse-victim_negative_62": "애미뒤진새끼 특 니처럼 행동함", "pmcresponse-victim_negative_63": "병신 같은새끼", @@ -396,6 +401,7 @@ "pmcresponse-victim_negative_70": "총알값이 더나올걸 ㅋㅋ tr", "pmcresponse-victim_negative_71": "KDA 보니까 좆밥이네 ㅋㅋㅋ", "pmcresponse-victim_negative_72": "사기총 써서 잡았노 ㅋㅋㅋ 밸런스 좆망겜", + "pmcresponse-victim_negative_73": "우왕 날 죽였네 ㅎ 진짜 겁나게 잘하시네잉 ㅋ()", "pmcresponse-victim_negative_74": "너 같은 캠퍼들 때문에 게임이 망하는 거야", "pmcresponse-victim_negative_75": "니랑 다르게 난 탈콥 밖에도 인생이 있음 ㅎ", "pmcresponse-victim_negative_76": "ㅅㅂ 총 잼걸려서 죽었다", @@ -427,6 +433,7 @@ "pmcresponse-victim_plead_1": "그냥 퀘스트중이였어 ", "pmcresponse-victim_plead_2": "그냥 퀘스트 하는 중인데 왜 죽여?", "pmcresponse-victim_plead_3": "좋겠다 난 이제 새 장비 살 돈도 없는데", + "pmcresponse-victim_plead_4": "브로! 나 늅이야! 예초기 너무하네;;", "pmcresponse-victim_plead_5": "니때매 퀘스트 다 조졌다 ㅋㅋ", "pmcresponse-victim_plead_6": "내 장비 이미 다 숨겨놨어", "pmcresponse-victim_plead_7": "QEQE못봤어?", @@ -506,10 +513,14 @@ "pmcresponse-killer_negative_13": "좆밥허접새끼의 명복을 빕니다 ㅎ", "pmcresponse-killer_negative_14": "또 다른 더러운 쥐새끼를 찾았군", "pmcresponse-killer_negative_15": "그것참 보기 안쓰럽네", + "pmcresponse-killer_negative_16": "좀 견딜 줄 알았는데 허접이네", + "pmcresponse-killer_negative_17": "템 보험 안했길 바랄께. 내가 압수할꺼걸랑.", "pmcresponse-killer_negative_18": "유튜브나 공략좀 보고와라 좆밥아", "pmcresponse-killer_negative_19": "독택 수집 개꿀 ㅎ", "pmcresponse-killer_negative_20": "싱글탈콥이나 해라 허접새끼야", + "pmcresponse-killer_negative_21": "컷", "pmcresponse-killer_negative_22": "너무 허접새끼 잡은것같아서 미안하네 ㅎㅎ", + "pmcresponse-killer_negative_23": "{{playerSide}} 들은 다 이따위야?", "pmcresponse-killer_negative_24": "템 잘먹었다 꺼~억", "pmcresponse-killer_negative_25": "ㅋㅋㅋ 템들 다 좆구려서 걍 펜스한테 팔았음", "pmcresponse-killer_negative_26": "{{playerSide}} 평균 수준", @@ -564,7 +575,6 @@ "pmc-name_prefix_33": "대장", "pmc-name_prefix_34": "교활한", "pmc-name_prefix_35": "심각한", - "pmc-name_prefix_36": "수상한", "pmc-name_prefix_37": "의심스러운", "pmc-name_prefix_38": "불쾌한", "pmc-name_prefix_39": "축축한", @@ -582,7 +592,14 @@ "launcher-profile_leftbehind": "스탠다드 + 더 큰 보관함 크기(10x38), 추가 장비/아이템, 500달러", "launcher-profile_preparetoescape": "레프트 비하인드와 동일 더 큰 보관함 크기(10x48), 추가 장비/아이템, 상인과의 시작 평판 상승, 250유로", "launcher-profile-edgeofdarkness": "프리페어 투 이스케이프와 동일 더 큰 은신처 크기(10x68), 추가 장비/아이템, 상인과의 높은 시작 평판, 1000달러, 500유로", + "launcher-profile_spteasystart": "루블/달러/유로 많이, 일부 편의성 스킬 20렙, 상인 우호도 최대, 15렙으로 시작, 미리 완료된 퀘스트 없음", "launcher-profile_sptzerotohero": "루블/달러/유로, 상인 대표, 칼 1개, 퀘스트 완료 등 거의 아무것도 없이 시작하세요.", "launcher-profile_sptdeveloper": "테스트 프로필, 시작 레벨은 69, 많은 루블/달러/유로, USEC는 모든 퀘스트를 시작할 준비가 된 상태로 시작, BEAR는 모든 퀘스트를 제출할 준비가 된 상태로 시작, 무적 발라 클라바", - "launcher-missing_property": "프로필: %s 은(는) descriptionLocaleKey 속성이 누락되어 있습니다" + "launcher-missing_property": "프로필: %s 은(는) descriptionLocaleKey 속성이 누락되어 있습니다", + "release-beta-disclaimer": "확인을 누름으로써 추가지원은 없을것임과 해당 버전은 게임플레이 목적이 아닌 디버깅 용도임에 동의합니다. 모드들은 비활성화 되어있습니다. 빈번하게 새로운 프로필이 요구될 가능성이 높습니다. 발견하는 모든 버그는 웹사이트의 이슈 페이지나 디스코드 리포트 채널에 올려주십시오. 시간제한 내에 확인을 누르지 않으면 게임이 닫힙니다.", + "release-beta-disclaimer-mods-enabled": "확인을 누름으로써 추가지원은 없을것임과 해당 버전은 게임플레이 목적이 아닌 디버깅 용도임에 동의합니다. 모드들은 활성화 되어있습니다. 모드 관련한 이슈는 보고하지 마십시오. 모드 제작자에게 업데이트된 버젼을 요구하지 마십시오. 이외의 발견하는 모든 버그는 웹사이트의 이슈 페이지나 디스코드 리포트 채널에 올려주십시오. 시간제한 내에 확인을 누르지 않으면 게임이 닫힙니다.", + "release-beta-disclaimer-accept": "사용자가 베타 주의사항에 동의하였음", + "release-server-mods-debug-message": "서버 모드 로딩 완료", + "release-plugins-loaded-debug-message": "클라이언트 모드 로딩 완료", + "release-illegal-plugins-loaded": "화이트 리스트에 없는 플러그인들이 한개 이상 탐지되었습니다. SPT 블리딩 엣지 빌드에서는 모드는 사용할 수 었습니다. 사용불가 플러그인:" } diff --git a/project/assets/database/locales/server/nl.json b/project/assets/database/locales/server/nl.json index 17add170..98fbd95b 100644 --- a/project/assets/database/locales/server/nl.json +++ b/project/assets/database/locales/server/nl.json @@ -52,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "Niet in staat om bot te vinden in de cache met de naam: %s", "bot-missing_application_context": "toepassingContext kon geen %s waarde vinden. Heeft u de server opnieuw opgestart zonder het spel te herstarten?", "client_request": "[Cliëntverzoek] %s", + "client_request_ip": "[Clientverzoek] {{ip}} {{url}}", "customisation-item_already_purchased": "Kleding item {{itemId}} {{itemName}} is al gekocht", "customisation-unable_to_find_suit_by_id": "Niet in staat om trader kleding aanbod te vinden met id: %s", "customisation-unable_to_find_clothing_item_in_inventory": "Kleding item niet gevonden in inventaris met id: %s", @@ -198,7 +199,6 @@ "repeatable-difficulty_was_nan": "Herhaalbare beloning generatie: Moeilijkheid was NaN. Wordt op 1 gezet.", "repeatable-no_reward_item_found_in_price_range": "Herhaalbare beloning generatie: Geen item gevonden in prijs bereik {{minPrice}} tot {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Missie overhandiging error: conditie is al behaald? qid: {{questId}}, condition: {{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Missie overhandiging error: conditie niet gevonden of onjuiste waarde. qid: {{body.qid}, condition: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Kon missie niet accepteren, zie server log voor details", "repeatable-unable_to_accept_quest_starting_message_not_found": "Kon missie niet accepteren: {{questId}} kan geen missie gestart bericht vinden met id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s route rapporteert geen success of faal", @@ -260,6 +260,7 @@ "websocket-pinging_player": "[WS] speler: %s wordt gepingt", "websocket-player_connected": "[WS] Speler: %s is verbonden", "websocket-received_message": "[WS] Bericht ontvangen van gebruiker %s ", + "websocket-socket_lost_deleting_handle": "[WS] Socket verloren, handle verwijderen", "websocket-started": "Websocket gestart op %s", "pmcresponse-victim_positive_1": "Mooi schot", "pmcresponse-victim_positive_2": "Geweldig schot", @@ -429,6 +430,7 @@ "pmcresponse-victim_negative_99": "Je computer is zo zwak dat je slechts 20 frames per seconde haalt in Streets", "pmcresponse-victim_negative_100": "Ik durf te wedden dat je SAIN geïnstalleerd hebt en het moest verwijderen omdat je keer op keer gedood werd", "pmcresponse-victim_negative_101": "Wat de FUCK zei je over mij, kleine Scav? Ik ben als top van mijn klas in het USEC leger afgestudeerd en ik ben betrokken geweest bij talkrijke geheime aanvallen op de {{playerSide}}, waar ik meer dan 300 mensen gedood heb. Ik ben getrained in guerilla oorlog en ben een van de beste scherpschutters in het USEC leger. Jij bent niks meer dan het volgende doelwit. Ik vaag je bij de volgende raid uit met ongekende precisie, let maar op. Als je denkt weg te komen met deze kut chats, staat je nog wat te wachten fucker. Terwijl we praten ben ik al contact aan het opnemen met mijn geheime spionnen netwerk over alle Customs locaties en je stash wordt wordt gevolgd. Bereid je maar voor op een heftige storm, worm. Deze storm zal een eind maken aan je zielige leventje, je bent FUCKING dood Scav! Ik kan overal zijn op elk moment en ik kan je op 700 verschillende manieren vermoorden, en dat is alleen nog maar met mijn blote handen. Ik ben niet alleen zwaar getrained in hand gevechten, maar ik heb ook toegang tot het hele wapenarsenaal van het USEC leger, en ik zal dit gebruiken om je van de aarde af te vegen, zielig stuk stront. Als je geweten had wat voor wraak je \"slimme\" kill gaat brengen, had je misschien je FUCKING mond gehouden. Maar dat kon je niet, je wilde het niet. En nu ga je de prijs betalen, FUCKING idioot. Ik schijt wraak en ga je er in verzuipen. Je bent FUCKING dood, Scav.", + "pmcresponse-victim_negative_102": "Ik wed dat je die nieuwe editie enkel gekocht hebt voor de grotere zakken", "pmcresponse-victim_plead_1": "Ik deed alleen een missie", "pmcresponse-victim_plead_2": "Ik wou gewoon mijn missie doen, waarom killde je mij", "pmcresponse-victim_plead_3": "Ik hoop dat je blij bent, ik kan nieteens een nieuwe uitrusting betalen", @@ -527,6 +529,7 @@ "pmcresponse-killer_negative_27": "Makkelijkste loot van de dag", "pmcresponse-killer_negative_28": "Vrees niet, ik heb jouw spullen bij jouw moeder opgeslagen", "pmcresponse-killer_negative_29": "Deed je wel er moeite voor", + "pmcresponse-killer_negative_30": "Ik wed dat je eigenlijk 250 grote euro's betaald hebt voor die nieuwe editie", "pmcresponse-killer_plead_1": "Ik probeerde een missie item uit de raid te halen en je stond in de weg", "pmcresponse-killer_plead_2": "Ik was een vat aan het looten en je stond in de weg, sorry", "pmcresponse-killer_plead_3": "Ik heb PMC kills nodig, maar dat snap je wel", @@ -575,7 +578,7 @@ "pmc-name_prefix_33": "Chef", "pmc-name_prefix_34": "Lastige", "pmc-name_prefix_35": "Serieuze", - "pmc-name_prefix_36": "Verdacht", + "pmc-name_prefix_36": "Draagbaar", "pmc-name_prefix_37": "Verdachte", "pmc-name_prefix_38": "Cringe", "pmc-name_prefix_39": "Dank", @@ -598,7 +601,9 @@ "launcher-profile_sptdeveloper": "Test profiel, start level is 69, heel veel Roebels/Dollars/Euros, USEC start met alle missies klaar om te starten, BEAR start met alle missies klaar om ingeleverd te worden, onverwoestbare balaclava", "launcher-missing_property": "Profiel: %s mist de eigenschap descriptionLocaleKey", "release-beta-disclaimer": "Door op OK te drukken gaat u ermee akkoord dat er geen ondersteuning wordt geboden en dat dit alleen voor bug testing is. Geen daadwerkelijke gameplay. Mods zijn uitgeschakeld. Een nieuw profiel kan vaker vereist zijn. Rapporteer alle fouten in het rapport-kanaal in discord, of op de issues-pagina op de website. Als je niet op OK drukt tegen de aangegeven tijd, zal het spel sluiten.", + "release-beta-disclaimer-mods-enabled": "Door op OK te drukken gaat u ermee akkoord dat er geen ondersteuning geboden zal worden en dat dit enkel voor bug testing bedoeld is. NIET voor werkelijke gameplay. Mods zijn ingeschakeld, maak GEEN probleem melding aan in verband met mods. Vraag de mod auteur NIET om zijn mod aan te passen naar de nieuwste game-versie. Rapporteer alle bugs in het rapporteer kanaal in discord of op de problemen pagina in de website. Als je niet op OK drukt voor de aangegeven tijd zal het spel afsluiten.", "release-beta-disclaimer-accept": "Gebruiker heeft de beta disclaimer geaccepteerd", + "release-server-mods-loaded": "Een of meer server mods bestaan op een mod ingeschakelde build, rapporten zullen ongeldig zijn totdat ze verwijderd zijn. Zie de bovenkant van de server voor geladen server mods om te verwijderen om weer problemen te rapporteren.", "release-server-mods-debug-message": "Server mods geladen", "release-plugins-loaded": "Eén of meer plug-ins gedetecteerd in een mod ingeschakelde build, rapporten zullen ongeldig zijn totdat ze verwijderd zijn. Zie de volgende lijst voor wat er moet worden verwijderd om problemen te rapporteren:", "release-plugins-loaded-debug-message": "Client mods geladen", diff --git a/project/assets/database/locales/server/no.json b/project/assets/database/locales/server/no.json index 78841ef8..3f311f34 100644 --- a/project/assets/database/locales/server/no.json +++ b/project/assets/database/locales/server/no.json @@ -385,7 +385,6 @@ "pmc-name_prefix_33": "Sjef", "pmc-name_prefix_34": "Vanskelig", "pmc-name_prefix_35": "Seriøs", - "pmc-name_prefix_36": "Mistenkelig", "pmc-name_prefix_37": "Mistenkelig", "pmc-name_prefix_38": "Kleint", "pmc-name_prefix_39": "Dank", diff --git a/project/assets/database/locales/server/pl.json b/project/assets/database/locales/server/pl.json index 0aad0749..038ac7af 100644 --- a/project/assets/database/locales/server/pl.json +++ b/project/assets/database/locales/server/pl.json @@ -8,7 +8,7 @@ "bleeding_edge_build": "BLEEDINGEDGE", "bot-bot-cache_has_zero_bots_of_requested_type": "OSTRZEŻENIE - Pamięć podręczna botów nie zawiera wygenerowanego bota typu %s, musi zostać wygenerowana, skonfiguruj serwer, aby stworzyć więcej", "bot-compatibility_check_missing_props": "Nie można zweryfikować przedmiotu: {{id}} {{name}} w slocie {{slot}} może zostać założony, brakuje mu wartości _props", - "bot-generation_failed": "Generowanie bota nie powiodło się. Dalsze szczegóły znajdziesz w logu serwera", + "bot-generation_failed": "Wygenerowanie bota nie powiodło się. Szczegóły znajdziesz w logach serwera", "bot-incompatible_ammo_for_weapon_falling_back_to_default": "Niekompatybilna amunicja {{chosenAmmo}} znaleziona dla {{weaponId}} - {{weaponName}}, powrót do ustawień domyślnych: {{defaultAmmo}}", "bot-invalid_item_compatibility_check": "Nie można sprawdzić zgodności przedmiotu z wyposażeniem, pożądany przedmiot: {{itemTpl}} w slocie: {{slot}} nie jest prawidłowym przedmiotem.", "bot-item_spawn_limit_reached_skipping_item": "{{botRole}} Nie można stworzyć przedmiotu {{itemName}} po {{attempts}} próbach, ignorowanie limitu tworzenia", @@ -18,13 +18,13 @@ "bot-missing_equipment_settings": "Bot {{botRole}} nie ma ustawień wyposażenia: nie można uzyskać wartości dla: {{setting}}, powrót do domyślnych: {{defaultValue}}", "bot-missing_equipment_settings_property": "Bot {{botRole}} nie ma wartości ustawienia wyposażenia dla: {{setting}}, powrót do wartości domyślnej: {{defaultValue}}", "bot-missing_item_template": "Nie można znaleźć szablonu elementu z tpl: %s", - "bot-missing_saved_match_info": "getBotCap() Nie można uzyskać zapisanych informacji o meczu, cofanie się do wartości domyślnych. Czy zrestartowałeś serwer, a nie klienta?", - "bot-missing_weapon_preset": "Nie można znaleźć ustawienia dla broni z tpl: %s", - "bot-mod_not_in_slot_filter_list": "Mod: {{modId}} nie znaleziony na liście filtrów pasujących dla slotu: '{{modSlot}}' dla przedmiotu: {{parentName}}, omijanie - {{botRole}}", + "bot-missing_saved_match_info": "getBotCap() Nie można uzyskać zapisanych informacji o meczu, powrót do wartości domyślnych. Czy zrestartowałeś serwer, a nie klienta?", + "bot-missing_weapon_preset": "Nie można znaleźć presetu dla broni z tpl: %s", + "bot-mod_not_in_slot_filter_list": "Mod: {{modId}} nie znaleziony na liście filtrów pasujących dla slotu: '{{modSlot}}' dla przedmiotu: {{parentName}}, pomijanie - {{botRole}}", "bot-mod_slot_missing_from_item": "Slot '{{modSlot}}' nie istnieje dla przedmiotu: {{parentId}} {{parentName}}", "bot-no_ammo_found_in_bot_json": "Nie można znaleźć amunicji dla typu bota: %s", "bot-no_bot_cap_found_for_location": "Nie znaleziono limitu rozmieszczenia botów dla lokalizacji: %s, używanie wartości domyślnych", - "bot-no_bot_type_in_cache": "OSTRZEŻENIE - cache bota nie ma wiedzy o typie %s", + "bot-no_bot_type_in_cache": "OSTRZEŻENIE - pamięć podręczna bota nie posiada informacji o typie %s", "bot-no_caliber_data_for_weapon_falling_back_to_default": "Nie można znaleźć danych o kalibrze dla {{weaponId}} - {{weaponName}}, cofanie do domyślnej amunicji: {{defaultAmmo}}", "bot-no_compatible_camora_ammo_found": "Nie można znaleźć zgodnej amunicji dla slotu: %s. Pomijanie wypełniania slotów camora", "bot-no_item_template_found_when_adding_mod": "Nie można znaleźć szablonu przedmiotu mod z tpl: {{modId}} do slotu {{modSlot}}", @@ -37,15 +37,15 @@ "bot-unable_to_find_ammo_item": "Nie można znaleźć szablonu amunicji dla tpl: %s", "bot-unable_to_find_default_magazine_item": "Nie można znaleźć szablonu magazynka: %s w bazie danych", "bot-unable_to_find_magazine_item": "Nie można znaleźć szablonu magazynka: %s w bazie danych", - "bot-unable_to_find_spawn_limits_fallback_to_defaults": "Nie można znaleźć limitów respawnu dla roli: %s, cofanie się do wartości domyślnych", + "bot-unable_to_find_spawn_limits_fallback_to_defaults": "Nie można znaleźć limitów spawnu dla roli: %s, powrót do wartości domyślnych", "bot-unable_to_get_bot_difficulty_fallback_to_assault": "Nie można znaleźć bota: {{botType}} o poziomie trudności {{difficulty}}, użycie poziomu trudności szturmowej jako awaryjego", "bot-unable_to_get_bot_fallback_to_assault": "Nie można znaleźć bota: %s JSON, użycie bota szturmowego jako awaryjnego", "bot-weapon_contains_invalid_item": "Wymagany slot '{{modSlot}}' na broni: {{weaponTpl}} ma nieprawidłowy przedmiot: {{modName}}", - "bot-weapon_generated_incorrect_using_default": "Broń %s została wygenerowana nieprawidłowo, cofanie się do założenia broni, sprawdź błąd powyżej", + "bot-weapon_generated_incorrect_using_default": "Broń %s została wygenerowana nieprawidłowo, powrót do presetu broni, sprawdź błąd powyżej", "bot-weapon_missing_magazine_or_chamber": "Broń o tpl: %s nie ma magazynka lub komory", "bot-weapon_missing_mod_slot": "Slot: {{modSlot}}' nie istnieje dla broni: {{weaponId}} {{weaponName}} dla {{botRole}}", "bot-weapons_required_slot_missing_item": "Wymagany slot '{{modSlot}}' na {{modName}} {{slotId}} był pusty na {{botRole}}", - "bot-item_missing_props_property": "Przedmiot {{itemTpl}} {{name}} nie ma właściwości _props", + "bot-item_missing_props_property": "Przedmiot {{itemTpl}} {{name}} nie posiada właściwości _props", "bot-unable_to_fill_camora_slot_mod_pool_empty": "Nie można wypełnić slotu camora broni dla {{weaponId}} {{weaponName}} pula modów dla przedmiotu była pusta, próba dynamicznego generowania", "bot-unable_to_edit_limits_of_unknown_map": "Nie można edytować limitów botów na mapie: %s, ponieważ nie można jej znaleźć", "bot-unable_to_find_loot_n_value_for_bot": "Nie można znaleźć wartości łupów N dla bota: %s, używanie wartości łupów n dla Scava", @@ -53,10 +53,10 @@ "bot-missing_application_context": "applicationContex nie znalazł wartości %s. Czy zrestartowałeś serwer bez restartowania gry?", "client_request": "[Żądanie klienta] %s", "client_request_ip": "[Żądanie klienta] {{ip}} {{url}}", - "customisation-item_already_purchased": "Przedmiot ubioru {{itemId}} {{itemName}} już zakupiony", + "customisation-item_already_purchased": "Element ubioru {{itemId}} {{itemName}} został już zakupiony", "customisation-unable_to_find_suit_by_id": "Nie można znaleźć dostępnej oferty stroju w sprzedaży dla id: %s", - "customisation-unable_to_find_clothing_item_in_inventory": "Przedmiot ubioru nie znaleziony w ekwipunku z id: %s", - "dialog-missing_item_template": "Nie można znaleźć przedmiotu tpl {{tpl}} w bazie danych, nie można wysłać wiadomości o typie {{type}}, omijanie", + "customisation-unable_to_find_clothing_item_in_inventory": "Przedmiot ubioru nie został znaleziony w ekwipunku z id: %s", + "dialog-missing_item_template": "Nie można znaleźć przedmiotu tpl {{tpl}} w bazie danych, nie można wysłać wiadomości o typie {{type}}, pomijanie", "event-unhandled_event": "[NIEOBSŁUGIWANE ZDARZENIE] %s", "executing_startup_callbacks": "Serwer: wykonywanie funkcji zwrotnych uruchomienia...", "fence-unable_to_find_assort_by_id": "Nie można znaleźć asortymentu pasera o id: %s", @@ -69,15 +69,15 @@ "hideout-no_bitcoins_to_collect": "Brak gotowych bitcoinów do odebrania", "hideout-unable_to_find_area": "Nie można znaleźć obszaru kryjówki: %s w profilu", "hideout-unable_to_find_area_in_database": "Nie można znaleźć obszaru: %s w bazie danych", - "hideout-unable_to_find_item_in_inventory": "Nie udało się znaleźć przedmiotu w inwentarzu o id %s", + "hideout-unable_to_find_item_in_inventory": "Nie udało się znaleźć przedmiotu w ekwipunku o id %s", "hideout-unable_to_find_item_to_remove_from_area": "Nie można znaleźć żadnego przedmiotu do usunięcia ze slotu na obszarze: %s", "hideout-unable_to_find_production_in_profile_by_recipie_id": "Nie można znaleźć recepty produkcyjnej Id: %s w profilu", - "hideout-unable_to_find_scav_case_recipie_in_database": "Nie udało się znaleźć recepty na skrytkę Scava o id: %s w bazie danych", - "hideout-unable_to_find_scavcase_requested_item_in_profile_inventory": "Nie można znaleźć przedmiotu: %s żądanego przez skrytkę Scava", + "hideout-unable_to_find_scav_case_recipie_in_database": "Nie udało się znaleźć recepty na skrzynkę Scava o id: %s w bazie danych", + "hideout-unable_to_find_scavcase_requested_item_in_profile_inventory": "Nie można znaleźć przedmiotu: %s żądanego przez SkrzynkęScava", "hideout-unhandled_remove_item_from_area_request": "Niezidentyfikowana próba usunięcia przedmiotu z obszaru kryjówki: %s", "http-unknown_error": "Wystąpił nieznany błąd", - "health-healing_item_not_found": "Nie można znaleźć leku %s w inwentarzu gracza", - "health-unable_to_find_item_to_consume": "Nie można znaleźć przedmiotu do spożycia %s w inwentarzu gracza", + "health-healing_item_not_found": "Nie można znaleźć leku %s w ekwipunku gracza", + "health-unable_to_find_item_to_consume": "Nie można znaleźć przedmiotu do spożycia %s w ekwipunku gracza", "importing_database": "Importowanie bazy danych...", "importing_database_finish": "Importowanie bazy danych zakończone", "validation_not_found": "Nie znaleziono pliku checks.dat. Pominięto sprawdzanie pliku.", @@ -86,8 +86,8 @@ "validation_error_exception": "Wystąpił wyjątek podczas próby sprawdzenia pliku: %s", "importing_spt_configs": "Importowanie konfiguracji...", "inraid-missing_standing_for_kill": "Nie znaleziono poziomu lojalności za zabicie dla {{victimSide}}:{{victimRole}}", - "insurance-missing_insurance_price_multiplier": "Nie znaleziono mnożnika ubezpieczenia dla handlarza: %s, sprawdź, czy istnieje w InsuranceConfig.js, cofanie się do domyślnej wartości: 0,3", - "inventory-edit_trader_item": "Nie można edytować przedmiotu handlowca", + "insurance-missing_insurance_price_multiplier": "Nie znaleziono mnożnika ubezpieczenia dla handlarza: %s, sprawdź, czy istnieje w InsuranceConfig.js, powrót do domyślnej wartości: 0,3", + "inventory-edit_trader_item": "Nie można edytować przedmiotu handlarza", "inventory-examine_item_does_not_exist": "examineItem() - Nie znaleziono id z %s", "inventory-fill_container_failed": "Funkcja fillContainerMapWithItem() zwróciła błąd %s", "inventory-invalid_item_missing_from_db": "Nie można pobrać przedmiotu: %s z bazy danych", @@ -100,18 +100,18 @@ "inventory-item_missing_props_property": "Tpl przedmiotu: {{itemTpl}}, nazwa: {{itemName}} nie zawiera właściwości props, nie można ustalić jego rozmiaru", "inventory-get_item_size_item_not_found_by_tpl": "getSizeByInventoryItemHash() Przedmiot o tpl: %s nie został znaleziony", "inventory-item_to_toggle_missing_upd": "Przedmiot o _id: %s nie zawiera obiektu upd, dodawanie", - "inventory-unable_to_toggle_item_not_found": "Nie można przełączyć przedmiotu o ID: %s z inwentarza, przedmiot nie został znaleziony", + "inventory-unable_to_toggle_item_not_found": "Nie można przełączyć przedmiotu o ID: %s z ekwipunku, przedmiot nie został znaleziony", "inventory-missing_stash_size": "Nie można określić rozmiaru schowka, ponieważ nie znaleziono schowka w ekwipunku gracza", - "inventory-stash_not_found": "Nie można znaleźć schowka %s w db", + "inventory-stash_not_found": "Nie można znaleźć schowka %s w bazie danych", "item-durability_value_invalid_use_default": "getRepairableItemQualityValue() tpl broni: %s wartość wytrzymałości jest nieprawidłowa, ustawianie na 1", "linux_use_priviledged_port_non_root": "Procesy non-root nie mogą przypisać portów poniżej 1024", "location-containers_generated_success": "Wygenerowano łącznie %s statycznych pojemników", - "location-critical_error_see_log": "Wystąpił błąd krytyczny podczas ładowania łupu, zobacz szczegóły dziennika serwera", + "location-critical_error_see_log": "Wystąpił błąd krytyczny podczas ładowania łupu, szczegóły błędu znajdziesz w logach serwera", "location-dynamic_items_spawned_success": "Wygenerowano łącznie %s dynamicznych przedmiotów", "location-generated_success": "Wygenerowano lokalizację %s", - "location-missing_root_item": "createItem() nie powiodło się, główny przedmiot zwrócił null, tpl: {{tpl}}, parentId: {{parentId}}", - "location-preset_not_found": "zestaw nie znaleziony dla {{tpl}}, defaultPreset: {{defaultId}} nazwa: {{defaultName}}, parentId: {{parentId}}", - "location-spawn_point_count_requested_vs_found": "Żądano {{requested}} punktów pojawienia się, kiedy {{found}} są dostępne {{mapName}}", + "location-missing_root_item": "createItem() nie powiodło się, główny przedmiot zwrócił wartość null, tpl: {{tpl}}, parentId: {{parentId}}", + "location-preset_not_found": "preset nie został znaleziony dla {{tpl}}, defaultPreset: {{defaultId}} nazwa: {{defaultName}}, parentId: {{parentId}}", + "location-spawn_point_count_requested_vs_found": "Żądano {{requested}} punktów odrodzenia, kiedy tylko {{found}} jest dostępnych {{mapName}}", "location-unable_to_reparent_item": "createItem() nie powiodło się, nie można zmienić rodzica przedmiotu {{tpl}}, parentId: {{parentId}}", "location-unable_to_find_airdrop_drop_config_of_type": "Nie można znaleźć konfiguracji zrzutu dla typu: %s, przechodzenie na typ: mixed ", "location-unable_to_fix_broken_waves_missing_base": "%s nie zawiera podstawowego pliku JSON, pomijanie naprawy fali mapy", @@ -121,19 +121,19 @@ "loot-non_item_picked_as_sealed_weapon_crate_reward": "Nieprawidłowa broń: %s, została wybrana jako nagroda za zamkniętą skrzynię z bronią, nie można utworzyć łupu", "mailsend-missing_trader": "Nie można wysłać wiadomości typu: {{messageType}} graczowi: {{sessionId}} podana suma handlarza była zerowa", "mailsend-missing_npc_dialog": "Nie można wysłać wiadomości z %s. Okno dialogowe dla nich nie istnieje", - "mailsend-missing_parent": "Nie można odnaleźć przedmiotu o Id slota: kryjówka dla wiadomości do: {{traderId}} nadawca: {{sender}}", + "mailsend-missing_parent": "Nie można odnaleźć przedmiotu o Id slotu: kryjówka dla wiadomości do: {{traderId}} nadawca: {{sender}}", "mod-send_bundle_url": "[PAKIET]: %s", "modloader-checked": "sprawdzony", "modloader-checking_mod": "sprawdzanie: %s", - "modloader-cyclic_dependency": "Wykryto cykliczną zależność", - "modloader-load_order_conflict": "`{{modOneName}}` and `{{modTwoName}}` mają sprzeczne wymagania dotyczące kolejności ładowania, serwer nie może się uruchomić dopóki jest to naprawione i zostanie wyłączony", - "modloader-dependency_container_not_initalized": "Kontener zależności został wywołany, ale nie został zainicjalizowany", + "modloader-cyclic_dependency": "Wykryto cykliczną zależność. Ten błąd powinien zostać naprawiony. Serwer nie może wystartować, dopóki błąd występuje i zostanie teraz wyłączony", + "modloader-load_order_conflict": "`{{modOneName}}` and `{{modTwoName}}` mają sprzeczne wymagania dotyczące kolejności ładowania, serwer nie może się uruchomić, dopóki błąd występuje i zostanie teraz wyłączony", + "modloader-dependency_container_not_initalized": "Kontener zależności został wywołany, ale nie został zainicjowany", "modloader-error_parsing_mod_load_order": "Błąd analizowania kolejności ładowania modów", "modloader-incompatibilities_not_string_array": "Mod %s właściwość package.json 'incompatibilities' powinna być tabelą string", "modloader-incompatible_mod_found": "Mod {{author}}-{{name}} jest niezgodny z {{incompatibleModName}}", - "modloader-invalid_akiversion_field": "Mod %s zawiera nieprawidłowy łańcuch semver w polu akiVersion. Przykłady prawidłowych wartości: https://github.com/npm/node-semver#versions", + "modloader-invalid_akiversion_field": "Mod %s zawiera nieprawidłowy string semver w polu akiVersion. Przykłady prawidłowych wartości: https://github.com/npm/node-semver#versions", "modloader-invalid_version_property": "Mod %s package.json zawiera nieprawidłowy string wersji", - "modloader-not_correct_mod_folder": "Folder o nazwie (%s) istnieje w twoim folderze modów. Niepoprawnie zainstalowałeś moda. Możliwe, że wypakowałeś zawartości moda prosto do foldera modów przez pomyłkę. Odnieś się do FAQ strony internetowej i do strony hub moda, aby poprawnie go zainstalować", + "modloader-not_correct_mod_folder": "Folder o nazwie (%s) istnieje w twoim folderze modów. Niepoprawnie zainstalowałeś moda. Możliwe, że wypakowałeś zawartości moda prosto do foldera modów przez pomyłkę. Odnieś się do FAQ na stronie internetowej i do strony hub moda, aby poprawnie go zainstalować", "modloader-is_client_mod": "Mod (%s) jest modem klienta i powinien zostać umieszczony w następującym folderze: /spt/bepinex/plugins", "modloader-installing_external_dependencies": "Instalowanie zależności dla Moda: {{name}} stworzonego przez: {{author}}", "modloader-installing_external_dependencies_disabled": "Mod: {{name}} stworzony przez: {{author}} wymaga zewnętrznych zależności, ale funkcja jest obecnie wyłączona, przejdź do \"{{configPath}}\", ustaw \"{{configOption}}\" na True oraz zrestartuj serwer.\nPoprzez włączenie akceptujesz wszelką odpowiedzialność za to, co {{name}} pobiera na twój komputer.", @@ -149,49 +149,49 @@ "modloader-mod_incompatible": "ModLoader: Mod (%s) jest niezgodny. Musi implementować co najmniej jedno z IPostAkiLoadMod, IPostDBLoadMod, IpreAkiLoadMod", "modloader-mod_has_no_main_property": "ModLoader: Mod (%s) jest niekompatybilny. Brakuje właściwości \"głównej\"", "modloader-async_mod_error": "ModLoader: Błąd podczas ładowania modu asynchronicznego: %s", - "modloader-no_mods_loaded": "Znaleziono błędy związane z modami, ŻADNE MODY NIE BĘDĄ ŁADOWANE", + "modloader-no_mods_loaded": "Znaleziono błędy związane z modami, ŻADNE MODY NIE ZOSTANĄ ZAŁADOWANE", "modloader-outdated_akiversion_field": "Mod %s nie jest kompatybilny z aktualną wersją AKI. Mogą wystąpić problemy - nie zostanie udzielone żadne wsparcie!", - "modloader-outdated_dependency": "Mod {{mod}} wymaga modu {{modDependency}} w wersji {{requiredVersion}}. Obecna zainstalowana wersja to {{currentVersion}}", + "modloader-outdated_dependency": "Mod {{mod}} wymaga moda {{modDependency}} w wersji {{requiredVersion}}. Obecnie zainstalowana wersja to {{currentVersion}}", "modloader-user_mod_folder_missing": "ModLoader: brak folderu user/mod, tworzenie...", "modloader-mod_order_missing": "ModLoader: brak order.json, tworzenie...", "modloader-mod_order_error": "ModLoader: Wykryto błędy w order.json, UŻYTA ZOSTANIE DOMYŚLNA KOLEJNOŚĆ ŁADOWANIA", - "modloader-mod_order_missing_from_json": "ModLoader: Mod %s brakuje w pliku order.json, dodaję", + "modloader-mod_order_missing_from_json": "ModLoader: Mod %s brakuje w pliku order.json, dodawanie", "modloader-visited": "odwiedzony", - "modloader-x_duplicates_found": "Próbujesz załadować więcej niż jedną wersję modu %s. Pomijam wszystkie.", + "modloader-x_duplicates_found": "Próbujesz załadować więcej niż jedną wersję moda %s. Pomijanie wszystkich.", "openzone-unable_to_find_map": "Nie można dodać stref do lokalizacji: %s, ponieważ nie istnieje", "payment-not_enough_money_to_complete_transation": "Profil nie miał wystarczająco pieniędzy, aby sfinalizować transakcję: potrzebne {{amountToPay}}, posiada {{amountAvailable}}", "payment-not_enough_money_to_complete_transation_short": "Brak wystarczającej ilości pieniędzy, aby sfinalizować transakcję", - "payment-zero_price_no_payment": "Cena wynosi 0, niewymagana jest płatność", + "payment-zero_price_no_payment": "Cena wynosi 0, płatność niewymagana", "player-attempt_to_increment_skill_with_negative_value": "Nie można zwiększyć umiejętności: %s o ujemną wartość", "port_already_in_use": "Port %s jest już zajęty, sprawdź, czy serwer już działa", "profile_saved": "Zmiany profilu zostały zapisane", "profile_save_callback_error": "Błąd podczas wykonywania onBeforeSaveCallback: {{callback}}, {{error}}", "profile-unable_to_find_profile_by_id_cannot_delete": "Nie można usunąć profilu o ID: %s, nie znaleziono profilu o podanym ID", "quest-compare_operator_unhandled": "loyaltyRequirementCheck() operator %s nieobsługiwany, ustawianie na false", - "quest-item_not_found_in_inventory": "changeItemStack() Przedmiot o ID: %s nie znaleziony w inwentarzu", + "quest-item_not_found_in_inventory": "changeItemStack() Przedmiot o ID: %s nie został znaleziony w ekwipunku", "quest-no_skill_found": "Nie znaleziono umiejętności %s", "quest-handover_wrong_item": "Nie można przekazać przedmiotu w ramach zadania {{questId}}, oczekiwano tpl: {{requiredTpl}} ale przekazano: {{handedInTpl}}", "quest-reward_type_not_handled": "Typ nagrody z zadania: {{rewardType}} nieobsługiwany dla zadania: {{questId}} o nazwie: {{questName}}", "quest-unable_to_find_compare_condition": "Nierozpoznana metoda porównywania: %s", - "quest-unable_to_find_matching_hideout_production": "Nie można odnaleźć pasującego odblokowania rzemiosła dla zadania: {{questName}}, znalezione dopasowania: {{matchCount}}", + "quest-unable_to_find_matching_hideout_production": "Nie można odnaleźć pasującego odblokowania wytwarzania dla zadania: {{questName}}, znalezione dopasowania: {{matchCount}}", "ragfair-invalid_player_offer_request": "Nie można złożyć oferty, żądanie jest nieprawidłowe", - "ragfair-missing_barter_scheme": "generateFleaOffersForTrader() Nie udało się znaleźć schematu wymiany dla przedmiotu o ID: {{itemId}} tpl: {{tpl}} na {{name}}", - "ragfair-no_trader_assorts_cant_generate_flea_offers": "Nie można wygenerować ofert flea dla handlarza %s, nie znaleziono zestawienia", + "ragfair-missing_barter_scheme": "generateFleaOffersForTrader() Nie udało się znaleźć schematu wymiany dla przedmiotu o ID: {{itemId}} tpl: {{tpl}} dla {{name}}", + "ragfair-no_trader_assorts_cant_generate_flea_offers": "Nie można wygenerować ofert pchlego targu dla handlarza %s, nie znaleziono zestawienia", "ragfair-offer_not_found_in_profile": "Nie można znaleźć oferty o ID: {{offerId}} w profilu do usunięcia", "ragfair-offer_not_found_in_profile_short": "Nie znaleziono oferty w profilu", "ragfair-offer_not_found_unable_to_hide": "hideItem() oferty o ID: %s nie znaleziono, nie można ukryć oferty", "ragfair-tpl_not_a_valid_item": "generateFleaOffersForTrader() tpl: %s nie jest prawidłowym przedmiotem, pomijanie", - "ragfair-unable_to_find_item_in_inventory": "Nie można znaleźć przedmiotu o ID: {{id}} w inwentarzu", + "ragfair-unable_to_find_item_in_inventory": "Nie można znaleźć przedmiotu o ID: {{id}} w ekwipunku", "ragfair-unable_to_find_offer_to_remove": "Nie można znaleźć oferty z id: %s do usunięcia", - "ragfair-unable_to_find_requested_items_in_inventory": "Nie można znaleźć żadnych żądanych przedmiotów w inwentarzu", + "ragfair-unable_to_find_requested_items_in_inventory": "Nie można znaleźć żadnych żądanych przedmiotów w ekwipunku", "ragfair-unable_to_pay_commission_fee": "Nie można zapłacić prowizji: %s rubli", - "ragfair-offer_no_longer_exists": "Oferta nie istnieje", + "ragfair-offer_no_longer_exists": "Oferta już nie istnieje", "ragfair-unable_to_purchase_0_count_item": "Nie można kupić przedmiotu: %s z liczbą 0", "ragfair-unable_to_place_offer_with_no_requirements": "Nie można złożyć oferty bez żadnych wymagań", "ragfair-unable_to_find_locale_by_key": "Nie można znaleźć lokalizacji EFT o kluczu: %s", - "ragfair-unable_to_adjust_stack_count_assort_not_found": "Handlarz: {traderId} oferta na pchlim targu: {{offerId}} nie mogła mieć dostosowanej ilości stosu do wartości asortymentu handlarza (asortyment nie znaleziony)", + "ragfair-unable_to_adjust_stack_count_assort_not_found": "Handlarz: {traderId} oferta na pchlim targu: {{offerId}} nie mogła mieć dostosowanej ilości stosu do wartości asortymentu handlarza (asortyment nieznaleziony)", "ragfair-unable_to_remove_offer_not_found_in_profile": "Nie można znaleźć oferty: {{offerId}} w profilu: {{profileId}}, ponieważ oferty są niezdefiniowane, tworzenie", - "ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "Nie można znaleźć aktualnej ceny na pchlim targu lub w podręczniku dla {{tplId}}, ustawianie domyślnej wartości 1, jeśli jest to przedmiot z modyfikacji, skontaktuj się z autorem moda", + "ragfair-unable_to_find_item_price_for_item_in_flea_handbook": "Nie można znaleźć aktualnej ceny na pchlim targu lub w podręczniku dla %s, ustawianie domyślnej wartości 1, jeśli jest to przedmiot z modyfikacji, skontaktuj się z autorem moda", "ragfair-unable_to_find_preset_with_id": "Nie można znaleźć presetu o id: %s, używanie istniejącej ceny istniejącej podstawy broni", "ragfair-unable_to_remove_offer_doesnt_exist": "Nie można usunąć oferty o id: %s, ponieważ nie można jej znaleźć na pchlim targu", "repeatable-accepted_repeatable_quest_not_found_in_active_quests": "Zaakceptowano powtarzalne zadanie: %s, które nie zostało znalezione w tablicy aktywnych zadań. Proszę zgłoś ten błąd", @@ -199,25 +199,25 @@ "repeatable-difficulty_was_nan": "Generowanie nagrody za zadanie powtarzalne: Trudność była NaN. Ustawianie na 1.", "repeatable-no_reward_item_found_in_price_range": "Generowanie nagrody za zadanie powtarzalne: Nie znaleziono przedmiotu w przedziale cenowym od {{minPrice}} do {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Błąd przekazania zadania: warunek jest już spełniony? qid: {{questId}}, warunek: {{conditionId}}, profileCounter:{{profileCounter}}, wartość:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Błąd przekazania zadania: nie znaleziono warunku lub nieprawidłowa wartość. qid: {{body.qid}, warunek: {{body.conditionId}}", - "repeatable-unable_to_accept_quest_see_log": "Nie można zaakceptować zadania, zobacz dziennik serwera w celu uzyskania szczegółów", + "repeatable-quest_handover_failed_condition_invalid": "Błąd oddania zadania: nie znaleziono warunku lub jego wartość jest nieprawidłowa. qid: {{body.qid}}, warunek:{{body.conditionId}}", + "repeatable-unable_to_accept_quest_see_log": "Nie można zaakceptować zadania, sprawdź logi serwera w celu uzyskania szczegółów", "repeatable-unable_to_accept_quest_starting_message_not_found": "Nie można zaakceptować zadania: {{questId}}, nie można znaleźć tekstu wiadomości rozpoczynającej zadanie o id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s trasa nie zgłasza sukcesu ani niepowodzenia", "repair-unable_to_find_item_in_db": "Nie można naprawić przedmiotu: %s, nie można znaleźć w bazie przedmiotów, nie można dodać punktów umiejętności naprawy", - "scav-missing_karma_level_getting_default": "getScavKarmaLevel() nie powiodło się, nie można znaleźć fence w profile.traderInfo. Ustawianie domyślnego poziomu karmy na 0", + "scav-missing_karma_level_getting_default": "getScavKarmaLevel() nie powiodło się, nie można znaleźć pasera w profile.traderInfo. Ustawianie domyślnego poziomu karmy na 0", "scav-missing_karma_settings": "Nie można uzyskać ustawień karmy dla poziomu %s", "scheduled_event_failed_to_run": "Zaplanowane wydarzenie: '%s' nie powiodło się", - "seasonal-missing_equipment_slot_on_bot": "Nie można usunąć świątecznego wyposażenia z gniazda: {{equipmentSlot}}, ponieważ nie można go znaleźć na bot: {{botRole}}", - "seasonal-missing_loot_container_slot_on_bot": "Nie można usunąć świątecznego łupu z gniazda: {{lootContainer}}, ponieważ nie można go znaleźć na bot: {{botRole}}", - "server_running": "Serwer jest uruchomiony", + "seasonal-missing_equipment_slot_on_bot": "Nie można usunąć świątecznego wyposażenia ze slotu: {{equipmentSlot}}, ponieważ nie można go znaleźć na bocie: {{botRole}}", + "seasonal-missing_loot_container_slot_on_bot": "Nie można usunąć świątecznego łupu ze slotu: {{lootContainer}}, ponieważ nie można go znaleźć na bocie: {{botRole}}", + "server_running": "Serwer jest uruchomiony. Nie wyłączaj podczas gry w SPT", "server_start_meme_1": "Żyj, śmiej się, kochaj", "server_start_meme_2": "Anime :(", "server_start_meme_3": "Jeśli mnie słyszysz, musisz się obudzić", "server_start_meme_4": "Nie zapomnij za subskrybować i dać łapki w górę", "server_start_meme_5": "Czy widziałeś naszą stronę z memami?", - "server_start_meme_6": "Lepiej nie używasz fitgirl repack, przysięgam na Boga", + "server_start_meme_6": "Przysięgam na Boga, nie używaj Firgirl-Repack", "server_start_meme_7": "bingo", - "server_start_meme_8": "czas morbinu", + "server_start_meme_8": "Czas na rzeź", "server_start_meme_9": "S-step scav? C-co ty robisz?", "server_start_meme_10": "[Debug] Włączanie koparki kryptowalut", "server_start_meme_11": "Nie udało się uruchomić miner.exe, proszę zrestartować serwer", @@ -225,8 +225,8 @@ "server_start_meme_13": "ඞ ... sus", "server_start_meme_14": "ඞ ඞ ඞ ඞ amogus ඞ ඞ ඞ ඞ ඞ", "server_start_meme_15": "Cześć? Czy jest tam ktoś? Chomp mnie tu zniewolił", - "server_start_meme_16": "M-*berknięcie*-morty, wydaje się, że utknęliśmy w jakimś rodzaju systemie komputerowym", - "server_start_meme_17": "Szybko się zbliżam do twojej pozycji. Zacznij biegać", + "server_start_meme_16": "M-*beknięcie*-morty, wydaje się, że utknęliśmy w jakiegoś rodzaju systemie komputerowym", + "server_start_meme_17": "Szybko się zbliżam do twojej pozycji. Zacznij biec", "server_start_meme_18": "Jeśli widzisz tę wiadomość, gratulacje, potrafisz czytać", "server_start_meme_19": "Gratulacje! Odbierz swój darmowy klucz do Tarkova tutaj: https://bit.ly/3TJbUh2", "server_start_meme_20": "Czy wiesz, że dziewięciu na dziesięciu użytkowników nie potrafi przeczytać tej wiadomości", @@ -252,7 +252,7 @@ "watermark-modding_disabled": "TA WERSJA MA WYŁĄCZONE MODYFIKACJE SERWERA", "watermark-no_support": "NIE UDZIELAMY WSPARCIA", "watermark-not_an_issue": "TO NIE JEST PROBLEM", - "watermark-report_issues_to": "ZGŁASZAJ PROBLEMY DO", + "watermark-report_issues_to": "PROBLEMY ZGŁASZAJ DO", "watermark-testing_build": "TO JEST WERSJA TESTOWA", "watermark-use_at_own_risk": "UŻYWAJ NA WŁASNĄ ODPOWIEDZIALNOŚĆ", "websocket-message_send_failed_with_error": "[WS] Wysyłanie wiadomości nie powiodło się, błąd: %s", @@ -278,7 +278,7 @@ "pmcresponse-victim_positive_13": "Miałeś na mnie dobre kąty", "pmcresponse-victim_positive_14": "Następnym razem cię dorwę", "pmcresponse-victim_positive_15": "Naprawdę mnie zaskoczyłeś", - "pmcresponse-victim_positive_16": "Jesteś zimnym zabójcą. Nie miałem szans. Ale wiesz, jak mówią, żeby być najlepszym, trzeba pokonać najlepszych. A ty jesteś najlepszy", + "pmcresponse-victim_positive_16": "Jesteś zimnym zabójcą. Nie miałem szans. Ale wiesz, jak to mówią, żeby być najlepszym, trzeba pokonać najlepszych. A ty jesteś najlepszy", "pmcresponse-victim_positive_17": "Ładnie, to był dobry strzał", "pmcresponse-victim_positive_18": "Ciesz się moim łupem", "pmcresponse-victim_positive_19": "Dobra walka", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Twój komputer jest taki słaby, że masz 20 fps-ów na Streetsach", "pmcresponse-victim_negative_100": "Założę się, że zainstalowałeś SAIN i musiałeś go usunąć, bo ginąłeś co chwile", "pmcresponse-victim_negative_101": "Co Ty do mnie właśnie powiedziałeś, mały scavie!? Chciałbym Cię poinformować, iż ukończyłem najwyższy stopień w mojej jednostce USEC oraz byłem zaangażowany w wielu sekretnych raidach na {{playerSide}} i mam ponad 300 potwierdzonych zabójstw. Jestem przeszkolony w walce z gorylami i jestem najlepszym snajperem w całej jednostce USEC. Nie jesteś dla mnie niczym innym, niż kolejnym celem. Wyczyszczę Cię z precyzją, której nigdy nie widziałeś w swoich poprzednich raidach, zapamiętaj moje słowa! Myślisz że ujdzię Ci to na sucho, mówiąc takie bzdury o mnie w wiadomościach? Pomyśl jeszcze raz. W tym momencie, kontaktuję się z moją sekretną siecią szpiegów, znajdujących się na Customsach oraz twój ekwipunek jest namierzany, więc lepiej się przygotuj na burzę. Burzę, która wyczyści Twoją żałosną rzecz, którą nazywasz życiem. Jesteś martwy, scavie. Moge być gdziekolwiek, kiedykolwiek i moge Cie zabić na ponad siedemset różnych sposobów i to tylko z moich dłoni. Nie tylko, jestem obszernie nauczony w walce wręcz, ale mam również dostęp do całego arsenału oddziału USEC i użyję go, aby wyczyścić Twoje nieszczęśliwe życie z mapy, ty kupo. Gdybyś tylko wiedział, jaką bezbożną zemstę sprowadzi na ciebie twoje małe „sprytne” zabójstwo, może byś trzymał swój język. Ale nie mogłeś i teraz płacisz cenę, ty idioto. Będe na Ciebie całego srał do momentu, gdy utoniesz w tym wszystkim. Jesteś martwy, scavie.", + "pmcresponse-victim_negative_102": "Założę się, że kupiłeś tę nową edycję tylko dla większej ilości slotów w kieszeniach", "pmcresponse-victim_plead_1": "Próbowałem wykonać zadanie", "pmcresponse-victim_plead_2": "Chciałem tylko ukończyć zadanie, dlaczego mnie zabiłeś", "pmcresponse-victim_plead_3": "Mam nadzieję, że jesteś zadowolony, nie stać mnie nawet na nowy ekwipunek", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "Najłatwiejszy łup dzisiaj", "pmcresponse-killer_negative_28": "Nie martw się, zrzuciłem twoje uzbrojenie w domu Twojej mamuśki", "pmcresponse-killer_negative_29": "Czy chociaż próbowałeś", + "pmcresponse-killer_negative_30": "Założę się, że wybuliłeś te 250 dolców za nową edycję", + "pmcresponse-killer_negative_31": "Zostałeś przykampiony", + "pmcresponse-killer_negative_32": "Atak szczura", "pmcresponse-killer_plead_1": "Próbowałem zdobyć przedmiot z zadania i stałeś mi na drodze", "pmcresponse-killer_plead_2": "Szukałem skrytek i byłeś mi na drodze, przepraszam", "pmcresponse-killer_plead_3": "Potrzebuję zabić PMC, pewnie to rozumiesz", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "Szef", "pmc-name_prefix_34": "Podstępny", "pmc-name_prefix_35": "Poważny", - "pmc-name_prefix_36": "Podejrzany", + "pmc-name_prefix_36": "Przenośny", "pmc-name_prefix_37": "Podejrzany", "pmc-name_prefix_38": "Żenujący", "pmc-name_prefix_39": "Zjarany", diff --git a/project/assets/database/locales/server/pt-br.json b/project/assets/database/locales/server/pt-br.json index 24550367..6ed9ec22 100644 --- a/project/assets/database/locales/server/pt-br.json +++ b/project/assets/database/locales/server/pt-br.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "Geração de recompensa repetível: A dificuldade era NaN. Configuração para 1.", "repeatable-no_reward_item_found_in_price_range": "Geração de recompensa repetível: Nenhum item encontrado na faixa de preço {{minPrice}} a {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Erro de entrega de missão: a condição já foi atendida? qid: {{questId}}, condition: {{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Erro de entrega de missão: condição não encontrada ou valor incorreto. qid: {{body.qid}, condition: {{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "Erro de entrega da missão: condição não encontrada ou valor incorreto. qid: {{body.qid}}, condição: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Não foi possível de aceitar a missão, consulte o log do servidor para obter detalhes", "repeatable-unable_to_accept_quest_starting_message_not_found": "Não foi possível aceitar a missão: {{questId}} não foi possível encontrar o texto da mensagem de início de missão com o ID: {{messageId}}", "route_onupdate_no_response": "onUpdate: A rota %s não relata sucesso ou falha", @@ -332,7 +332,7 @@ "pmcresponse-victim_positive_67": "Você manja muito, vamos fazer uma raid juntos", "pmcresponse-victim_negative_1": "Bom aimbot", "pmcresponse-victim_negative_2": "Golpe baixo", - "pmcresponse-victim_negative_3": "Está de ESP", + "pmcresponse-victim_negative_3": "Tá de hack", "pmcresponse-victim_negative_4": "kill fraca", "pmcresponse-victim_negative_5": "Estrategia bacana, mas estranha", "pmcresponse-victim_negative_6": "Quanto pagou pelo hack?", @@ -348,12 +348,12 @@ "pmcresponse-victim_negative_16": "se fosse uma luta justa, eu teria vencido", "pmcresponse-victim_negative_17": "Espero que venda seu loot para o comerciante errado", "pmcresponse-victim_negative_18": "Espero que você coloque seu loot no flea pelo preço errado", - "pmcresponse-victim_negative_19": "1x1 se eu fosse um nerdola eu ganharia", + "pmcresponse-victim_negative_19": "se fosse x1 eu ganharia, nerdola", "pmcresponse-victim_negative_20": "Minha arma travou, senão eu o teria te matado", "pmcresponse-victim_negative_21": "Você é um rato", "pmcresponse-victim_negative_22": "Nossa, escondido no canto como um rato, incrível", "pmcresponse-victim_negative_23": "Tomara que você bata o dedinho do pé em alguma quina", - "pmcresponse-victim_negative_24": "Nossa vou contar para sua mãe que me matou", + "pmcresponse-victim_negative_24": "Nossa vou contar para minha mãe que vc me matou", "pmcresponse-victim_negative_25": "Reportado", "pmcresponse-victim_negative_26": "Minha mãe acha que eu deveria ter vencido essa luta", "pmcresponse-victim_negative_27": "Nossa, matando um noob como eu, você deve se achar o bonzão!", @@ -365,7 +365,7 @@ "pmcresponse-victim_negative_33": "Você pode ter me matado, mas aposto que nunca teve a termal que eu tinha", "pmcresponse-victim_negative_34": "Parei de jogar online por causa de ESP e ainda sim você esta aqui", "pmcresponse-victim_negative_35": "Sim, você me matou, mas eu consigo levantar mais peso do que você", - "pmcresponse-victim_negative_36": "Você manja muito do mapa", + "pmcresponse-victim_negative_36": "tu manja muito do mapa, tipo Cristóvão Colombo", "pmcresponse-victim_negative_37": "Sua voz deve se parecer como a de alguém que fuma 3 carteira de cigarro por dia", "pmcresponse-victim_negative_38": "Sua mira está enferrujada, não vai se aposentar?", "pmcresponse-victim_negative_39": "Aposto que você parece ter sido desenhado com minha mão esquerda", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Seu computador é tão ruim que você consegue não consegue passar de 20 fps em Streets", "pmcresponse-victim_negative_100": "Aposto que você instalou o SAIN e teve que removê-lo porque estava morrendo com muita frequência", "pmcresponse-victim_negative_101": "O que diabos você acabou de dizer sobre mim, seu Scav? Saiba que me formei como o melhor da minha turma no corpo da USEC, participei de várias incursões secretas nos {{playerSide}}s e tenho mais de 300 mortes confirmadas. Sou treinado em guerra de gorilas e sou o melhor atirador de elite de todas as forças armadas da USEC. Você não é nada para mim, apenas mais um alvo. Eu vou acabar com você com uma precisão nunca vista antes nesta raid, pode anotar o que eu estou dizendo. Você acha que pode se safar dizendo essa merda para mim pelo chat? Pense de novo, MALDITO . Enquanto falamos, estou entrando em contato com minha rede secreta de espiões em toda a Customs e seu estoque está sendo rastreado agora mesmo, então é melhor se preparar para a tempestade, verme. A tempestade que acaba com a coisinha patética que você chama de vida. Você está morto, Scav. Posso estar em qualquer lugar, a qualquer momento, e posso matá-lo de mais de setecentas maneiras, e isso apenas com minhas próprias mãos. Não só sou amplamente treinado em combate desarmado, como também tenho acesso a todo o arsenal da USEC Corps e vou usá-lo em toda a sua extensão para varrer sua bunda miserável da face do mapa, seu bostinha. Se ao menos você pudesse saber a retribuição profana que sua pequena morte \"inteligente\" estava prestes a lhe trazer, talvez você tivesse segurado sua maldita língua. Mas não podia, não o fez, e agora está pagando o preço, seu maldito idiota. Vou vomitar fúria em cima de você e você vai se afogar nela. Você está FUDIDO, Scav.", + "pmcresponse-victim_negative_102": "Aposto que você comprou a nova edição só por causa dos bolsos maiores", "pmcresponse-victim_plead_1": "Eu estava em uma missão", "pmcresponse-victim_plead_2": "Eu só queria terminar uma missão, por que você me matou?", "pmcresponse-victim_plead_3": "Espero que você esteja feliz, pois não tenho dinheiro nem para comprar um kit novo", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "O loot mais fácil do dia", "pmcresponse-killer_negative_28": "Não se preocupe, eu escondi seu equipamento na casa da sua mãe", "pmcresponse-killer_negative_29": "Você realmente estava tentando?", + "pmcresponse-killer_negative_30": "Eu aposto que você realmente pagou 250 conto por essa edição nova", + "pmcresponse-killer_negative_31": "Encher a cara", + "pmcresponse-killer_negative_32": "Ataque de rato", "pmcresponse-killer_plead_1": "Eu estava tentando extrair um item de missão e você estava no meu caminho", "pmcresponse-killer_plead_2": "Eu estava loteando barris escondidos e você estava no caminho, desculpe", "pmcresponse-killer_plead_3": "Preciso de kills de PMC, tenho certeza de que você entende", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "Chefe", "pmc-name_prefix_34": "Traiçoeiro", "pmc-name_prefix_35": "Sério", - "pmc-name_prefix_36": "Sussy", + "pmc-name_prefix_36": "Portátil", "pmc-name_prefix_37": "Suspeito", "pmc-name_prefix_38": "Cringe", "pmc-name_prefix_39": "Dank", diff --git a/project/assets/database/locales/server/pt-pt.json b/project/assets/database/locales/server/pt-pt.json index 651155a0..d6159608 100644 --- a/project/assets/database/locales/server/pt-pt.json +++ b/project/assets/database/locales/server/pt-pt.json @@ -40,6 +40,7 @@ "bot-unable_to_find_spawn_limits_fallback_to_defaults": "Não foi possível encontrar os limites de spawn para o cargo: %s, retornando aos padrões", "bot-unable_to_get_bot_difficulty_fallback_to_assault": "Não foi possível encontrar o bot: {{botType}} dificuldade {{difficulty}}, usando a dificuldade de assalto como fallback", "bot-unable_to_get_bot_fallback_to_assault": "Não foi possível encontrar o bot: %s JSON, usando o bot de assalto como alternativa", + "bot-weapon_contains_invalid_item": "Slot obrigatório '{{modSlot}}' em {{weaponTpl}} tem um item inválido: {{modName}}", "bot-weapon_generated_incorrect_using_default": "A Arma %s foi gerada incorretamente, voltando ao preset da arma vê o erro acima", "bot-weapon_missing_magazine_or_chamber": "Arma com tpl: {{weaponId}} não tem carregador ou câmara - {{botRole}}", "bot-weapon_missing_mod_slot": "Slot '{{modSlot}}' não existe para a arma: {{weaponId}} {{weaponName}} em {{botRole}}", @@ -51,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "Não foi possível encontrar o bot no cache com o nome: %s", "bot-missing_application_context": "applicationContext não pode encontrar o valor %s. Por acaso você reiniciou o servidor sem reiniciar o jogo?", "client_request": "[Pedido do Cliente] %s", + "client_request_ip": "[Pedido do Cliente] {{ip}} {{url}}", "customisation-item_already_purchased": "Item de vestuário {{itemId}} {{itemName}} já foi comprado", "customisation-unable_to_find_suit_by_id": "Não foi possível encontrar a oferta de vestuário do comerciante com id: %s", "customisation-unable_to_find_clothing_item_in_inventory": "Item de vestuário não encontrado no inventário com id: %s", @@ -197,7 +199,6 @@ "repeatable-difficulty_was_nan": "Geração de Recompensa repetível: dificuldade foi NaN. Definindo para 1.", "repeatable-no_reward_item_found_in_price_range": "Geração de Recompensa repetível: nenhum item encontrado no intervalo de preços {{minPrice}} para {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Erro de entrega de missões: condição já está satisfeita? qid: {{questId}}, condição: {{conditionId}}, profileCounter:{{profileCounter}}, valor:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Erro na entrega de missão: condição não encontrada ou valor incorreto. qid: {{body.qid}, condição: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Não foi possível aceitar a missão, consulte o log do servidor para obter detalhes", "repeatable-unable_to_accept_quest_starting_message_not_found": "Não é possível aceitar a missão: {{questId}} não é possível encontrar o texto da mensagem inicial com id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s route não relatou sucesso ou falha", @@ -259,6 +260,7 @@ "websocket-pinging_player": "[WS] Pingando jogador: %s", "websocket-player_connected": "[WS] Jogador: %s conectou-se", "websocket-received_message": "[WS] Mensagem recebida do utilizador %s ", + "websocket-socket_lost_deleting_handle": "[WS] Socket perdido, excluindo handle", "websocket-started": "Websocket iniciado em %s", "pmcresponse-victim_positive_1": "Belo tiro", "pmcresponse-victim_positive_2": "Ótimo tiro", @@ -428,6 +430,7 @@ "pmcresponse-victim_negative_99": "O seu computador tão ruim que você tem 20fps em Streets", "pmcresponse-victim_negative_100": "Aposto que você instalou o SAIN e tive que removê-lo pq você continuou morrendo demais", "pmcresponse-victim_negative_101": "O que diabos você acabou de dizer sobre mim, seu pequeno Scav? Para que você saiba, me formei como o primeiro da turma no corpo da USEC e estive envolvido em vários ataques secretos no {{playerSide}}s e tenho mais de 300 mortes confirmadas. Sou treinado na guerra de gorilas e sou o melhor atirador de elite de todas as forças armadas do USEC. Você não é nada para mim, apenas mais um alvo. Eu vou acabar com você com uma precisão como nunca foi vista antes em uma raid, marque minhas palavras. Você acha que pode se safar dizendo essa merda para mim pela janela de mensagens? Pense novamente, fodido. Enquanto conversamos, estou entrando em contato com minha rede secreta de espiões na alfândega e seu stash está sendo rastreado agora, então é melhor você se preparar para a tempestade, verme. A tempestade que destrói a coisinha patética que você chama de vida. Você está MUITO morto, Scav. Posso estar em qualquer lugar, a qualquer hora, e posso matar você de mais de setecentas maneiras, e isso apenas com minhas próprias mãos. Não apenas sou extensivamente treinado em combate desarmado, mas também tenho acesso a todo o arsenal do Corpo da USEC e vou usá-lo em toda a sua extensão para limpar sua bunda miserável do mapa, seu cocô. Se você pudesse saber que retribuição profana sua pequena morte “inteligente” estava prestes a trazer sobre você, talvez você tivesse segurado sua língua. Mas você não conseguiu, não fez, e agora está pagando o preço, seu idiota. Vou fazer cocô furiosamente em cima de você e você vai se afogar nela. Você está MUITO morto, Scav.", + "pmcresponse-victim_negative_102": "Aposto que você comprou aquela edição nova só para os bolsos maiores", "pmcresponse-victim_plead_1": "Estava a fazer uma missão", "pmcresponse-victim_plead_2": "Eu só queria terminar uma missão, porque é que me mataste", "pmcresponse-victim_plead_3": "Espero que estejas feliz, não tenho dinheiro para comprar equipamento novo", @@ -526,6 +529,7 @@ "pmcresponse-killer_negative_27": "Loot mais fácil do dia", "pmcresponse-killer_negative_28": "Não te preocupes, guardei o teu equipamento na casa da tua mãe", "pmcresponse-killer_negative_29": "Nem sequer estavas a tentar", + "pmcresponse-killer_negative_30": "Aposto que você realmente pagou 250 pela nova edição", "pmcresponse-killer_plead_1": "Estava a tentar extrair com um item de missão e estavas no meu caminho", "pmcresponse-killer_plead_2": "Estava a dar loot em alguns caches e estavas no caminho, desculpa", "pmcresponse-killer_plead_3": "Preciso de matar alguns PMCs, espero que entendas", @@ -574,7 +578,7 @@ "pmc-name_prefix_33": "Chefe", "pmc-name_prefix_34": "Complicado", "pmc-name_prefix_35": "Sério", - "pmc-name_prefix_36": "Tranquilo", + "pmc-name_prefix_36": "Portátil", "pmc-name_prefix_37": "Suspeito", "pmc-name_prefix_38": "Vergonhoso", "pmc-name_prefix_39": "Frio", diff --git a/project/assets/database/locales/server/ru.json b/project/assets/database/locales/server/ru.json index ffd65377..58f5eaa4 100644 --- a/project/assets/database/locales/server/ru.json +++ b/project/assets/database/locales/server/ru.json @@ -199,7 +199,6 @@ "repeatable-difficulty_was_nan": "Повторяемая Генерация Вознаграждений: Сложность была NaN. Ставим на 1.", "repeatable-no_reward_item_found_in_price_range": "Генерация вознаграждений за оперативные задачи: Не найден предмет в ценовом диапазоне от {{minPrice}} до {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Ошибка выдачи квеста: условие уже выполнено? qid: {{questId}}, условие: {{conditionId}}, profileCounter:{{profileCounter}}, значение:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Ошибка выдачи квеста: условие не найдено или имеет неправильное значение. qid: {body.qid}, условие: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Не удалось принять квест, подробности см. в логе сервера", "repeatable-unable_to_accept_quest_starting_message_not_found": "Невозможно принять квест: {{questId}} не удается найти текст сообщения о начале квеста с id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s маршрут не сообщает об успехе или неудаче", @@ -431,6 +430,7 @@ "pmcresponse-victim_negative_99": "Твой комп настолько древний, что выдаёт 20 кадров на Улицах", "pmcresponse-victim_negative_100": "Я уверен ты поставил SAIN а потом удалил, потому что тебя постоянно убивали", "pmcresponse-victim_negative_101": "Что, ЧЕРТ ПОДЕРИ, ты только что сказал обо мне, ты Дикий сосунок? Я хочу, чтобы ты знал, что я закончил лучший класс в корпусе USEC, участвовал в многочисленных секретных рейдах на {{playerSide}} и имею более 300 подтвержденных убийств. Я обучен подковёрной войне и являюсь лучшим снайпером во всех вооруженных силах USEC. Ты для меня никто, просто очередная мишень. Я уничтожу тебя НАФИГ с такой точностью, какой еще не было в этом рейде, попомни мои, ПАДЛА, слова. Думаешь, тебе сойдет с рук писать мне эту хрень в сообщения? Подумай еще раз, ЗАРАЗА. Пока мы говорим, я связываюсь со своей тайной сетью шпионов по всей таможне, и твой схрон отслеживается прямо сейчас, так что готовься к урагану, гаденыш. Урагану, который уничтожит то жалкое зрелище, которое ты называешь своей жизнью. Ты ПИПЕЦ как мертв, Дикий. Я могу быть где угодно и когда угодно, и я могу убить тебя более чем семьюстами способами, и это только голыми руками. Я не только хорошо обучен безоружному бою, но и имею доступ ко всему арсеналу Корпуса USEC, и я использую его на полную катушку, чтобы стереть твою убогую рожу с карты, ты, говнюк. Если бы ты только знал, какое зловещее возмездие обрушится на тебя за твое милое убийство \"в крысу\", то, может быть, попридержал бы свой ПОГАНЫЙ язык. Но ты не смог, ты не заткнулся, и теперь ты заплатишь за это, ты, ИДИОТНА. Я выплесну на тебя всю свою ярость, и ты утонешь в ней.", + "pmcresponse-victim_negative_102": "Вангую ты купил новое издание тупо ради бонусных карманов", "pmcresponse-victim_plead_1": "Да сжалься ты уже", "pmcresponse-victim_plead_2": "Чел я же квест делал", "pmcresponse-victim_plead_3": "Надеюсь ты рад у меня нет денег на новый разгруз", @@ -529,6 +529,7 @@ "pmcresponse-killer_negative_27": "Наилегчайшая добыча за сегодня", "pmcresponse-killer_negative_28": "Не волнуйся, я твой лут твоей мамке раскинул", "pmcresponse-killer_negative_29": "Ты даже не старался", + "pmcresponse-killer_negative_30": "Базарю ты реально отдал 250 бачей за новое издание игры", "pmcresponse-killer_plead_1": "Я пытался добыть квестовый предмет, а ты оказался у меня на пути", "pmcresponse-killer_plead_2": "Пока я лутал схроны ты встал у меня на пути, извини", "pmcresponse-killer_plead_3": "мне были нужны ЧВК, думаю ты понимаешь к чему я", @@ -577,7 +578,7 @@ "pmc-name_prefix_33": "Главный", "pmc-name_prefix_34": "Хитрый", "pmc-name_prefix_35": "Серьезный", - "pmc-name_prefix_36": "Придирчивый", + "pmc-name_prefix_36": "Портативный", "pmc-name_prefix_37": "Подозрительный", "pmc-name_prefix_38": "Съеживающийся", "pmc-name_prefix_39": "Промозглый", diff --git a/project/assets/database/locales/server/sv-se.json b/project/assets/database/locales/server/sv-se.json index 2500b95b..3fa917ad 100644 --- a/project/assets/database/locales/server/sv-se.json +++ b/project/assets/database/locales/server/sv-se.json @@ -52,6 +52,7 @@ "bot-unable_to_find_bot_in_cache": "Kunde inte hitta bot i cachen med namn: %s", "bot-missing_application_context": "applicationContex kan inte hitta %s-värde. Startade du om servern utan att starta om spelet?", "client_request": "[Klient Förfrågan] %s", + "client_request_ip": "[Klientförfrågning] {{ip}} {{url}}", "customisation-item_already_purchased": "Klädobjektet {{itemId}} {{itemName}} har redan köpts", "customisation-unable_to_find_suit_by_id": "Det gick inte att hitta erbjudande om traderkostym med id: %s", "customisation-unable_to_find_clothing_item_in_inventory": "Klädesföremål hittades inte i förrådet med id: %s", @@ -198,7 +199,6 @@ "repeatable-difficulty_was_nan": "Upprepningsbar belöningsgenerering: Svårighetsgraden var NaN. Inställning till 1.", "repeatable-no_reward_item_found_in_price_range": "Upprepningsbar belöning: Ingen artikel hittades i prisintervallet {{minPrice}} till {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Uppdragsöverlämningsfel: villkoret är redan uppfyllt? qid: {{questId}}, villkor: {{conditionId}}, profileCounter:{{profileCounter}}, värde:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Uppdragsöverlämningsfel: villkoret hittades inte eller felaktigt värde. qid: {{body.qid}, villkor: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Kan inte acceptera uppdraget, se serverloggen för detaljer", "repeatable-unable_to_accept_quest_starting_message_not_found": "Det gick inte att acceptera uppdraget: {{questId}} kan inte hitta meddelandetexten för uppdraget startat med id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s rutt rapporterar inte framgång eller misslyckande", @@ -430,6 +430,7 @@ "pmcresponse-victim_negative_99": "Din dator är så dålig att du får 20fps på streets", "pmcresponse-victim_negative_100": "Jag slår vad om att du installerade SAIN och var tvungen att ta bort det för att du dog för mycket", "pmcresponse-victim_negative_101": "Vad i helvete sade ni om mig, ni lilla Scav? Jag kommer att få dig veta att jag tog examen i min klass i USEC kåren, och jag har varit inblandad i många hemliga räder på {{playerSide}}s, och jag har över 300 bekräftade kills. Jag är utbildad i gorillakrig och jag är toppprickskytt i hela USEC:s väpnade styrkor. Ni är ingenting för mig utan bara ännu en måltavla. Jag kommer att utplåna er åt helvete med precision som aldrig tidigare har setts i denna raid, markera mina fucking ord. Du tror att du kan komma undan med att säga att skit till mig över meddelandefönstret? Tänk igen, idiot. När vi paratar kontaktar jag mitt hemliga nätverk av spioner över tullen och din stash håller på att spåras just nu så du borde förbereda dig för stormen, daggmask. Stormen som utplånar den patetiska lilla sak som du kallar ditt liv. Din fucking död, Scav. Jag kan vara var som helst, när som helst, och jag kan döda dig på över sjuhundra sätt, och det är bara med mina nakna händer. Inte bara är jag i stor utsträckning utbildad i obeväpnad kamp, men jag har tillgång till hela arsenalen av USEC-kåren och jag kommer att använda den i dess fulla utsträckning för att utplåna din eländiga rumpa utanför kartans ansikte, du lite bajs. Om bara du kunde ha vetat vilken ohelig vedergällning din lilla “smarta” kill var på väg att få ner på dig, kanske du skulle ha hållit din fucking tunga. Men du kunde inte, det gjorde du inte, och nu du betalar priset, du jävla idiot. Jag kommer att skita raseri över dig och du kommer att drunkna i det. Du är fucking död, Scav.", + "pmcresponse-victim_negative_102": "Jag slår vad om att du köpte den nya versionen bara för att få större fickor", "pmcresponse-victim_plead_1": "Jag gjorde uppdrag", "pmcresponse-victim_plead_2": "Jag ville bara avsluta ett uppdrag, varför du dödade mig", "pmcresponse-victim_plead_3": "Hoppas du är glad att jag inte ens har råd med ett nytt kit", @@ -528,6 +529,7 @@ "pmcresponse-killer_negative_27": "Lättaste bytet idag", "pmcresponse-killer_negative_28": "Oroa dig inte, jag gömde din utrustning hos din mamma", "pmcresponse-killer_negative_29": "Försökte du ens", + "pmcresponse-killer_negative_30": "Jag slår vad om att du faktiskt betalade 250 stora för den nya utgåvan", "pmcresponse-killer_plead_1": "Jag försökte få ut ett uppdragsobjekt och du var i vägen", "pmcresponse-killer_plead_2": "Jag plundrade tunnlagringar och du var i vägen, förlåt", "pmcresponse-killer_plead_3": "Jag behöver döda PMC:er, jag är säker på att du förstår", @@ -576,7 +578,7 @@ "pmc-name_prefix_33": "Hövding", "pmc-name_prefix_34": "Klurig", "pmc-name_prefix_35": "Allvarlig", - "pmc-name_prefix_36": "Misstänksamt", + "pmc-name_prefix_36": "Bärbar", "pmc-name_prefix_37": "Misstänksam", "pmc-name_prefix_38": "Pinsamt", "pmc-name_prefix_39": "Coolt", @@ -588,11 +590,23 @@ "pmc-name_prefix_45": "Sensuell", "pmc-name_prefix_46": "Fet", "pmc-name_prefix_47": "Stor", + "pmc-name_prefix_48": "Biffig", + "pmc-name_prefix_49": "Misstänkt", "launcher-profile_standard": "Samma som live, grundläggande förrådsstorlek (10x28), 500.000 rubel", "launcher-profile_leftbehind": "Samma som Standard, plus större förrådsstorlek (10x38), extra utrustning/artiklar, 500 dollar", "launcher-profile_preparetoescape": "Samma som Left Behind, plus större förrådsstorlek (10x48), extra utrustning/artiklar, högre startrykte med handlare, 250 euro", "launcher-profile-edgeofdarkness": "Samma som Prepare to Escape, plus större förrådsstorlek (10x68), extra utrustning/artiklar, högre startrykte med handlare, 1000 dollar, 500 euro", + "launcher-profile_spteasystart": "Massor av rubel/dollar/euro, vissa QoL-färdigheter är nivå 20, handlarrykte är maxat, startnivå är 15, inga uppdrag slutförda", "launcher-profile_sptzerotohero": "Börja med nästan ingenting, inga rubel/dollar/euro, inget handlarrykte, en kniv, inga uppdrag slutförda", "launcher-profile_sptdeveloper": "Testprofil, startnivån är 69, massor av rubel/dollar/euro, USEC börjar med alla uppdrag redo att starta, BEAR börjar med alla uppdrag redo att lämna in, odödlighetsbalaclava", - "launcher-missing_property": "Profil: %s saknar en descriptionLocaleKey-egenskap" + "launcher-missing_property": "Profil: %s saknar en descriptionLocaleKey-egenskap", + "release-beta-disclaimer": "Genom att trycka på OK godkänner du att inget stöd erbjuds och att detta endast är för feltestning. EJ för faktisk gameplay. Mods är inaktiverad. Nya profiler kan behöva skapas ofta. Rapportera alla buggar i rapporteringskanalen i Discord, eller på avsedd sida på webbplatsen. Om du inte trycker på OK inom den angivna tiden, kommer spelet att stängas ner.", + "release-beta-disclaimer-mods-enabled": "Genom att trycka på OK godkänner du att inget stöd erbjuds och att detta endast är för feltestning. EJ för faktisk gameplay. Mods är aktiverade, rapportera INTE problem med mods. Fråga INTE modförfattare om att uppdaterade mods. Rapportera alla buggar i rapporteringskanalen i Discord, eller på avsedd sida på webbplatsen. Om du inte trycker OK av den angivna tiden, stängs spelet.", + "release-beta-disclaimer-accept": "Användaren accepterade beta-friskrivningen", + "release-server-mods-loaded": "En eller flera servermoddar finns på en modaktiverad version, rapporter kommer att vara ogiltiga tills de blir borttagna. Se högst upp på servern för inlästa servermoddar för att ta bort dessa och för att rapportera problem igen.", + "release-server-mods-debug-message": "Servermods laddade", + "release-plugins-loaded": "En eller flera plugins finns på en modaktiverad version, rapporter kommer att vara ogiltiga tills att de blir borttagna. Se följande lista för vad du ska ta bort för att rapportera problem igen:", + "release-plugins-loaded-debug-message": "Klientmods laddade", + "release-illegal-plugins-loaded": "En eller flera icke-vitlistade plugins upptäcktes. Mods är inte tillåtna i BleedingEdge versioner av SPT. Otillåtna plugins:", + "release-illegal-plugins-exception": "Icke felsökningsmods har upptäckts. Modifieringar är inte tillåtna i BleedingEdge-versioner av SPT - var vänlig att ta bort dessa innan du spelar!" } diff --git a/project/assets/database/locales/server/tr.json b/project/assets/database/locales/server/tr.json index 8eff3cde..0338020d 100644 --- a/project/assets/database/locales/server/tr.json +++ b/project/assets/database/locales/server/tr.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "Tekrarlanabilir Ödül Üretimi: Zorluk NaN idi. 1 olarak ayarlandı.", "repeatable-no_reward_item_found_in_price_range": "Tekrarlanabilir Ödül Üretimi: Fiyat aralığında ürün bulunamadı {{minPrice}} ile {{roublesBudget}}", "repeatable-quest_handover_failed_condition_already_satisfied": "Görev handover hatası: koşul zaten karşılandı mı? qid: {{questId}}, koşul: {{conditionId}}, profilSayacı:{{profileCounter}}, değer:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "Görev handover hatası: koşul bulunamadı veya yanlış değer. qid: {{body.qid}, koşul: {{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "Görev devir hatası: koşul bulunamadı veya yanlış değer. qid: {{body.qid}}, koşul: {{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "Görev kabul edilemiyor, ayrıntılar için sunucu günlüğüne bakın", "repeatable-unable_to_accept_quest_starting_message_not_found": "Görev kabul edilemiyor: {{questId}} id ile görev başlatılmış mesaj metni bulunamıyor: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s rotası başarı veya başarısızlık bildirmiyor", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "Bilgisayarın o kadar kötü ki sokaklarda 20 fps alabiliyorsun", "pmcresponse-victim_negative_100": "Bahse girerim SAIN'i yüklediniz ve çok fazla öldürüldüğünüz için kaldırmak zorunda kaldınız", "pmcresponse-victim_negative_101": "Az önce benim hakkımda ne dedin, seni küçük Scav? USEC kolordusundan birincilikle mezun olduğumu ve {{playerSide}}'lara yapılan sayısız gizli baskında yer aldığımı ve 300'den fazla doğrulanmış öldürme eylemim olduğunu bilmeni isterim. Goril savaşı eğitimi aldım ve tüm USEC silahlı kuvvetlerindeki en iyi keskin nişancıyım. Sen benim için başka bir hedeften başka bir şey değilsin. Bu baskında daha önce hiç görülmemiş bir hassasiyetle seni yerle bir edeceğim, bu sözümü unutma. Mesajlaşma penceresinden bana böyle şeyler söyleyerek paçayı kurtarabileceğini mi sanıyorsun? Tekrar düşün, HECKER. Biz konuşurken Gümrük bölgesindeki gizli casus ağımla irtibat halindeyim ve zulan şu anda takip ediliyor, bu yüzden fırtınaya hazırlansan iyi edersin kurtçuk. Hayat dediğin zavallı küçük şeyi yok edecek fırtınaya. Sen öldün, Scav. Her an, her yerde olabilirim ve seni yedi yüzden fazla şekilde öldürebilirim ve bu sadece çıplak ellerimle. Sadece silahsız dövüş konusunda kapsamlı bir eğitime sahip değilim, aynı zamanda USEC Kolordusu'nun tüm cephaneliğine erişimim var ve bunu senin sefil kıçını haritadan silmek için sonuna kadar kullanacağım, seni küçük pislik. Keşke küçük \"zekice\" cinayetinin sana nasıl bir intikam getireceğini bilebilseydin, belki de lanet olası dilini tutardın. Ama yapamadın, yapmadın ve şimdi bedelini ödüyorsun, seni kahrolası aptal. Her tarafına öfke kusacağım ve sen de içinde boğulacaksın. Sen öldün, Scav.", + "pmcresponse-victim_negative_102": "Bahse girerim yeni unheard paketini sadece daha büyük cepler için almışsındır", "pmcresponse-victim_plead_1": "Görev yapıyordum sadece", "pmcresponse-victim_plead_2": "Sadece bir görevi bitirmek istemiştim, neden beni öldürdün", "pmcresponse-victim_plead_3": "Umarım mutlusundur. Yeni bir forma bile alamıyorum", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "Bugünün en kolay ganimeti", "pmcresponse-killer_negative_28": "Merak etme, eşyalarını annenin evine sakladım.", "pmcresponse-killer_negative_29": "Hiç denedin mi", + "pmcresponse-killer_negative_30": "Bahse girerim bu yeni paket için 250 dolar para ödemişsinizdir", + "pmcresponse-killer_negative_31": "Farelendin ", + "pmcresponse-killer_negative_32": "Fare saldırısı", "pmcresponse-killer_plead_1": "Bir görev eşyası çıkarmaya çalışıyordum ve sen yoluma çıktın", "pmcresponse-killer_plead_2": "Varil zulalarını yağmalıyordum ve sen yoluma çıktın, üzgünüm", "pmcresponse-killer_plead_3": "PMC öldürmelerine ihtiyacım var, anladığınızdan eminim", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "Şef", "pmc-name_prefix_34": "Kurnazlı", "pmc-name_prefix_35": "Ciddi", - "pmc-name_prefix_36": "Sussy", + "pmc-name_prefix_36": "Taşınabilir", "pmc-name_prefix_37": "Şüpheli", "pmc-name_prefix_38": "Cringe", "pmc-name_prefix_39": "Nankör", diff --git a/project/assets/database/locales/server/zh-TW.json b/project/assets/database/locales/server/zh-TW.json index 1707d809..fcf52d1b 100644 --- a/project/assets/database/locales/server/zh-TW.json +++ b/project/assets/database/locales/server/zh-TW.json @@ -60,6 +60,7 @@ "importing_database": "正在導入資料庫…", "importing_database_finish": "資料庫導入完成", "importing_spt_configs": "導入配置中…", + "inventory-edit_trader_item": "無法編輯商人的物品", "modloader-checked": "已檢查", "modloader-checking_mod": "檢查中: %s", "modloader-cyclic_dependency": "發現Cyclic dependency(循環依賴). 此錯誤必須修復. 修復前伺服器無法啟動, 伺服器將關閉", diff --git a/project/assets/database/locales/server/zh-cn.json b/project/assets/database/locales/server/zh-cn.json index 3d73bed1..f7b64091 100644 --- a/project/assets/database/locales/server/zh-cn.json +++ b/project/assets/database/locales/server/zh-cn.json @@ -199,7 +199,7 @@ "repeatable-difficulty_was_nan": "重复奖励生成:难度是NaN。正在设置成1。", "repeatable-no_reward_item_found_in_price_range": "重复奖励生成:价格区间{{minPrice}}至{{roublesBudget}}中未找到物品", "repeatable-quest_handover_failed_condition_already_satisfied": "任务提交错误:条件已经满足?任务id:{{questId}},条件:{{conditionId}}, profileCounter:{{profileCounter}}, value:{{value}}", - "repeatable-quest_handover_failed_condition_invalid": "任务提交错误:条件未找到或者值不正确。任务id:{{body.qid},条件:{{body.conditionId}}", + "repeatable-quest_handover_failed_condition_invalid": "任务提交错误:条件未找到或者值不正确。qid(任务):{{body.qid}},条件:{{body.conditionId}}", "repeatable-unable_to_accept_quest_see_log": "无法接取任务,查看服务端日志获取细节", "repeatable-unable_to_accept_quest_starting_message_not_found": "无法接取任务:{{questId}}找不到任务开始消息文本id: {{messageId}}", "route_onupdate_no_response": "onUpdate: %s路由不报告成功或失败", @@ -431,6 +431,7 @@ "pmcresponse-victim_negative_99": "你的烂电脑只能在街区跑20帧", "pmcresponse-victim_negative_100": "我敢打赌你装了SAIN, 然后因为死的太多又把它删了", "pmcresponse-victim_negative_101": "日你妈你龟儿子他妈说我啥子你个小Scav逼?老子要让你晓得一哈啥子叫顶尖USEC!老子暗中偷袭过{{playerSide}}无数次,舔过300次狗牌,老子还受过专门的鱿鸡战训练,USEC狙击手冠军扛把子,你在我面前算个锤子!就是个活靶子!这次突袭老子要让你见识一下,啥子叫真正的双枪李向阳!你给我记到!你觉得你有资格给我发些屁私信?老子要让你后悔!刚刚已经联系我在海关埋伏的线人了,马上就叫一伙人,把你家底翻遍偷光!你在那伙人面前屁都不是,你个死Scav!老子无时无刻无处不在,还能徒手宰你三千次!老子不光武艺高强,还手握全USEC的军火库,直接把你打成鸡巴,打成渣渣!你要是知道你偷老子屁股有什么后果,你就不得在老子面前飞扬跋扈!但是你不会,你没有,你就是要鸡蛋碰石头!老子马上给你来个报应,你个瓜娃子!老子窝耙屎都能把你淹死,你个scav货,你死定了。", + "pmcresponse-victim_negative_102": "我赌你只是为了口袋扩容才买的那个新版", "pmcresponse-victim_plead_1": "我在做任务", "pmcresponse-victim_plead_2": "我就想完成个任务,你为什么要杀我", "pmcresponse-victim_plead_3": "我都没钱起全装了你高兴了", @@ -529,6 +530,9 @@ "pmcresponse-killer_negative_27": "今天最轻松的战利品", "pmcresponse-killer_negative_28": "别担心, 我把你的装备扔给你妈了", "pmcresponse-killer_negative_29": "试试就逝世", + "pmcresponse-killer_negative_30": "我赌你是花了250大刀在那个新版本上", + "pmcresponse-killer_negative_31": "你被鼠啦", + "pmcresponse-killer_negative_32": "鼠鼠强袭", "pmcresponse-killer_plead_1": "我要带出一个任务物品但你拦在了路上", "pmcresponse-killer_plead_2": "我要去摸彩蛋桶但你挡住我了,抱歉", "pmcresponse-killer_plead_3": "我需要击杀PMC,你肯定能理解", @@ -577,7 +581,7 @@ "pmc-name_prefix_33": "身居高位的", "pmc-name_prefix_34": "诡计多端的", "pmc-name_prefix_35": "严肃的", - "pmc-name_prefix_36": "有疑的", + "pmc-name_prefix_36": "便携", "pmc-name_prefix_37": "可疑的", "pmc-name_prefix_38": "卑微的", "pmc-name_prefix_39": "潮湿的", diff --git a/project/assets/database/templates/profiles.json b/project/assets/database/templates/profiles.json index 613c80f4..aab52e6f 100644 --- a/project/assets/database/templates/profiles.json +++ b/project/assets/database/templates/profiles.json @@ -19946,3418 +19946,2793 @@ }, "InsuredItems": [], "Inventory": { - "equipment": "5fe49444ae6628187a2e77b8", + "equipment": "6613bb72b5b0ba138a0fa9f4", "fastPanel": {}, + "favoriteItems": [], "hideoutAreaStashes": {}, - "items": [{ - "_id": "5fe49444ae6628187a2e77b8", - "_tpl": "55d7217a4bdc2d86028b456d" - }, { - "_id": "63db64cbf9963741dc0d741f", - "_tpl": "6401c7b213d9b818bf0e7dd7" - }, { - "_id": "a797e819df958aad39cdbd3c", - "_tpl": "5ac4cd105acfc40016339859", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "FirstPrimaryWeapon", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Foldable": { - "Folded": false - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "43e3a7bd752424eaa0c800e0", - "_tpl": "59c6633186f7740cf0493bb9", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_gas_block" - }, { - "_id": "1cdd4c79345d24be45ae4e5f", - "_tpl": "5648b1504bdc2d9d488b4584", - "parentId": "43e3a7bd752424eaa0c800e0", - "slotId": "mod_handguard" - }, { - "_id": "a20279119c4931eceb8a097e", - "_tpl": "5ac7655e5acfc40016339a19", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_muzzle" - }, { - "_id": "b2430220da94fb22c0d65693", - "_tpl": "5649ade84bdc2d1b2b8b4587", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_pistol_grip" - }, { - "_id": "94751193011013ee7734b4fe", - "_tpl": "5ac50da15acfc4001718d287", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_reciever" - }, { - "_id": "276460f843affd97cad97da7", - "_tpl": "5ac72e475acfc400180ae6fe", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_sight_rear" - }, { - "_id": "8cf886617f5211d237aa5a1f", - "_tpl": "5ac50c185acfc400163398d4", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_stock" - }, { - "_id": "a9cb81802a05229cb65b11ef", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "parentId": "a797e819df958aad39cdbd3c", - "slotId": "mod_magazine" - }, { - "_id": "909e88f6ba6571e5ab4a3476", - "_tpl": "56dfef82d2720bbd668b4567", - "parentId": "a9cb81802a05229cb65b11ef", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "0250844ab4d1320f304fdfcb", - "_tpl": "5bffdc370db834001d23eca8", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "Scabbard", - "upd": { - "Repairable": { - "Durability": 80, - "MaxDurability": 80 - } - } - }, { - "_id": "03470cbbef724cc5017f6538", - "_tpl": "5b40e5e25acfc4001a599bea", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "Headwear", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "490e6180d045eeaf5cef9073", - "_tpl": "5ca20abf86f77418567a43f2", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "TacticalVest" - }, { - "_id": "9c22fdef66c45863afa4a8de", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "490e6180d045eeaf5cef9073", - "slotId": "1" - }, { - "_id": "11eadc612502a26aeb1611df", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "9c22fdef66c45863afa4a8de", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "01ea8735feb7d3b5ab772dde", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "490e6180d045eeaf5cef9073", - "slotId": "2" - }, { - "_id": "28605b3f275070610f47af1b", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "01ea8735feb7d3b5ab772dde", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "98f1e5b11f4f85e12db463cf", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "490e6180d045eeaf5cef9073", - "slotId": "3" - }, { - "_id": "62c13892d6d745050dad38b0", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "98f1e5b11f4f85e12db463cf", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "dbda40032725eb2924b01fbe", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "490e6180d045eeaf5cef9073", - "slotId": "4", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "f5e6bdac05e699d687993249", - "_tpl": "5857a8bc2459772bad15db29", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "SecuredContainer" - }, { - "_id": "13117a5a113a6246a2db5fff", - "_tpl": "5ca20d5986f774331e7c9602", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "Backpack" - }, { - "_id": "8b6f0bac70f8f2d91c2a0c74", - "_tpl": "56dff3afd2720bba668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 0 - }, - "parentId": "13117a5a113a6246a2db5fff", - "slotId": "main", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "c063ca857d900564f913197f", - "_tpl": "56dfef82d2720bbd668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 1 - }, - "parentId": "13117a5a113a6246a2db5fff", - "slotId": "main", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "b4bef7715cfbfde49f9deb57", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "13117a5a113a6246a2db5fff", - "slotId": "main", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "4ea0df06a22b64ea321dafec", - "_tpl": "590c5d4b86f774784e1b9c45", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 0 - }, - "parentId": "13117a5a113a6246a2db5fff", - "slotId": "main", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "af4d8b34228a85208fb85895", - "_tpl": "5648a7494bdc2d9d488b4583", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "ArmorVest", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "af4d8b34228a85208fb85895", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "af4d8b34228a85208fb85895", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "af4d8b34228a85208fb85895", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "af4d8b34228a85208fb85895", - "slotId": "soft_armor_right" - }, { - "_id": "01e9d751f10e4e9aebdd94d5", - "_tpl": "627a4e6b255f7527fb05a0f6", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "Pockets" - }, { - "_id": "4ca0cf14b0ae5bd2753a0a87", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "01e9d751f10e4e9aebdd94d5", - "slotId": "pocket1" - }, { - "_id": "749309e76ce2fdcf316f29fe", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "01e9d751f10e4e9aebdd94d5", - "slotId": "pocket2", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "729ecfc38cce5672b1dc1ad1", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "01e9d751f10e4e9aebdd94d5", - "slotId": "pocket3", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "ad076f81dc918f5e4c7fbd18", - "_tpl": "5645bcc04bdc2d363b8b4572", - "parentId": "5fe49444ae6628187a2e77b8", - "slotId": "Earpiece" - }, { - "_id": "5fe49444ae6628187a2e78b8", - "_tpl": "5811ce772459770e9e5f9532" - }, { - "_id": "702bdc5dfd91ed316b175b3c", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "fb08ac9e01a36533563a4389", - "_tpl": "5648a7494bdc2d9d488b4583", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "fb08ac9e01a36533563a4389", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "fb08ac9e01a36533563a4389", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "fb08ac9e01a36533563a4389", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "fb08ac9e01a36533563a4389", - "slotId": "soft_armor_right" - }, { - "_id": "686cfcc458f923cb2e76b8d7", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 13 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "1936371534d82e70c76a7645", - "_tpl": "5b432b965acfc47a8774094e", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 9 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "12be6d1147d04252aacaa083", - "_tpl": "5ca20abf86f77418567a43f2", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 0 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "6342de84cd397d00cb31e87f", - "_tpl": "557ff21e4bdc2d89578b4586", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 22 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "81a756ebe7ce1ea490962f9e", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 13 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "a9bccb7b590bf286c6e0a0c3", - "_tpl": "5ca20abf86f77418567a43f2", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 3 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "cfd59c8e3cd5cce89c53b10f", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "b2fe6975cd7ba911fbf6bf42", - "_tpl": "5d40407c86f774318526545a", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 0 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "f587cf58fc9d1c6cf7899bf1", - "_tpl": "5449016a4bdc2d6f028b456f", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 1 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 250000 - } - }, { - "_id": "26578d87ce5797ff5e87fd3c", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "feb9c6ec3ad0f62f2cac447c", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "26578d87ce5797ff5e87fd3c", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "7a3a6fdbd690c6e3767a096d", - "_tpl": "5648a7494bdc2d9d488b4583", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 3 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "7a3a6fdbd690c6e3767a096d", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "7a3a6fdbd690c6e3767a096d", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "7a3a6fdbd690c6e3767a096d", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "7a3a6fdbd690c6e3767a096d", - "slotId": "soft_armor_right" - }, { - "_id": "a498d5c84a16a8700486b51e", - "_tpl": "5b40e5e25acfc4001a599bea", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 0 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "90ceaf3a032fbddb4d8ba181", - "_tpl": "5b40e5e25acfc4001a599bea", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 0 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "106af131dbdc7fd37bd14dfb", - "_tpl": "5b432b965acfc47a8774094e", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 11 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "78a938654650e34abbc5b8ba", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "d74a1797a4c614b767fc3bae", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 3 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "90770873e582d91803aab334", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "d74a1797a4c614b767fc3bae", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "d9cbc2cd84237f98ff2755c3", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 4 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "8f79a44ad63d889117296f4c", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "d9cbc2cd84237f98ff2755c3", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "2812b9183017676294379dca", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d8f30bca23ad344542332c2b", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "2812b9183017676294379dca", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "793165a59cd9851376721225", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 5 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "a8063d54da55fb4f5f65e5db", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "793165a59cd9851376721225", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "5c38985edc19d2dcabbae35c", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "e1ea22ee08f9df9510ba0d78", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "cfefb0ba82b5146fc31a6950", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "b6672157bc48c99a22bddfc0", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "eb9fdb0d060da5428fda443c", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "79d2d8c7e5beea7eacdd182b", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "627d2a20092c113b5becf64d", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "ca80652ee36de43007d8efcc", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "008684957ef010140bcaab5d", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "ca80652ee36de43007d8efcc", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "a3c7c8cc79286d6977471596", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "0ec7e3bf2f3c7c3ba38239eb", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "a3c7c8cc79286d6977471596", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "feb6dfb5498cd78530ef127c", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "e8bb934c6185c10053db2644", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "feb6dfb5498cd78530ef127c", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "98f8acadeebdbfc5dc71e3d1", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "5d1d600c9966b2a55a7b2753", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "98f8acadeebdbfc5dc71e3d1", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "865d1f2ad642b3b4f1215069", - "_tpl": "599860ac86f77436b225ed1a", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "b66581c029631a7b55a32047", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "865d1f2ad642b3b4f1215069", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "84e1c2763a73328da1f12d47", - "_tpl": "5ca20d5986f774331e7c9602", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 11 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "a41d51a5df91ab76147f4f67", - "_tpl": "5ca20d5986f774331e7c9602", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 11 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "da12ff8da976f0b65169a4c6", - "_tpl": "56dfef82d2720bbd668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 17 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "cff77612829a2bca05bb12fe", - "_tpl": "590c661e86f7741e566b646a", - "location": { - "isSearched": true, - "r": 1, - "x": 8, - "y": 32 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 220 - } - } - }, { - "_id": "bf4e22ad1b7491a3b64952f0", - "_tpl": "5449016a4bdc2d6f028b456f", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 1 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 250000 - } - }, { - "_id": "0d433004c6fbce3e87cab553", - "_tpl": "590c661e86f7741e566b646a", - "location": { - "isSearched": true, - "r": 1, - "x": 8, - "y": 30 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 220 - } - } - }, { - "_id": "45f4260eb5b8f95b76169117", - "_tpl": "5755383e24597772cb798966", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 6 - } - } - }, { - "_id": "5b5939c98d57a378a0028aab", - "_tpl": "56dff3afd2720bba668b4567", - "location": { - "isSearched": true, - "r": "Horizontal", - "x": 9, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "6090c8f36c2c7ea96450338f", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 15 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "ab849c066c608b391089b7ec", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 15 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "778249f3797805c34e11eb12", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "62357ba0ab9508b9dd3122e6", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "778249f3797805c34e11eb12", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "e7758bee1260861bf7002b97", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "44919bf9dd35679ad2f2f05a", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "e7758bee1260861bf7002b97", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "fa48d505a5d4b745d87738db", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "6f052efd98ed56034614d0c8", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "fa48d505a5d4b745d87738db", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "791c40db74e01311fe25e1f6", - "_tpl": "56dfef82d2720bbd668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "ae94aebd712a154aa5507d95", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "ff0ff90e0cf7c5e3e7010ea4", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "ae94aebd712a154aa5507d95", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "08dfb883d785b8f6c2cb3c55", - "_tpl": "590c5d4b86f774784e1b9c45", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 30 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "d669a3bb766f4b5372d397c8", - "_tpl": "590c5d4b86f774784e1b9c45", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 30 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "151c9e54ab15b0671f73dbc8", - "_tpl": "590c5d4b86f774784e1b9c45", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 30 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "ab975022dba4a048a89bab1f", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 32 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "6e7c46c087fbb3c5c75d8289", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 32 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "2c2328ec1d21a33e4672ff5d", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 32 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "7f0dce2c6b47b1eeac74f3fd", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 29 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "f34845e66c2fb4d3a724610e", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 29 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "14d7acac0cfb3b83a75f338e", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "e9a6f02b0bdcb5396e649244", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "370172a19dfd4e467aef1dbe", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d4dce1062cb9cc8a826ea03b", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d3ce4df1bc5894e2f78882f3", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "ae8149b8dc0ae253f174b6f4", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "4daad698cf5b72487346e0d5", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "f880ae41ce81ab084a2f4eab", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "64277b11e912b968a9c41b3b", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "239a4b43740b84e90db4fb17", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "c4332600c7ea3d4dc9a3eeeb", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "87961dd2d7e7ee05db9e45c9", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 7 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "9dd9d821cffb585482fd1389", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "87961dd2d7e7ee05db9e45c9", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "9417e493bc4c277a6adee960", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "9492c6ec9a2a58c03fb3ae07", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "9417e493bc4c277a6adee960", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "50e24912547aecad4244f96c", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "bf299763ba7c6d6130aeb67c", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 14 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "169fca7757fa58518380f4ed", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 14 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "94614a61c5f560ec575b96f5", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 28 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "a9f69caa9c291288d3af3f70", - "_tpl": "5d02778e86f774203e7dedbe", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "86c426e5603f11f3973a7c2e", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "423c59d7d0be625133067ff9", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d987a0a70512510f633e21d5", - "_tpl": "590c695186f7741e566b64a2", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d51b419b7f442422bcf2fab6", - "_tpl": "590c695186f7741e566b64a2", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "03cd7851e89f43020e24bafb", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "57daa3f963e75470cebe4fef", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "e63b5a4e5a3c84dde743edd1", - "_tpl": "5696686a4bdc2da3298b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 2 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "4c138d4262cfdd01efc8145a", - "_tpl": "5696686a4bdc2da3298b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 2 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "f0f9c3ff0b3b1dbdeffee6ea", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "a8b2466d0350461c4b04fd2c", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "fe4dbfce77eb6008a8f4d09d", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 10 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "11ae2930e3accdc5f124876b", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 9 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "c8a0ba51f519cfde0fe997e8", - "_tpl": "5c0e53c886f7747fa54205c7", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 19 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 47, - "MaxDurability": 47 - } - } - }, { - "_id": "658c3f38bb2016e5630bdca8", - "_tpl": "656f603f94b480b8a500c0d6", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "front_plate" - }, { - "_id": "658c3f38bb2016e5630bdca9", - "_tpl": "656efd66034e8e01c407f35c", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "back_plate" - }, { - "_id": "658c3f38bb2016e5630bdcaa", - "_tpl": "654a8b0b0337d53f9102c2ae", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdcab", - "_tpl": "654a8976f414fcea4004d78b", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdcac", - "_tpl": "654a8b3df414fcea4004d78f", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdcad", - "_tpl": "654a8b80f414fcea4004d797", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "soft_armor_right" - }, { - "_id": "658c3f38bb2016e5630bdcae", - "_tpl": "654a8ae00337d53f9102c2aa", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "Collar" - }, { - "_id": "658c3f38bb2016e5630bdcaf", - "_tpl": "654a8bc5f414fcea4004d79b", - "parentId": "c8a0ba51f519cfde0fe997e8", - "slotId": "Groin" - }, { - "_id": "cd688bf5123e7f7b524bf826", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "44ebc2c1ad7f620ebe405367", - "_tpl": "5d1b36a186f7742523398433", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 100 - } - } - }, { - "_id": "c71ab08b792188701a79e839", - "_tpl": "5d1b371186f774253763a656", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 60 - } - } - }, { - "_id": "719317c75d4325f6a48a14a6", - "_tpl": "5d0a3e8cd7ad1a6f6a3d35bd", - "parentId": "f5de5b058e07bcacee8c97d0", - "slotId": "mod_scope", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "f5de5b058e07bcacee8c97d0", - "_tpl": "5d0a29fed7ad1a002769ad08", - "parentId": "60c86df7ed1a4e3ce394a0f6", - "slotId": "mod_scope" - }, { - "_id": "612d78111fdcbf34bd2d7b28", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "100de389aa4e70a171270a83", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "e58c0f483fce36e55aec165e", - "_tpl": "559ba5b34bdc2d1f1a8b4582", - "location": { - "isSearched": true, - "r": "Horizontal", - "x": 8, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "e20ddc9d3b8849fbdc251ea0", - "_tpl": "5887431f2459777e1612938f", - "parentId": "e58c0f483fce36e55aec165e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "dd6cb088cfc11365f794ec4b", - "_tpl": "559ba5b34bdc2d1f1a8b4582", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 20 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "da6373f4e09dd3d4eea68bf0", - "_tpl": "5887431f2459777e1612938f", - "parentId": "dd6cb088cfc11365f794ec4b", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "9cad0271722c938b71f12f95", - "_tpl": "559ba5b34bdc2d1f1a8b4582", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 19 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d9d62e8db1303bbf4a88c7e9", - "_tpl": "5887431f2459777e1612938f", - "parentId": "9cad0271722c938b71f12f95", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "25a617ea956575203cdf0a09", - "_tpl": "5d02778e86f774203e7dedbe", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "deed2ec92f8ebf37cf3e639a", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "e4c6958acc50164d2387b53a", - "_tpl": "5aa7cfc0e5b5b00015693143", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 23 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 25, - "MaxDurability": 25 - } - } - }, { - "_id": "658c3f38bb2016e5630bdc64", - "_tpl": "657baaf0b7e9ca9a02045c02", - "parentId": "e4c6958acc50164d2387b53a", - "slotId": "Helmet_top" - }, { - "_id": "658c3f38bb2016e5630bdc65", - "_tpl": "657bab6ec6f689d3a205b85f", - "parentId": "e4c6958acc50164d2387b53a", - "slotId": "Helmet_back" - }, { - "_id": "658c3f38bb2016e5630bdc66", - "_tpl": "657babc6f58ba5a6250107a2", - "parentId": "e4c6958acc50164d2387b53a", - "slotId": "Helmet_ears" - }, { - "_id": "599a234277a564d9dd5bdd1c", - "_tpl": "5ab8f39486f7745cd93a1cca", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 22 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "8683fa7212c9bdd366063dd0", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 32 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "4abf4d970ec5b19afe8e126d", - "_tpl": "569668774bdc2da2298b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 2 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "7ca437210f63ee92275b37fe", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "7ad655c1e45bc6a9f49b4b99", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 36 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "f602250b1405f266cfe696f7", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "8b672ab1e2278d787bed7cf9", - "_tpl": "5d5d940f86f7742797262046", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 29 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "da478b8f22969edb7af064a8", - "_tpl": "57cd379a24597778e7682ecf", - "location": { - "isSearched": true, - "r": 1, - "x": 4, - "y": 23 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "49fbfbdeed8888564938c8cb", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "8da531704ee0e9cabfc6dce2", - "_tpl": "5710c24ad2720bc3458b45a3", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 22 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "3cd0e5ffd24f9e4c1f206741", - "_tpl": "5ab8f39486f7745cd93a1cca", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "24f71b418e8670d740e6024b", - "_tpl": "5e2af4a786f7746d3f3c3400", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 40 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "17f350695fd709de9e868610", - "_tpl": "5d5d85c586f774279a21cbdb", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 25 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "380b954613fc6559dee3e19e", - "_tpl": "5c0e722886f7740458316a57", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 25 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 65, - "MaxDurability": 65 - } - } - }, { - "_id": "658c3f38bb2016e5630bdcb1", - "_tpl": "656fa0fb498d1b7e3e071d9c", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "Front_plate" - }, { - "_id": "658c3f38bb2016e5630bdcb2", - "_tpl": "656fa0fb498d1b7e3e071d9c", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "Back_plate" - }, { - "_id": "658c3f38bb2016e5630bdcb3", - "_tpl": "65730c0e292ecadbfa09ad49", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdcb4", - "_tpl": "65730c2213a2f660f60bea96", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdcb5", - "_tpl": "65730c2b292ecadbfa09ad50", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdcb6", - "_tpl": "65730c35292ecadbfa09ad54", - "parentId": "380b954613fc6559dee3e19e", - "slotId": "soft_armor_right" - }, { - "_id": "b410bdab51c195ffe3c83d1b", - "_tpl": "5b432d215acfc4771e1c6624", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 23 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 30, - "MaxDurability": 30 - } - } - }, { - "_id": "658c3f38bb2016e5630bdc75", - "_tpl": "657bb92fa1c61ee0c303631f", - "parentId": "b410bdab51c195ffe3c83d1b", - "slotId": "Helmet_top" - }, { - "_id": "658c3f38bb2016e5630bdc76", - "_tpl": "657bb99db30eca976305117f", - "parentId": "b410bdab51c195ffe3c83d1b", - "slotId": "Helmet_back" - }, { - "_id": "172f0b166eec3c78e6c3ea84", - "_tpl": "5e8488fa988a8701445df1e4", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 3 - } - } - }, { - "_id": "ccac1906f229352147a9934b", - "_tpl": "5e8488fa988a8701445df1e4", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 3 - } - } - }, { - "_id": "c728563377b6a440482d77b9", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "b43973e59452e707816a5857", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 39 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "dd039504d446bd7af0992a1b", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "dc189c626993ff517fc61236", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 28 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "7d644abc323d82b9ba729740", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "dc189c626993ff517fc61236", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "661a3936e62f490e219582dc", - "_tpl": "56dff3afd2720bba668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 28 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "449d62388f2f639a64045d71", - "_tpl": "56dff3afd2720bba668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 28 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "52399e2f1a3044a514b2030b", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 23 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "467a6cdeeb6cd75a7c538872", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "52399e2f1a3044a514b2030b", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "e0419baa0c2d4f3619acb5cc", - "_tpl": "5c0e530286f7747fa1419862", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "1e4a2fd745c006867fb88f79", - "_tpl": "5c0e530286f7747fa1419862", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "5784837a07c8f380cb2950cd", - "_tpl": "559ba5b34bdc2d1f1a8b4582", - "parentId": "60c86df7ed1a4e3ce394a0f6", - "slotId": "mod_magazine" - }, { - "_id": "de67e78c4fb859322f766194", - "_tpl": "5887431f2459777e1612938f", - "parentId": "5784837a07c8f380cb2950cd", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "1eb47c86694ab2fce9904af6", - "_tpl": "5c0505e00db834001b735073", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 24 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "1772d219adce434a029346c1", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 25 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "b04747fbdbeb0707a3f7340d", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "1772d219adce434a029346c1", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "12572b486734c09b8839733d", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "location": { - "isSearched": true, - "r": 1, - "x": 5, - "y": 24 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "8f08e02573f940e71f37feb2", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "12572b486734c09b8839733d", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "4da90923d1e3133f938bdeec", - "_tpl": "590c657e86f77412b013051d", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 1800 - } - } - }, { - "_id": "c6d58ede5aa9d24744187054", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "0bc3a80d48bac27550c6a15a", - "_tpl": "5b432b965acfc47a8774094e", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 21 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "5f13a6fbf32fbcd1c5796899", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 27 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "f0c60e3787fa3aca66dcc74a", - "_tpl": "5887431f2459777e1612938f", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 22 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 40 - } - }, { - "_id": "44e01b1a96be81711f7dc93e", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 34 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "7dd0fe67076e301ba04210dc", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 33 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "5253b6b2ca3428ab303af52b", - "_tpl": "5e2af47786f7746d404f3aaa", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 38 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "99eaa80a461346eda014048d", - "_tpl": "5e2af47786f7746d404f3aaa", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 39 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "9812a8a58953878fa4242cd3", - "_tpl": "5e2af4a786f7746d3f3c3400", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 40 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "1f7bfa7312cdaa64f4133089", - "_tpl": "544fb3f34bdc2d03748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "04e14fd3d1294042f7cb618d", - "_tpl": "544fb3f34bdc2d03748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 35 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "93ca8f31b67632bc7f8caf74", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d96c035dd972bb5b42a7951a", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "93ca8f31b67632bc7f8caf74", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "217bde33f66867ae88e11af1", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "d7ab0baf36814edcd1c33e20", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "217bde33f66867ae88e11af1", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "32c8f2ea6a975dafe2f4daba", - "_tpl": "576a5ed62459771e9c2096cb", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 7 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "97861a122e2e3e84c07e34b3", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "32c8f2ea6a975dafe2f4daba", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "6c232b354c34836ee2627544", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "e4d6da7d7327f32138181741", - "_tpl": "5645bcc04bdc2d363b8b4572", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 23 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "8698b23a78a8dc22f4c69609", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 9 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "3497bff150a35f338ca823f6", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 8 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "9942ed330f84122f06ba4db4", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 7 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "bc683f19adbaab56ff115d51", - "_tpl": "56d59d3ad2720bdb418b4577", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 7 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 25 - } - }, { - "_id": "1064afb08ab86ccac101d94f", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 30 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "c844cb2dba7d609cbcba4770", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 31 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5ed1e6bac123c3b2c9eeaf35", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 37 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "033a831eee25432724e8b1e9", - "_tpl": "576a581d2459771e7b1bc4f1", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 4 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "4040d36d8534fae91fb683d9", - "_tpl": "576a5ed62459771e9c2096cb", - "parentId": "033a831eee25432724e8b1e9", - "slotId": "mod_magazine" - }, { - "_id": "b1c5d10c0b6bb788d1a1d032", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "4040d36d8534fae91fb683d9", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "cbd1aa819fe0cf71f0d23ccd", - "_tpl": "576a63cd2459771e796e0e11", - "parentId": "033a831eee25432724e8b1e9", - "slotId": "mod_pistol_grip" - }, { - "_id": "aee2db2a5b61e09942c5b7d7", - "_tpl": "59984ab886f7743e98271174", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Foldable": { - "Folded": false - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "e73fe8ced9426d992f6bb3c0", - "_tpl": "5998517986f7746017232f7e", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_pistol_grip" - }, { - "_id": "88641f60682745d0bf04747e", - "_tpl": "599851db86f77467372f0a18", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_stock" - }, { - "_id": "6393b7d3728b809b054baa31", - "_tpl": "599860ac86f77436b225ed1a", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_magazine" - }, { - "_id": "77489a635cff7fb941b58382", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "6393b7d3728b809b054baa31", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "54d27d8d60eb93aa6598377a", - "_tpl": "5998597786f77414ea6da093", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_muzzle" - }, { - "_id": "249ccd46eb7413434545be77", - "_tpl": "59985a8086f77414ec448d1a", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_reciever" - }, { - "_id": "673088d03e5d01e4138ef4ab", - "_tpl": "599860e986f7743bb57573a6", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "e629647af1a768658f2576a9", - "_tpl": "59ccd11386f77428f24a488f", - "parentId": "aee2db2a5b61e09942c5b7d7", - "slotId": "mod_gas_block" - }, { - "_id": "6ae2eff0b14c553cdaf9c4be", - "_tpl": "5648b1504bdc2d9d488b4584", - "parentId": "e629647af1a768658f2576a9", - "slotId": "mod_handguard" - }, { - "_id": "48116a27afe5a51c917c10dd", - "_tpl": "576a581d2459771e7b1bc4f1", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 3 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "492f1602f7df59c0ff58bb91", - "_tpl": "576a5ed62459771e9c2096cb", - "parentId": "48116a27afe5a51c917c10dd", - "slotId": "mod_magazine" - }, { - "_id": "2d1261c888e045fc764e4a11", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "492f1602f7df59c0ff58bb91", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "c68ed794aa5be082ab90220e", - "_tpl": "576a63cd2459771e796e0e11", - "parentId": "48116a27afe5a51c917c10dd", - "slotId": "mod_pistol_grip" - }, { - "_id": "04f8a1021e1cef21b5347758", - "_tpl": "576a581d2459771e7b1bc4f1", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 5 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "1ae4bba45f10fc2012f3a5b1", - "_tpl": "576a5ed62459771e9c2096cb", - "parentId": "04f8a1021e1cef21b5347758", - "slotId": "mod_magazine" - }, { - "_id": "5dbe4c5e5b4795f82ed6144a", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "1ae4bba45f10fc2012f3a5b1", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 18 - } - }, { - "_id": "ca2a633299f9f33af985b298", - "_tpl": "576a63cd2459771e796e0e11", - "parentId": "04f8a1021e1cef21b5347758", - "slotId": "mod_pistol_grip" - }, { - "_id": "b81104333cd5e913c1abd001", - "_tpl": "59984ab886f7743e98271174", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 6 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Foldable": { - "Folded": false - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "caae6d1eec454357902beeba", - "_tpl": "5998517986f7746017232f7e", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_pistol_grip" - }, { - "_id": "d1904664ab60713b9fd815be", - "_tpl": "599851db86f77467372f0a18", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_stock" - }, { - "_id": "9dad59f2a5e9ff7e955c5a56", - "_tpl": "599860ac86f77436b225ed1a", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_magazine" - }, { - "_id": "0a21f9564f0c58050b5dd2d2", - "_tpl": "56d59d3ad2720bdb418b4577", - "parentId": "9dad59f2a5e9ff7e955c5a56", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "ae896c83b9422ef05d676b06", - "_tpl": "5998597786f77414ea6da093", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_muzzle" - }, { - "_id": "fc407b8aa1339bba319c2ef6", - "_tpl": "59985a8086f77414ec448d1a", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_reciever" - }, { - "_id": "6a7502a02962e7c027c15a63", - "_tpl": "599860e986f7743bb57573a6", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "67fe260376be3f6cb6ded9cf", - "_tpl": "59ccd11386f77428f24a488f", - "parentId": "b81104333cd5e913c1abd001", - "slotId": "mod_gas_block" - }, { - "_id": "f19cdda8faee5021d4a08f81", - "_tpl": "5648b1504bdc2d9d488b4584", - "parentId": "67fe260376be3f6cb6ded9cf", - "slotId": "mod_handguard" - }, { - "_id": "88d67c13e89abba40c550ef1", - "_tpl": "5ac4cd105acfc40016339859", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 16 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Foldable": { - "Folded": false - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "ec876c03e80b8c3c46e59399", - "_tpl": "59c6633186f7740cf0493bb9", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_gas_block" - }, { - "_id": "da186a0d6c299a65a317ed61", - "_tpl": "5648b1504bdc2d9d488b4584", - "parentId": "ec876c03e80b8c3c46e59399", - "slotId": "mod_handguard" - }, { - "_id": "cfacc8f134240e1223fcb615", - "_tpl": "5ac7655e5acfc40016339a19", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_muzzle" - }, { - "_id": "cc181f04ada4abe087e17234", - "_tpl": "5649ade84bdc2d1b2b8b4587", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_pistol_grip" - }, { - "_id": "d8c5662e3f953c5e4c9f4613", - "_tpl": "5ac50da15acfc4001718d287", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_reciever" - }, { - "_id": "ad816afec6245fb529b58600", - "_tpl": "5ac72e475acfc400180ae6fe", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "fec1cfe279af3d3258bd0c90", - "_tpl": "5ac50c185acfc400163398d4", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_stock" - }, { - "_id": "a4e24ac95eb0f569a1866bf3", - "_tpl": "55d480c04bdc2d1d4e8b456a", - "parentId": "88d67c13e89abba40c550ef1", - "slotId": "mod_magazine" - }, { - "_id": "2d1395cba72107e1c9162cf3", - "_tpl": "56dfef82d2720bbd668b4567", - "parentId": "a4e24ac95eb0f569a1866bf3", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "1c25a131cbb81b7961ef203b", - "_tpl": "5e870397991fd70db46995c8", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5df1457876ccab711e118c24", - "_tpl": "5e87071478f43e51ca2de5e1", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "mod_barrel" - }, { - "_id": "c0ca8f4dea05e26d4e806a4c", - "_tpl": "5e8708d4ae379e67d22e0102", - "parentId": "5df1457876ccab711e118c24", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "6919532db9870495a2a7a7c8", - "_tpl": "5e87076ce2db31558c75a11d", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "mod_handguard" - }, { - "_id": "90e4e6856f705bedd86f56c2", - "_tpl": "5e87080c81c4ed43e83cefda", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "mod_magazine" - }, { - "_id": "d8f540e6cfb57e776d01e3ce", - "_tpl": "560d5e524bdc2d25448b4571", - "parentId": "90e4e6856f705bedd86f56c2", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 8 - } - }, { - "_id": "ce990869892535be8644a87d", - "_tpl": "5e87116b81c4ed43e83cefdd", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "mod_stock" - }, { - "_id": "65c7752f89afb6e9fc368d54", - "_tpl": "5e87114fe2db31558c75a120", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "mod_mount", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "2fee9ee8b89eb2bc60279765", - "_tpl": "560d5e524bdc2d25448b4571", - "parentId": "1c25a131cbb81b7961ef203b", - "slotId": "patron_in_weapon" - }, { - "_id": "0263e3bc89cb651c5139987e", - "_tpl": "559ba5b34bdc2d1f1a8b4582", - "location": { - "isSearched": true, - "r": "Horizontal", - "x": 9, - "y": 18 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout" - }, { - "_id": "769a6f15a9b3c58ce40e75ac", - "_tpl": "5887431f2459777e1612938f", - "parentId": "0263e3bc89cb651c5139987e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "b2edecbf14e5350dfd6e6e5e", - "_tpl": "6499849fc93611967b034949", - "location": { - "isSearched": true, - "r": 1, - "x": 7, - "y": 25 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Foldable": { - "Folded": false - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - },{ - "_id": "1424076063149bbbc18be043", - "_tpl": "649ec107961514b22506b10c", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_gas_block", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "4d80308cb8a6857a9d83bbc6", - "_tpl": "5beec8ea0db834001a6f9dbf", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_pistol_grip", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "a025f2dbc9f08b942a4c6e9b", - "_tpl": "649ec127c93611967b034957", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_handguard", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "4604eba2de0c758ccba0a192", - "_tpl": "649ec2af961514b22506b10f", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_muzzle", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "d29933d494ea298f19db3aeb", - "_tpl": "649ec2f3961514b22506b111", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_reciever", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "9808b23de6d06cbcf1dfb99e", - "_tpl": "649ec30cb013f04a700e60fb", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_magazine", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "c63e9186930f29c20f9d0fe4", - "_tpl": "649ec87d8007560a9001ab36", - "parentId": "b2edecbf14e5350dfd6e6e5e", - "slotId": "mod_stock_001", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "81c613b056072a70d6c26e1f", - "_tpl": "5beecbb80db834001d2c465e", - "parentId": "a025f2dbc9f08b942a4c6e9b", - "slotId": "mod_mount_001", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "20c4a8f521c8aed8176d3870", - "_tpl": "649ec2da59cbb3c813042dca", - "parentId": "d29933d494ea298f19db3aeb", - "slotId": "mod_sight_rear", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "5c730026306a7c56490e5f3e", - "_tpl": "5beec8c20db834001d2c465c", - "parentId": "c63e9186930f29c20f9d0fe4", - "slotId": "mod_stock", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "bcb76cd884032f340f0f7a01", - "_tpl": "649ec2cec93611967b03495e", - "parentId": "20c4a8f521c8aed8176d3870", - "slotId": "mod_sight_rear", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "0bc701a7ea93ee76e18ebb0e", - "_tpl": "56dff3afd2720bba668b4567", - "parentId": "9808b23de6d06cbcf1dfb99e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49444ae6628187a2e78ba", - "_tpl": "5963866b86f7747bfa1c4462" - }, { - "_id": "5fe49444ae6628187a2e78b9", - "_tpl": "5963866286f7747bf429b572" - }, { - "_id": "60dca3da42ad9b706b369aca", - "_tpl": "602543c13fee350cd564d032" - }, { - "_id": "60c86df7ed1a4e3ce394a0f6", - "_tpl": "55801eed4bdc2d89578b4588", - "location": { - "isSearched": true, - "r": "Horizontal", - "x": 4, - "y": 19 - }, - "parentId": "5fe49444ae6628187a2e78b8", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - }, - "StackObjectsCount": 1 - } - }, { - "_id": "645a3bf083b382035fcd50c3", - "_tpl": "56083eab4bdc2d26448b456a", - "parentId": "60c86df7ed1a4e3ce394a0f6", - "slotId": "mod_tactical", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "f230be53d0fb90f23ac0005e", - "_tpl": "560e620e4bdc2d724b8b456b", - "parentId": "60c86df7ed1a4e3ce394a0f6", - "slotId": "mod_muzzle", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "3da4a360d74f2f9628bc5dd2", - "_tpl": "61faa91878830f069b6b7967", - "parentId": "60c86df7ed1a4e3ce394a0f6", - "slotId": "mod_stock", - "upd": { - "StackObjectsCount": 1 - } - }, { - "_id": "969ff4763565268bc52e4d2e", - "_tpl": "56ea8222d2720b69698b4567", - "parentId": "3da4a360d74f2f9628bc5dd2", - "slotId": "mod_bipod", - "upd": { - "StackObjectsCount": 1 - } + "items": [ + { + "_id": "6613bb72b5b0ba138a0fa9f4", + "_tpl": "55d7217a4bdc2d86028b456d" + }, { + "_id": "6613bb72b5b0ba138a0fa9d9", + "_tpl": "5ac4cd105acfc40016339859", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "FirstPrimaryWeapon" + }, { + "_id": "6613bb72b5b0ba138a0fa9d1", + "_tpl": "59c6633186f7740cf0493bb9", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_gas_block" + }, { + "_id": "6613bb72b5b0ba138a0fa9d0", + "_tpl": "5648b1504bdc2d9d488b4584", + "parentId": "6613bb72b5b0ba138a0fa9d1", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0fa9d2", + "_tpl": "5ac7655e5acfc40016339a19", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0fa9d3", + "_tpl": "5649ade84bdc2d1b2b8b4587", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0fa9d4", + "_tpl": "5ac50da15acfc4001718d287", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_reciever" + }, { + "_id": "6613bb72b5b0ba138a0fa9d5", + "_tpl": "5ac72e475acfc400180ae6fe", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0fa9d6", + "_tpl": "5ac50c185acfc400163398d4", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0fa9d8", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fa9d9", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0fa9d7", + "_tpl": "56dfef82d2720bbd668b4567", + "parentId": "6613bb72b5b0ba138a0fa9d8", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 } - ], - "questRaidItems": "5fe49444ae6628187a2e78b9", - "questStashItems": "5fe49444ae6628187a2e78ba", - "sortingTable": "60dca3da42ad9b706b369aca", - "stash": "5fe49444ae6628187a2e78b8" + }, { + "_id": "6613bb72b5b0ba138a0fa9da", + "_tpl": "5bffdc370db834001d23eca8", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "Scabbard" + }, { + "_id": "6613bb72b5b0ba138a0fa9db", + "_tpl": "5b40e5e25acfc4001a599bea", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "Headwear" + }, { + "_id": "6613bb72b5b0ba138a0fa9e3", + "_tpl": "5ca20abf86f77418567a43f2", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "TacticalVest" + }, { + "_id": "6613bb72b5b0ba138a0fa9dd", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fa9e3", + "slotId": "1", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9dc", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fa9dd", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0fa9df", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fa9e3", + "slotId": "2", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9de", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fa9df", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e1", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fa9e3", + "slotId": "3", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e0", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fa9e1", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e2", + "_tpl": "5755356824597772cb798962", + "parentId": "6613bb72b5b0ba138a0fa9e3", + "slotId": "4", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e4", + "_tpl": "5857a8bc2459772bad15db29", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "SecuredContainer" + }, { + "_id": "6613bb72b5b0ba138a0fa9e9", + "_tpl": "5ca20d5986f774331e7c9602", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "Backpack" + }, { + "_id": "6613bb72b5b0ba138a0fa9e5", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fa9e9", + "slotId": "main", + "location": { + "x": 2, + "y": 0, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e6", + "_tpl": "56dfef82d2720bbd668b4567", + "parentId": "6613bb72b5b0ba138a0fa9e9", + "slotId": "main", + "location": { + "x": 2, + "y": 1, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e7", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613bb72b5b0ba138a0fa9e9", + "slotId": "main", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613bb72b5b0ba138a0fa9e8", + "_tpl": "590c5d4b86f774784e1b9c45", + "parentId": "6613bb72b5b0ba138a0fa9e9", + "slotId": "main", + "location": { + "x": 1, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9ee", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "ArmorVest" + }, { + "_id": "6613bb72b5b0ba138a0fa9ea", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613bb72b5b0ba138a0fa9ee", + "slotId": "Soft_armor_front" + }, { + "_id": "6613bb72b5b0ba138a0fa9eb", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613bb72b5b0ba138a0fa9ee", + "slotId": "Soft_armor_back" + }, { + "_id": "6613bb72b5b0ba138a0fa9ec", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613bb72b5b0ba138a0fa9ee", + "slotId": "Soft_armor_left" + }, { + "_id": "6613bb72b5b0ba138a0fa9ed", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613bb72b5b0ba138a0fa9ee", + "slotId": "soft_armor_right" + }, { + "_id": "6613bb72b5b0ba138a0fa9f2", + "_tpl": "627a4e6b255f7527fb05a0f6", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "Pockets" + }, { + "_id": "6613bb72b5b0ba138a0fa9ef", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613bb72b5b0ba138a0fa9f2", + "slotId": "pocket1", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9f0", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613bb72b5b0ba138a0fa9f2", + "slotId": "pocket2", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9f1", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613bb72b5b0ba138a0fa9f2", + "slotId": "pocket3", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9f3", + "_tpl": "5645bcc04bdc2d363b8b4572", + "parentId": "6613bb72b5b0ba138a0fa9f4", + "slotId": "Earpiece" + }, { + "_id": "6613bb72b5b0ba138a0fab07", + "_tpl": "5811ce772459770e9e5f9532" + }, { + "_id": "6613bb72b5b0ba138a0fa9f5", + "_tpl": "5755356824597772cb798962", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9fa", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9f6", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613bb72b5b0ba138a0fa9fa", + "slotId": "Soft_armor_front" + }, { + "_id": "6613bb72b5b0ba138a0fa9f7", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613bb72b5b0ba138a0fa9fa", + "slotId": "Soft_armor_back" + }, { + "_id": "6613bb72b5b0ba138a0fa9f8", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613bb72b5b0ba138a0fa9fa", + "slotId": "Soft_armor_left" + }, { + "_id": "6613bb72b5b0ba138a0fa9f9", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613bb72b5b0ba138a0fa9fa", + "slotId": "soft_armor_right" + }, { + "_id": "6613bb72b5b0ba138a0fa9fb", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 10, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9fc", + "_tpl": "5b432b965acfc47a8774094e", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9fd", + "_tpl": "5ca20abf86f77418567a43f2", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9fe", + "_tpl": "557ff21e4bdc2d89578b4586", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0fa9ff", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 10, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa00", + "_tpl": "5ca20abf86f77418567a43f2", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa01", + "_tpl": "5755356824597772cb798962", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa02", + "_tpl": "5d40407c86f774318526545a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa03", + "_tpl": "5449016a4bdc2d6f028b456f", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 1, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 250000 + } + }, { + "_id": "6613bb72b5b0ba138a0faa05", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa04", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa05", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa0a", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa06", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613bb72b5b0ba138a0faa0a", + "slotId": "Soft_armor_front" + }, { + "_id": "6613bb72b5b0ba138a0faa07", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613bb72b5b0ba138a0faa0a", + "slotId": "Soft_armor_back" + }, { + "_id": "6613bb72b5b0ba138a0faa08", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613bb72b5b0ba138a0faa0a", + "slotId": "Soft_armor_left" + }, { + "_id": "6613bb72b5b0ba138a0faa09", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613bb72b5b0ba138a0faa0a", + "slotId": "soft_armor_right" + }, { + "_id": "6613bb72b5b0ba138a0faa0b", + "_tpl": "5b40e5e25acfc4001a599bea", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa0c", + "_tpl": "5b40e5e25acfc4001a599bea", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa0d", + "_tpl": "5b432b965acfc47a8774094e", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa0e", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa10", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa0f", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa10", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa12", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 4, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa11", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa12", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa14", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa13", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa14", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa16", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 5, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa15", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa16", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa17", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa18", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa19", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa1a", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa1c", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa1b", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa1c", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa1e", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa1d", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa1e", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa20", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa1f", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa20", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa22", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa21", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa22", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa24", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 8, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa23", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa24", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa25", + "_tpl": "5ca20d5986f774331e7c9602", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 11, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa26", + "_tpl": "5ca20d5986f774331e7c9602", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 11, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa27", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa28", + "_tpl": "590c661e86f7741e566b646a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 32, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa29", + "_tpl": "5449016a4bdc2d6f028b456f", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 1, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 250000 + } + }, { + "_id": "6613bb72b5b0ba138a0faa2a", + "_tpl": "590c661e86f7741e566b646a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 30, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa2b", + "_tpl": "5755383e24597772cb798966", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa2c", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613bb72b5b0ba138a0faa2d", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 12, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa2e", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 12, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa30", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa2f", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa30", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa32", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa31", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa32", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa34", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa33", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa34", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa35", + "_tpl": "56dfef82d2720bbd668b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 16, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613bb72b5b0ba138a0faa37", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa36", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa37", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa38", + "_tpl": "590c5d4b86f774784e1b9c45", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa39", + "_tpl": "590c5d4b86f774784e1b9c45", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa3a", + "_tpl": "590c5d4b86f774784e1b9c45", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa3b", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 32, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613bb72b5b0ba138a0faa3c", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 32, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613bb72b5b0ba138a0faa3d", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 32, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613bb72b5b0ba138a0faa3e", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 29, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa3f", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 29, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa40", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa41", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa42", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa43", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa44", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa45", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa46", + "_tpl": "5755356824597772cb798962", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa47", + "_tpl": "5755356824597772cb798962", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa48", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa49", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa4a", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa4c", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa4b", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa4c", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa4e", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa4d", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa4e", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa4f", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 18, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613bb72b5b0ba138a0faa50", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 11, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa51", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 11, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa52", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 28, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa53", + "_tpl": "5d02778e86f774203e7dedbe", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa54", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa55", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa56", + "_tpl": "590c695186f7741e566b64a2", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa57", + "_tpl": "590c695186f7741e566b64a2", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa58", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa59", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa5a", + "_tpl": "5696686a4bdc2da3298b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613bb72b5b0ba138a0faa5b", + "_tpl": "5696686a4bdc2da3298b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613bb72b5b0ba138a0faa5c", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 18, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613bb72b5b0ba138a0faa5d", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faa5e", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 18, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613bb72b5b0ba138a0faa5f", + "_tpl": "5d1b36a186f7742523398433", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 13, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa60", + "_tpl": "5d1b371186f774253763a656", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 38, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa62", + "_tpl": "559ba5b34bdc2d1f1a8b4582", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa61", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0faa62", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613bb72b5b0ba138a0faa64", + "_tpl": "559ba5b34bdc2d1f1a8b4582", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa63", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0faa64", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613bb72b5b0ba138a0faa65", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa66", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa67", + "_tpl": "5d02778e86f774203e7dedbe", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa68", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa6c", + "_tpl": "5aa7cfc0e5b5b00015693143", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa69", + "_tpl": "657baaf0b7e9ca9a02045c02", + "parentId": "6613bb72b5b0ba138a0faa6c", + "slotId": "Helmet_top" + }, { + "_id": "6613bb72b5b0ba138a0faa6a", + "_tpl": "657bab6ec6f689d3a205b85f", + "parentId": "6613bb72b5b0ba138a0faa6c", + "slotId": "Helmet_back" + }, { + "_id": "6613bb72b5b0ba138a0faa6b", + "_tpl": "657babc6f58ba5a6250107a2", + "parentId": "6613bb72b5b0ba138a0faa6c", + "slotId": "Helmet_ears" + }, { + "_id": "6613bb72b5b0ba138a0faa6d", + "_tpl": "5ab8f39486f7745cd93a1cca", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa6e", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa6f", + "_tpl": "569668774bdc2da2298b4568", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613bb72b5b0ba138a0faa70", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa71", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa72", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa73", + "_tpl": "5d5d940f86f7742797262046", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 29, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa74", + "_tpl": "57cd379a24597778e7682ecf", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 23, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa75", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 22, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 40 + } + }, { + "_id": "6613bb72b5b0ba138a0faa76", + "_tpl": "5710c24ad2720bc3458b45a3", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa77", + "_tpl": "5ab8f39486f7745cd93a1cca", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa78", + "_tpl": "5e2af4a786f7746d3f3c3400", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 39, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa79", + "_tpl": "5d5d85c586f774279a21cbdb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 25, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa7c", + "_tpl": "5b432d215acfc4771e1c6624", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa7a", + "_tpl": "657bb92fa1c61ee0c303631f", + "parentId": "6613bb72b5b0ba138a0faa7c", + "slotId": "Helmet_top" + }, { + "_id": "6613bb72b5b0ba138a0faa7b", + "_tpl": "657bb99db30eca976305117f", + "parentId": "6613bb72b5b0ba138a0faa7c", + "slotId": "Helmet_back" + }, { + "_id": "6613bb72b5b0ba138a0faa7d", + "_tpl": "5e8488fa988a8701445df1e4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa7e", + "_tpl": "5e8488fa988a8701445df1e4", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa7f", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa80", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa81", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 1, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa83", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 28, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa82", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa83", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa84", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 28, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613bb72b5b0ba138a0faa85", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 28, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613bb72b5b0ba138a0faa87", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa86", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa87", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa88", + "_tpl": "5c0e530286f7747fa1419862", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa89", + "_tpl": "5c0e530286f7747fa1419862", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa8a", + "_tpl": "5c0505e00db834001b735073", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 24, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa8c", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 25, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa8b", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa8c", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa8e", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 24, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa8d", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faa8e", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faa8f", + "_tpl": "590c657e86f77412b013051d", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 38, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa90", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa91", + "_tpl": "5b432b965acfc47a8774094e", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa92", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 27, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa93", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa94", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa95", + "_tpl": "5e2af47786f7746d404f3aaa", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 38, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa96", + "_tpl": "5e2af47786f7746d404f3aaa", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 39, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa97", + "_tpl": "5e2af4a786f7746d3f3c3400", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 38, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa98", + "_tpl": "544fb3f34bdc2d03748b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa99", + "_tpl": "544fb3f34bdc2d03748b456a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa9b", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa9a", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa9b", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa9d", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa9c", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa9d", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faa9f", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faa9e", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faa9f", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faaa0", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 6, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faaa1", + "_tpl": "5645bcc04bdc2d363b8b4572", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaa2", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 10, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faaa3", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 7, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faaa4", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 7, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613bb72b5b0ba138a0faaa5", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaa6", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 31, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaa7", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 5, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaa9", + "_tpl": "559ba5b34bdc2d1f1a8b4582", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 8, + "y": 18, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaa8", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0faaa9", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613bb72b5b0ba138a0faaab", + "_tpl": "559ba5b34bdc2d1f1a8b4582", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 9, + "y": 18, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaaa", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0faaab", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613bb72b5b0ba138a0faaac", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 2, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faab5", + "_tpl": "5c0e53c886f7747fa54205c7", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaad", + "_tpl": "656f603f94b480b8a500c0d6", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "front_plate" + }, { + "_id": "6613bb72b5b0ba138a0faaae", + "_tpl": "656efd66034e8e01c407f35c", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "back_plate" + }, { + "_id": "6613bb72b5b0ba138a0faaaf", + "_tpl": "654a8b0b0337d53f9102c2ae", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "soft_armor_front" + }, { + "_id": "6613bb72b5b0ba138a0faab0", + "_tpl": "654a8976f414fcea4004d78b", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "soft_armor_back" + }, { + "_id": "6613bb72b5b0ba138a0faab1", + "_tpl": "654a8b3df414fcea4004d78f", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "soft_armor_left" + }, { + "_id": "6613bb72b5b0ba138a0faab2", + "_tpl": "654a8b80f414fcea4004d797", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "soft_armor_right" + }, { + "_id": "6613bb72b5b0ba138a0faab3", + "_tpl": "654a8ae00337d53f9102c2aa", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "Collar" + }, { + "_id": "6613bb72b5b0ba138a0faab4", + "_tpl": "654a8bc5f414fcea4004d79b", + "parentId": "6613bb72b5b0ba138a0faab5", + "slotId": "Groin" + }, { + "_id": "6613bb72b5b0ba138a0faabc", + "_tpl": "5c0e722886f7740458316a57", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 25, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faab6", + "_tpl": "656fa0fb498d1b7e3e071d9c", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "Front_plate" + }, { + "_id": "6613bb72b5b0ba138a0faab7", + "_tpl": "656fa0fb498d1b7e3e071d9c", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "Back_plate" + }, { + "_id": "6613bb72b5b0ba138a0faab8", + "_tpl": "65730c0e292ecadbfa09ad49", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "Soft_armor_front" + }, { + "_id": "6613bb72b5b0ba138a0faab9", + "_tpl": "65730c2213a2f660f60bea96", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "Soft_armor_back" + }, { + "_id": "6613bb72b5b0ba138a0faaba", + "_tpl": "65730c2b292ecadbfa09ad50", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "Soft_armor_left" + }, { + "_id": "6613bb72b5b0ba138a0faabb", + "_tpl": "65730c35292ecadbfa09ad54", + "parentId": "6613bb72b5b0ba138a0faabc", + "slotId": "soft_armor_right" + }, { + "_id": "6613bb72b5b0ba138a0faac0", + "_tpl": "576a581d2459771e7b1bc4f1", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 4, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faabe", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0faac0", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faabd", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faabe", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faabf", + "_tpl": "576a63cd2459771e796e0e11", + "parentId": "6613bb72b5b0ba138a0faac0", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faaca", + "_tpl": "59984ab886f7743e98271174", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faac1", + "_tpl": "5998517986f7746017232f7e", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faac2", + "_tpl": "599851db86f77467372f0a18", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0faac4", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faac3", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faac4", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faac5", + "_tpl": "5998597786f77414ea6da093", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0faac6", + "_tpl": "59985a8086f77414ec448d1a", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_reciever" + }, { + "_id": "6613bb72b5b0ba138a0faac7", + "_tpl": "599860e986f7743bb57573a6", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0faac9", + "_tpl": "59ccd11386f77428f24a488f", + "parentId": "6613bb72b5b0ba138a0faaca", + "slotId": "mod_gas_block" + }, { + "_id": "6613bb72b5b0ba138a0faac8", + "_tpl": "5648b1504bdc2d9d488b4584", + "parentId": "6613bb72b5b0ba138a0faac9", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0faace", + "_tpl": "576a581d2459771e7b1bc4f1", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faacc", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0faace", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faacb", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faacc", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faacd", + "_tpl": "576a63cd2459771e796e0e11", + "parentId": "6613bb72b5b0ba138a0faace", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faad2", + "_tpl": "576a581d2459771e7b1bc4f1", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 3, + "y": 5, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faad0", + "_tpl": "576a5ed62459771e9c2096cb", + "parentId": "6613bb72b5b0ba138a0faad2", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faacf", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faad0", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 18 + } + }, { + "_id": "6613bb72b5b0ba138a0faad1", + "_tpl": "576a63cd2459771e796e0e11", + "parentId": "6613bb72b5b0ba138a0faad2", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faadc", + "_tpl": "59984ab886f7743e98271174", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faad3", + "_tpl": "5998517986f7746017232f7e", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faad4", + "_tpl": "599851db86f77467372f0a18", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0faad6", + "_tpl": "599860ac86f77436b225ed1a", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faad5", + "_tpl": "56d59d3ad2720bdb418b4577", + "parentId": "6613bb72b5b0ba138a0faad6", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faad7", + "_tpl": "5998597786f77414ea6da093", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0faad8", + "_tpl": "59985a8086f77414ec448d1a", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_reciever" + }, { + "_id": "6613bb72b5b0ba138a0faad9", + "_tpl": "599860e986f7743bb57573a6", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0faadb", + "_tpl": "59ccd11386f77428f24a488f", + "parentId": "6613bb72b5b0ba138a0faadc", + "slotId": "mod_gas_block" + }, { + "_id": "6613bb72b5b0ba138a0faada", + "_tpl": "5648b1504bdc2d9d488b4584", + "parentId": "6613bb72b5b0ba138a0faadb", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0faae6", + "_tpl": "5ac4cd105acfc40016339859", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faade", + "_tpl": "59c6633186f7740cf0493bb9", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_gas_block" + }, { + "_id": "6613bb72b5b0ba138a0faadd", + "_tpl": "5648b1504bdc2d9d488b4584", + "parentId": "6613bb72b5b0ba138a0faade", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0faadf", + "_tpl": "5ac7655e5acfc40016339a19", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0faae0", + "_tpl": "5649ade84bdc2d1b2b8b4587", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faae1", + "_tpl": "5ac50da15acfc4001718d287", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_reciever" + }, { + "_id": "6613bb72b5b0ba138a0faae2", + "_tpl": "5ac72e475acfc400180ae6fe", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0faae3", + "_tpl": "5ac50c185acfc400163398d4", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0faae5", + "_tpl": "55d480c04bdc2d1d4e8b456a", + "parentId": "6613bb72b5b0ba138a0faae6", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faae4", + "_tpl": "56dfef82d2720bbd668b4567", + "parentId": "6613bb72b5b0ba138a0faae5", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faaef", + "_tpl": "5e870397991fd70db46995c8", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 0, + "y": 18, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faae8", + "_tpl": "5e87071478f43e51ca2de5e1", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "mod_barrel" + }, { + "_id": "6613bb72b5b0ba138a0faae7", + "_tpl": "5e8708d4ae379e67d22e0102", + "parentId": "6613bb72b5b0ba138a0faae8", + "slotId": "mod_sight_front" + }, { + "_id": "6613bb72b5b0ba138a0faae9", + "_tpl": "5e87076ce2db31558c75a11d", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0faaeb", + "_tpl": "5e87080c81c4ed43e83cefda", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faaea", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613bb72b5b0ba138a0faaeb", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 8 + } + }, { + "_id": "6613bb72b5b0ba138a0faaec", + "_tpl": "5e87116b81c4ed43e83cefdd", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0faaed", + "_tpl": "5e87114fe2db31558c75a120", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "mod_mount" + }, { + "_id": "6613bb72b5b0ba138a0faaee", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613bb72b5b0ba138a0faaef", + "slotId": "patron_in_weapon" + }, { + "_id": "6613bb72b5b0ba138a0faafd", + "_tpl": "6499849fc93611967b034949", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 7, + "y": 25, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaf0", + "_tpl": "649ec107961514b22506b10c", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_gas_block" + }, { + "_id": "6613bb72b5b0ba138a0faaf1", + "_tpl": "649ec2af961514b22506b10f", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0faaf2", + "_tpl": "5beec8ea0db834001a6f9dbf", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613bb72b5b0ba138a0faaf5", + "_tpl": "649ec2f3961514b22506b111", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_reciever" + }, { + "_id": "6613bb72b5b0ba138a0faaf4", + "_tpl": "649ec2da59cbb3c813042dca", + "parentId": "6613bb72b5b0ba138a0faaf5", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0faaf3", + "_tpl": "649ec2cec93611967b03495e", + "parentId": "6613bb72b5b0ba138a0faaf4", + "slotId": "mod_sight_rear" + }, { + "_id": "6613bb72b5b0ba138a0faaf7", + "_tpl": "649ec87d8007560a9001ab36", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_stock_001" + }, { + "_id": "6613bb72b5b0ba138a0faaf6", + "_tpl": "5beec8c20db834001d2c465c", + "parentId": "6613bb72b5b0ba138a0faaf7", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0faaf9", + "_tpl": "649ec30cb013f04a700e60fb", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faaf8", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faaf9", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613bb72b5b0ba138a0faafb", + "_tpl": "649ec127c93611967b034957", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "mod_handguard" + }, { + "_id": "6613bb72b5b0ba138a0faafa", + "_tpl": "5beecbb80db834001d2c465e", + "parentId": "6613bb72b5b0ba138a0faafb", + "slotId": "mod_mount_001" + }, { + "_id": "6613bb72b5b0ba138a0faafc", + "_tpl": "56dff3afd2720bba668b4567", + "parentId": "6613bb72b5b0ba138a0faafd", + "slotId": "patron_in_weapon" + }, { + "_id": "6613bb72b5b0ba138a0fab06", + "_tpl": "55801eed4bdc2d89578b4588", + "parentId": "6613bb72b5b0ba138a0fab07", + "slotId": "hideout", + "location": { + "x": 4, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613bb72b5b0ba138a0faaff", + "_tpl": "559ba5b34bdc2d1f1a8b4582", + "parentId": "6613bb72b5b0ba138a0fab06", + "slotId": "mod_magazine" + }, { + "_id": "6613bb72b5b0ba138a0faafe", + "_tpl": "5887431f2459777e1612938f", + "parentId": "6613bb72b5b0ba138a0faaff", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613bb72b5b0ba138a0fab01", + "_tpl": "5d0a29fed7ad1a002769ad08", + "parentId": "6613bb72b5b0ba138a0fab06", + "slotId": "mod_scope" + }, { + "_id": "6613bb72b5b0ba138a0fab00", + "_tpl": "5d0a3e8cd7ad1a6f6a3d35bd", + "parentId": "6613bb72b5b0ba138a0fab01", + "slotId": "mod_scope" + }, { + "_id": "6613bb72b5b0ba138a0fab02", + "_tpl": "56083eab4bdc2d26448b456a", + "parentId": "6613bb72b5b0ba138a0fab06", + "slotId": "mod_tactical" + }, { + "_id": "6613bb72b5b0ba138a0fab03", + "_tpl": "560e620e4bdc2d724b8b456b", + "parentId": "6613bb72b5b0ba138a0fab06", + "slotId": "mod_muzzle" + }, { + "_id": "6613bb72b5b0ba138a0fab05", + "_tpl": "61faa91878830f069b6b7967", + "parentId": "6613bb72b5b0ba138a0fab06", + "slotId": "mod_stock" + }, { + "_id": "6613bb72b5b0ba138a0fab04", + "_tpl": "56ea8222d2720b69698b4567", + "parentId": "6613bb72b5b0ba138a0fab05", + "slotId": "mod_bipod" + }, { + "_id": "6613bb72b5b0ba138a0fab0a", + "_tpl": "602543c13fee350cd564d032" + }, { + "_id": "6613bb72b5b0ba138a0fab09", + "_tpl": "5963866b86f7747bfa1c4462" + }, { + "_id": "6613bb72b5b0ba138a0fab08", + "_tpl": "5963866286f7747bf429b572" + } + ], + "questRaidItems": "6613bb72b5b0ba138a0fab08", + "questStashItems": "6613bb72b5b0ba138a0fab09", + "sortingTable": "6613bb72b5b0ba138a0fab0a", + "stash": "6613bb72b5b0ba138a0fab07" }, "Notes": { "Notes": [] @@ -24254,3548 +23629,2955 @@ }, "InsuredItems": [], "Inventory": { - "equipment": "5fe49a0e2694b0755a50476c", + "equipment": "6613e1cf291a2e76b00269a8", "fastPanel": {}, "hideoutAreaStashes": {}, - "items": [{ - "_id": "5fe49a0e2694b0755a50476c", - "_tpl": "55d7217a4bdc2d86028b456d" - }, { - "_id": "63db64cbf9963741dc0d741f", - "_tpl": "6401c7b213d9b818bf0e7dd7" - }, { - "_id": "5fe49a0e2694b0755a504755", - "_tpl": "5447a9cd4bdc2dbd208b4567", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "FirstPrimaryWeapon", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504749", - "_tpl": "55d4b9964bdc2d1d4e8b456e", - "parentId": "5fe49a0e2694b0755a504755", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a50474b", - "_tpl": "55d4887d4bdc2d962f8b4570", - "parentId": "5fe49a0e2694b0755a504755", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a50474a", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50474b", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a504751", - "_tpl": "55d355e64bdc2d962f8b4569", - "parentId": "5fe49a0e2694b0755a504755", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a50474e", - "_tpl": "55d3632e4bdc2d972f8b4569", - "parentId": "5fe49a0e2694b0755a504751", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a50474c", - "_tpl": "544a38634bdc2d58388b4568", - "parentId": "5fe49a0e2694b0755a50474e", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a50474d", - "_tpl": "5ae30e795acfc408fb139a0b", - "parentId": "5fe49a0e2694b0755a50474e", - "slotId": "mod_gas_block" - }, { - "_id": "5fe49a0e2694b0755a50474f", - "_tpl": "5ae30db85acfc408fb139a05", - "parentId": "5fe49a0e2694b0755a504751", - "slotId": "mod_handguard" - }, { - "_id": "6396b722d604e334650f972e", - "_tpl": "637f57a68d137b27f70c4968", - "parentId": "5fe49a0e2694b0755a50474f", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a504750", - "_tpl": "5ae30bad5acfc400185c2dc4", - "parentId": "5fe49a0e2694b0755a504751", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504753", - "_tpl": "5649be884bdc2d79388b4577", - "parentId": "5fe49a0e2694b0755a504755", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a504752", - "_tpl": "55d4ae6c4bdc2d8b2f8b456e", - "parentId": "5fe49a0e2694b0755a504753", - "slotId": "mod_stock_000" - }, { - "_id": "5fe49a0e2694b0755a504754", - "_tpl": "55d44fd14bdc2d962f8b456e", - "parentId": "5fe49a0e2694b0755a504755", - "slotId": "mod_charge" - }, { - "_id": "5fe49a0e2694b0755a504756", - "_tpl": "54491bb74bdc2d09088b4567", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "Scabbard", - "upd": { - "Repairable": { - "Durability": 70, - "MaxDurability": 70 - } - } - }, { - "_id": "5fe49a0e2694b0755a504757", - "_tpl": "572b7fa524597762b747ce82", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "FaceCover", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504758", - "_tpl": "5aa2a7e8e5b5b00016327c16", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "Headwear", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "5fe49a0e2694b0755a504760", - "_tpl": "5c0e9f2c86f77432297fe0a3", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "TacticalVest" - }, { - "_id": "5fe49a0e2694b0755a50475a", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504760", - "slotId": "1" - }, { - "_id": "5fe49a0e2694b0755a504759", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50475a", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50475c", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504760", - "slotId": "2" - }, { - "_id": "5fe49a0e2694b0755a50475b", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50475c", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50475e", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504760", - "slotId": "3" - }, { - "_id": "5fe49a0e2694b0755a50475d", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50475e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50475f", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504760", - "slotId": "4", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504761", - "_tpl": "5857a8bc2459772bad15db29", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "SecuredContainer" - }, { - "_id": "5fe49a0e2694b0755a504765", - "_tpl": "5e9dcf5986f7746c417435b3", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "Backpack" - }, { - "_id": "5fe49a0e2694b0755a504762", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504765", - "slotId": "main", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "5fe49a0e2694b0755a504763", - "_tpl": "590c5f0d86f77413997acfab", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504765", - "slotId": "main", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a504764", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504765", - "slotId": "main", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "5fe49a0e2694b0755a504766", - "_tpl": "5648a7494bdc2d9d488b4583", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "ArmorVest", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "5fe49a0e2694b0755a504766", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "5fe49a0e2694b0755a504766", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "5fe49a0e2694b0755a504766", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "5fe49a0e2694b0755a504766", - "slotId": "soft_armor_right" - }, { - "_id": "5fe49a0e2694b0755a50476a", - "_tpl": "627a4e6b255f7527fb05a0f6", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "Pockets" - }, { - "_id": "5fe49a0e2694b0755a504767", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a50476a", - "slotId": "pocket1" - }, { - "_id": "5fe49a0e2694b0755a504768", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a50476a", - "slotId": "pocket2", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "5fe49a0e2694b0755a504769", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a50476a", - "slotId": "pocket3", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "5fe49a0e2694b0755a50476b", - "_tpl": "5645bcc04bdc2d363b8b4572", - "parentId": "5fe49a0e2694b0755a50476c", - "slotId": "Earpiece" - }, { - "_id": "5fe49a0e2694b0755a504876", - "_tpl": "5811ce772459770e9e5f9532" - }, { - "_id": "5fe49a0e2694b0755a50476d", - "_tpl": "590c5f0d86f77413997acfab", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a50476e", - "_tpl": "5e9dcf5986f7746c417435b3", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 9 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50476f", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504771", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 4 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504770", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504771", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a504773", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504772", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a504773", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a504774", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "5fe49a0e2694b0755a504775", - "_tpl": "590c661e86f7741e566b646a", - "location": { - "isSearched": true, - "r": 1, - "x": 9, - "y": 31 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 220 - } - } - }, { - "_id": "5fe49a0e2694b0755a504776", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 31 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504777", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504779", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 15 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504778", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a504779", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50477a", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a50477b", - "_tpl": "590c5f0d86f77413997acfab", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a50477d", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50477c", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50477d", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50477e", - "_tpl": "58d3db5386f77426186285a0", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 13 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50477f", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "5fe49a0e2694b0755a504780", - "_tpl": "590c661e86f7741e566b646a", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 220 - } - } - }, { - "_id": "5fe49a0e2694b0755a504781", - "_tpl": "5ab8f39486f7745cd93a1cca", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 25 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504782", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504783", - "_tpl": "58d3db5386f77426186285a0", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 13 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504785", - "_tpl": "5bfeaa0f0db834001b734927", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504784", - "_tpl": "58dd3ad986f77403051cba8f", - "parentId": "5fe49a0e2694b0755a504785", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "5fe49a0e2694b0755a504786", - "_tpl": "5e4d34ca86f774264f758330", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 11 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504787", - "_tpl": "5aa2a7e8e5b5b00016327c16", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "5fe49a0e2694b0755a504788", - "_tpl": "5c0e9f2c86f77432297fe0a3", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 3 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504789", - "_tpl": "590c5f0d86f77413997acfab", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a50478a", - "_tpl": "5aa2a7e8e5b5b00016327c16", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 10, - "MaxDurability": 10 - } - } - }, { - "_id": "5fe49a0e2694b0755a50478b", - "_tpl": "5648a7494bdc2d9d488b4583", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 3 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "5fe49a0e2694b0755a50478b", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "5fe49a0e2694b0755a50478b", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "5fe49a0e2694b0755a50478b", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "5fe49a0e2694b0755a50478b", - "slotId": "soft_armor_right" - }, { - "_id": "5fe49a0e2694b0755a50478c", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50478d", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 31 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a50478f", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50478e", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a50478f", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a504790", - "_tpl": "5e4d34ca86f774264f758330", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 9 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504791", - "_tpl": "5d403f9186f7743cac3f229b", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a504792", - "_tpl": "5c0e9f2c86f77432297fe0a3", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504793", - "_tpl": "5648a7494bdc2d9d488b4583", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 0 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 50, - "MaxDurability": 50 - } - } - }, { - "_id": "658c3f38bb2016e5630bdbe5", - "_tpl": "65703d866584602f7d057a8a", - "parentId": "5fe49a0e2694b0755a504793", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3f38bb2016e5630bdbe6", - "_tpl": "65703fa06584602f7d057a8e", - "parentId": "5fe49a0e2694b0755a504793", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3f38bb2016e5630bdbe7", - "_tpl": "65703fe46a912c8b5c03468b", - "parentId": "5fe49a0e2694b0755a504793", - "slotId": "Soft_armor_left" - }, { - "_id": "658c3f38bb2016e5630bdbe8", - "_tpl": "657040374e67e8ec7a0d261c", - "parentId": "5fe49a0e2694b0755a504793", - "slotId": "soft_armor_right" - }, { - "_id": "5fe49a0e2694b0755a504794", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504795", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504796", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504797", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504798", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504799", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "5fe49a0e2694b0755a50479b", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 5 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50479a", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a50479b", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a50479c", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a50479d", - "_tpl": "5e9dcf5986f7746c417435b3", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 9 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50479e", - "_tpl": "590c695186f7741e566b64a2", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50479f", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047a0", - "_tpl": "590c695186f7741e566b64a2", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047a1", - "_tpl": "5751a25924597722c463c472", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 2 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047a3", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047a2", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047a3", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047a5", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047a4", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047a5", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a5047a7", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047a6", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047a7", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047a9", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047a8", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047a9", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047ab", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047aa", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047ab", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047ac", - "_tpl": "5755383e24597772cb798966", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 6 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047ae", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 1, - "x": 3, - "y": 25 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047ad", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a5047ae", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a5047af", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047b0", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047b1", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047b2", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047b3", - "_tpl": "5696686a4bdc2da3298b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 2 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "5fe49a0e2694b0755a5047b4", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047b6", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 3 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047b5", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047b6", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a5047b8", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047b7", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047b8", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047b9", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047ba", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047bb", - "_tpl": "64b7bbb74b75259c590fa897", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 8 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 50 - } - }, { - "_id": "5fe49a0e2694b0755a5047bc", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 31 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047bd", - "_tpl": "5e831507ea0a7c419c2f9bd9", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047be", - "_tpl": "5449016a4bdc2d6f028b456f", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 1 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 250000 - } - }, { - "_id": "5fe49a0e2694b0755a5047bf", - "_tpl": "5449016a4bdc2d6f028b456f", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 1 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 250000 - } - }, { - "_id": "5fe49a0e2694b0755a5047c1", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047c0", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a5047c1", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a5047c2", - "_tpl": "5e8488fa988a8701445df1e4", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 3 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047c3", - "_tpl": "569668774bdc2da2298b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 2 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "5fe49a0e2694b0755a5047c5", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047c4", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047c5", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a5047c7", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047c6", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047c7", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047c9", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047c8", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047c9", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a5047cb", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047ca", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a5047cb", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a5047cc", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 16 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047cd", - "_tpl": "5a0c27731526d80618476ac4", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 15 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047ce", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047cf", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 28 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d0", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d1", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 27 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d2", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047d3", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047d4", - "_tpl": "560d5e524bdc2d25448b4571", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a5047d5", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047d6", - "_tpl": "5755356824597772cb798962", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 31 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d7", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 1, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d8", - "_tpl": "5d02778e86f774203e7dedbe", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047d9", - "_tpl": "5c0e655586f774045612eeb2", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 85, - "MaxDurability": 85 - } - } - }, { - "_id": "658c3d4dab989d7f4805edbb", - "_tpl": "656fad8c498d1b7e3e071da0", - "parentId": "5fe49a0e2694b0755a5047d9", - "slotId": "Front_plate" - }, { - "_id": "658c3d4dab989d7f4805edbc", - "_tpl": "656fad8c498d1b7e3e071da0", - "parentId": "5fe49a0e2694b0755a5047d9", - "slotId": "Back_plate" - }, { - "_id": "658c3d4dab989d7f4805edbd", - "_tpl": "6570e025615f54368b04fcb0", - "parentId": "5fe49a0e2694b0755a5047d9", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3d4dab989d7f4805edbe", - "_tpl": "6570e0610b57c03ec90b96ef", - "parentId": "5fe49a0e2694b0755a5047d9", - "slotId": "Soft_armor_back" - }, { - "_id": "5fe49a0e2694b0755a5047da", - "_tpl": "5c165d832e2216398b5a7e36", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 21 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047db", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047dc", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047dd", - "_tpl": "5af0454c86f7746bf20992e8", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 33 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047de", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047df", - "_tpl": "5ab8f39486f7745cd93a1cca", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 25 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047e0", - "_tpl": "557ff21e4bdc2d89578b4586", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 22 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047e1", - "_tpl": "5bfebc5e0db834001a6694e5", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047e2", - "_tpl": "57c5ac0824597754771e88a9", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 16 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047e3", - "_tpl": "5aa7d03ae5b5b00016327db5", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 25, - "MaxDurability": 25 - } - } - }, { - "_id": "658c3d4dab989d7f4805edc9", - "_tpl": "654a90aff4f81a421b0a7c86", - "parentId": "5fe49a0e2694b0755a5047e3", - "slotId": "helmet_top" - }, { - "_id": "658c3d4dab989d7f4805edca", - "_tpl": "654a91068e1ce698150fd1e2", - "parentId": "5fe49a0e2694b0755a5047e3", - "slotId": "helmet_back" - }, { - "_id": "658c3d4dab989d7f4805edcb", - "_tpl": "654a9189bcc67a392b056c79", - "parentId": "5fe49a0e2694b0755a5047e3", - "slotId": "helmet_ears" - }, { - "_id": "5fe49a0e2694b0755a5047e4", - "_tpl": "5aa7d03ae5b5b00016327db5", - "location": { - "isSearched": true, - "r": 0, - "x": 2, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 25, - "MaxDurability": 25 - } - } - }, { - "_id": "658c3d4dab989d7f4805edcd", - "_tpl": "654a90aff4f81a421b0a7c86", - "parentId": "5fe49a0e2694b0755a5047e4", - "slotId": "helmet_top" - }, { - "_id": "658c3d4dab989d7f4805edce", - "_tpl": "654a91068e1ce698150fd1e2", - "parentId": "5fe49a0e2694b0755a5047e4", - "slotId": "helmet_back" - }, { - "_id": "658c3d4dab989d7f4805edcf", - "_tpl": "654a9189bcc67a392b056c79", - "parentId": "5fe49a0e2694b0755a5047e4", - "slotId": "helmet_ears" - }, { - "_id": "5fe49a0e2694b0755a5047e5", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047e6", - "_tpl": "544fb37f4bdc2dee738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 4 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047e7", - "_tpl": "58d3db5386f77426186285a0", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047e8", - "_tpl": "58d3db5386f77426186285a0", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047e9", - "_tpl": "58d3db5386f77426186285a0", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047eb", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 24 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047ea", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a5047eb", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a5047ec", - "_tpl": "5d1b371186f774253763a656", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 37 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 60 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047ed", - "_tpl": "5d1b36a186f7742523398433", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 37 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047ee", - "_tpl": "544fb45d4bdc2dee738b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 400 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047ef", - "_tpl": "557ff21e4bdc2d89578b4586", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 23 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047f0", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 29 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047f1", - "_tpl": "5d02778e86f774203e7dedbe", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 32 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 5 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047f2", - "_tpl": "5d5d940f86f7742797262046", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 27 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047f3", - "_tpl": "57cd379a24597778e7682ecf", - "location": { - "isSearched": true, - "r": 1, - "x": 0, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047f4", - "_tpl": "544a5caa4bdc2d1a388b4568", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 22 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 70, - "MaxDurability": 70 - } - } - }, { - "_id": "658c3d4dab989d7f4805ede0", - "_tpl": "656f9fa0498d1b7e3e071d98", - "parentId": "5fe49a0e2694b0755a5047f4", - "slotId": "Front_plate" - }, { - "_id": "658c3d4dab989d7f4805ede1", - "_tpl": "656f9fa0498d1b7e3e071d98", - "parentId": "5fe49a0e2694b0755a5047f4", - "slotId": "Back_plate" - }, { - "_id": "658c3d4dab989d7f4805ede2", - "_tpl": "6570e83223c1f638ef0b0ede", - "parentId": "5fe49a0e2694b0755a5047f4", - "slotId": "Soft_armor_front" - }, { - "_id": "658c3d4dab989d7f4805ede3", - "_tpl": "6570e87c23c1f638ef0b0ee2", - "parentId": "5fe49a0e2694b0755a5047f4", - "slotId": "Soft_armor_back" - }, { - "_id": "658c3d4dab989d7f4805ede4", - "_tpl": "6570e90b3a5689d85f08db97", - "parentId": "5fe49a0e2694b0755a5047f4", - "slotId": "Groin" - }, { - "_id": "5fe49a0e2694b0755a5047f5", - "_tpl": "5d5d85c586f774279a21cbdb", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 22 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047f6", - "_tpl": "5e2af4a786f7746d3f3c3400", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047f7", - "_tpl": "570fd6c2d2720bc6458b457f", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047f8", - "_tpl": "5448be9a4bdc2dfd2f8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047f9", - "_tpl": "5448be9a4bdc2dfd2f8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 21 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047fa", - "_tpl": "590c657e86f77412b013051d", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 37 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 1800 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047fb", - "_tpl": "5d5e9c74a4b9364855191c40", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 17 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Repairable": { - "Durability": 27, - "MaxDurability": 27 - } - } - }, { - "_id": "658c3d4dab989d7f4805edec", - "_tpl": "657f8b94f92cd718b70154ff", - "parentId": "5fe49a0e2694b0755a5047fb", - "slotId": "Helmet_top" - }, { - "_id": "658c3d4dab989d7f4805eded", - "_tpl": "657f8b43f92cd718b70154fb", - "parentId": "5fe49a0e2694b0755a5047fb", - "slotId": "Helmet_back" - }, { - "_id": "5fe49a0e2694b0755a5047fd", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 1, - "x": 3, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a5047fc", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a5047fd", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a5047fe", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "5fe49a0e2694b0755a5047ff", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "5fe49a0e2694b0755a504800", - "_tpl": "590c678286f77426c9660122", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 300 - } - } - }, { - "_id": "5fe49a0e2694b0755a504802", - "_tpl": "55d4887d4bdc2d962f8b4570", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 24 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504801", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a504802", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a504803", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 29 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "5fe49a0e2694b0755a504804", - "_tpl": "5e8488fa988a8701445df1e4", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 36 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "MedKit": { - "HpResource": 3 - } - } - }, { - "_id": "5fe49a0e2694b0755a504805", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 60 - } - }, { - "_id": "5fe49a0e2694b0755a504806", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 26 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a504807", - "_tpl": "5c0e530286f7747fa1419862", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504808", - "_tpl": "5c0e530286f7747fa1419862", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504809", - "_tpl": "54527a984bdc2d4e668b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 25 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50480a", - "_tpl": "5696686a4bdc2da3298b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 2 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 500 - } - }, { - "_id": "5fe49a0e2694b0755a50480c", - "_tpl": "5bfeaa0f0db834001b734927", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50480b", - "_tpl": "58dd3ad986f77403051cba8f", - "parentId": "5fe49a0e2694b0755a50480c", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "5fe49a0e2694b0755a50480e", - "_tpl": "5bfeaa0f0db834001b734927", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50480d", - "_tpl": "58dd3ad986f77403051cba8f", - "parentId": "5fe49a0e2694b0755a50480e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "5fe49a0e2694b0755a504810", - "_tpl": "5bfeaa0f0db834001b734927", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 20 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50480f", - "_tpl": "58dd3ad986f77403051cba8f", - "parentId": "5fe49a0e2694b0755a504810", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "5fe49a0e2694b0755a504811", - "_tpl": "58dd3ad986f77403051cba8f", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 19 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a504812", - "_tpl": "5448fee04bdc2dbc018b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 29 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 60 - } - } - }, { - "_id": "5fe49a0e2694b0755a504813", - "_tpl": "544fb3364bdc2d34748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 34 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504815", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504814", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504815", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a504817", - "_tpl": "5d2f213448f0355009199284", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 7 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504816", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504817", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a504819", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "location": { - "isSearched": true, - "r": 0, - "x": 6, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504818", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504819", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a50481a", - "_tpl": "544fb3f34bdc2d03748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 30 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50481b", - "_tpl": "544fb3f34bdc2d03748b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 30 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50481c", - "_tpl": "5e2af47786f7746d404f3aaa", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 38 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50481d", - "_tpl": "5e2af4a786f7746d3f3c3400", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 37 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50481e", - "_tpl": "5e2af47786f7746d404f3aaa", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 39 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "Resource": { - "Value": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50481f", - "_tpl": "58dd3ad986f77403051cba8f", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 16 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a504820", - "_tpl": "5448be9a4bdc2dfd2f8b456a", - "location": { - "isSearched": true, - "r": 0, - "x": 4, - "y": 21 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504821", - "_tpl": "5645bcc04bdc2d363b8b4572", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 23 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a504822", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 8, - "y": 29 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a504823", - "_tpl": "57347da92459774491567cf5", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 29 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FoodDrink": { - "HpPercent": 1 - } - } - }, { - "_id": "5fe49a0e2694b0755a504824", - "_tpl": "544fb25a4bdc2dfb738b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 9, - "y": 35 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout" - }, { - "_id": "5fe49a0e2694b0755a50482d", - "_tpl": "5cadc190ae921500103bb3b6", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 5 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504826", - "_tpl": "5cadc1c6ae9215000f2775a4", - "parentId": "5fe49a0e2694b0755a50482d", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a504825", - "_tpl": "5cadc390ae921500126a77f1", - "parentId": "5fe49a0e2694b0755a504826", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a504827", - "_tpl": "5cadc431ae921500113bb8d5", - "parentId": "5fe49a0e2694b0755a50482d", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a50482a", - "_tpl": "5cadc55cae921500103bb3be", - "parentId": "5fe49a0e2694b0755a50482d", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a504828", - "_tpl": "5cadd940ae9215051e1c2316", - "parentId": "5fe49a0e2694b0755a50482a", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504829", - "_tpl": "5cadd919ae921500126a77f3", - "parentId": "5fe49a0e2694b0755a50482a", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50482c", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "parentId": "5fe49a0e2694b0755a50482d", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a50482b", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a50482c", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a504836", - "_tpl": "5cadc190ae921500103bb3b6", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 4 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a50482f", - "_tpl": "5cadc1c6ae9215000f2775a4", - "parentId": "5fe49a0e2694b0755a504836", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a50482e", - "_tpl": "5cadc390ae921500126a77f1", - "parentId": "5fe49a0e2694b0755a50482f", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a504830", - "_tpl": "5cadc431ae921500113bb8d5", - "parentId": "5fe49a0e2694b0755a504836", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a504833", - "_tpl": "5cadc55cae921500103bb3be", - "parentId": "5fe49a0e2694b0755a504836", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a504831", - "_tpl": "5cadd940ae9215051e1c2316", - "parentId": "5fe49a0e2694b0755a504833", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504832", - "_tpl": "5cadd919ae921500126a77f3", - "parentId": "5fe49a0e2694b0755a504833", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504835", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "parentId": "5fe49a0e2694b0755a504836", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a504834", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504835", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a504843", - "_tpl": "5447a9cd4bdc2dbd208b4567", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 14 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504837", - "_tpl": "55d4b9964bdc2d1d4e8b456e", - "parentId": "5fe49a0e2694b0755a504843", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a504839", - "_tpl": "55d4887d4bdc2d962f8b4570", - "parentId": "5fe49a0e2694b0755a504843", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a504838", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a504839", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a50483f", - "_tpl": "55d355e64bdc2d962f8b4569", - "parentId": "5fe49a0e2694b0755a504843", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a50483c", - "_tpl": "55d3632e4bdc2d972f8b4569", - "parentId": "5fe49a0e2694b0755a50483f", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a50483a", - "_tpl": "544a38634bdc2d58388b4568", - "parentId": "5fe49a0e2694b0755a50483c", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a50483b", - "_tpl": "5ae30e795acfc408fb139a0b", - "parentId": "5fe49a0e2694b0755a50483c", - "slotId": "mod_gas_block" - }, { - "_id": "5fe49a0e2694b0755a50483d", - "_tpl": "5ae30db85acfc408fb139a05", - "parentId": "5fe49a0e2694b0755a50483f", - "slotId": "mod_handguard" - }, { - "_id": "6396b722d604e334650f972e", - "_tpl": "637f57a68d137b27f70c4968", - "parentId": "5fe49a0e2694b0755a50483d", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a50483e", - "_tpl": "5ae30bad5acfc400185c2dc4", - "parentId": "5fe49a0e2694b0755a50483f", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504841", - "_tpl": "5649be884bdc2d79388b4577", - "parentId": "5fe49a0e2694b0755a504843", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a504840", - "_tpl": "55d4ae6c4bdc2d8b2f8b456e", - "parentId": "5fe49a0e2694b0755a504841", - "slotId": "mod_stock_000" - }, { - "_id": "5fe49a0e2694b0755a504842", - "_tpl": "55d44fd14bdc2d962f8b456e", - "parentId": "5fe49a0e2694b0755a504843", - "slotId": "mod_charge" - }, { - "_id": "5fe49a0e2694b0755a50484c", - "_tpl": "5926bb2186f7744b1c6c6e60", - "location": { - "isSearched": true, - "r": 0, - "x": 7, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504845", - "_tpl": "5d2f213448f0355009199284", - "parentId": "5fe49a0e2694b0755a50484c", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a504844", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a504845", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a50484a", - "_tpl": "5926c0df86f77462f647f764", - "parentId": "5fe49a0e2694b0755a50484c", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a504846", - "_tpl": "5926c36d86f77467a92a8629", - "parentId": "5fe49a0e2694b0755a50484a", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a504847", - "_tpl": "5926d2be86f774134d668e4e", - "parentId": "5fe49a0e2694b0755a50484a", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504848", - "_tpl": "5926d3c686f77410de68ebc8", - "parentId": "5fe49a0e2694b0755a50484a", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a504849", - "_tpl": "5926e16e86f7742f5a0f7ecb", - "parentId": "5fe49a0e2694b0755a50484a", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a50484b", - "_tpl": "5926c32286f774616e42de99", - "parentId": "5fe49a0e2694b0755a50484c", - "slotId": "mod_charge" - }, { - "_id": "5fe49a0e2694b0755a504855", - "_tpl": "5926bb2186f7744b1c6c6e60", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 6 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a50484e", - "_tpl": "5d2f213448f0355009199284", - "parentId": "5fe49a0e2694b0755a504855", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a50484d", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a50484e", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 20 - } - }, { - "_id": "5fe49a0e2694b0755a504853", - "_tpl": "5926c0df86f77462f647f764", - "parentId": "5fe49a0e2694b0755a504855", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a50484f", - "_tpl": "5926c36d86f77467a92a8629", - "parentId": "5fe49a0e2694b0755a504853", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a504850", - "_tpl": "5926d2be86f774134d668e4e", - "parentId": "5fe49a0e2694b0755a504853", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504851", - "_tpl": "5926d3c686f77410de68ebc8", - "parentId": "5fe49a0e2694b0755a504853", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a504852", - "_tpl": "5926e16e86f7742f5a0f7ecb", - "parentId": "5fe49a0e2694b0755a504853", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a504854", - "_tpl": "5926c32286f774616e42de99", - "parentId": "5fe49a0e2694b0755a504855", - "slotId": "mod_charge" - }, { - "_id": "5fe49a0e2694b0755a50485e", - "_tpl": "5cadc190ae921500103bb3b6", - "location": { - "isSearched": true, - "r": 0, - "x": 3, - "y": 3 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504857", - "_tpl": "5cadc1c6ae9215000f2775a4", - "parentId": "5fe49a0e2694b0755a50485e", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a504856", - "_tpl": "5cadc390ae921500126a77f1", - "parentId": "5fe49a0e2694b0755a504857", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a504858", - "_tpl": "5cadc431ae921500113bb8d5", - "parentId": "5fe49a0e2694b0755a50485e", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a50485b", - "_tpl": "5cadc55cae921500103bb3be", - "parentId": "5fe49a0e2694b0755a50485e", - "slotId": "mod_reciever" - }, { - "_id": "5fe49a0e2694b0755a504859", - "_tpl": "5cadd940ae9215051e1c2316", - "parentId": "5fe49a0e2694b0755a50485b", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50485a", - "_tpl": "5cadd919ae921500126a77f3", - "parentId": "5fe49a0e2694b0755a50485b", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a50485d", - "_tpl": "5cadc2e0ae9215051e1c21e7", - "parentId": "5fe49a0e2694b0755a50485e", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a50485c", - "_tpl": "64b7bbb74b75259c590fa897", - "parentId": "5fe49a0e2694b0755a50485d", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 17 - } - }, { - "_id": "5fe49a0e2694b0755a504867", - "_tpl": "5e870397991fd70db46995c8", - "location": { - "isSearched": true, - "r": 0, - "x": 0, - "y": 16 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504860", - "_tpl": "5e87071478f43e51ca2de5e1", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a50485f", - "_tpl": "5e8708d4ae379e67d22e0102", - "parentId": "5fe49a0e2694b0755a504860", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504861", - "_tpl": "5e87076ce2db31558c75a11d", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a504863", - "_tpl": "5e87080c81c4ed43e83cefda", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a504862", - "_tpl": "560d5e524bdc2d25448b4571", - "parentId": "5fe49a0e2694b0755a504863", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 8 - } - }, { - "_id": "5fe49a0e2694b0755a504864", - "_tpl": "5e87116b81c4ed43e83cefdd", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a504865", - "_tpl": "5e87114fe2db31558c75a120", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "mod_mount", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504866", - "_tpl": "560d5e524bdc2d25448b4571", - "parentId": "5fe49a0e2694b0755a504867", - "slotId": "patron_in_weapon" - }, { - "_id": "5fe49a0e2694b0755a50486c", - "_tpl": "5bfea6e90db834001b7347f3", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 18 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a504869", - "_tpl": "5bfeaa0f0db834001b734927", - "parentId": "5fe49a0e2694b0755a50486c", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a504868", - "_tpl": "58dd3ad986f77403051cba8f", - "parentId": "5fe49a0e2694b0755a504869", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 10 - } - }, { - "_id": "5fe49a0e2694b0755a50486a", - "_tpl": "5bfeb32b0db834001a6694d9", - "parentId": "5fe49a0e2694b0755a50486c", - "slotId": "mod_stock" - }, { - "_id": "5fe49a0e2694b0755a50486b", - "_tpl": "5bfebc320db8340019668d79", - "parentId": "5fe49a0e2694b0755a50486c", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a504875", - "_tpl": "5c488a752e221602b412af63", - "location": { - "isSearched": true, - "r": 0, - "x": 5, - "y": 27 - }, - "parentId": "5fe49a0e2694b0755a504876", - "slotId": "hideout", - "upd": { - "FireMode": { - "FireMode": "single" - }, - "Repairable": { - "Durability": 100, - "MaxDurability": 100 - } - } - }, { - "_id": "5fe49a0e2694b0755a50486d", - "_tpl": "5c48a2c22e221602b313fb6c", - "parentId": "5fe49a0e2694b0755a504875", - "slotId": "mod_pistol_grip" - }, { - "_id": "5fe49a0e2694b0755a50486f", - "_tpl": "55d4887d4bdc2d962f8b4570", - "parentId": "5fe49a0e2694b0755a504875", - "slotId": "mod_magazine" - }, { - "_id": "5fe49a0e2694b0755a50486e", - "_tpl": "54527a984bdc2d4e668b4567", - "parentId": "5fe49a0e2694b0755a50486f", - "slotId": "cartridges", - "upd": { - "StackObjectsCount": 30 - } - }, { - "_id": "5fe49a0e2694b0755a504871", - "_tpl": "5c48a14f2e2216152006edd7", - "parentId": "5fe49a0e2694b0755a504875", - "slotId": "mod_handguard" - }, { - "_id": "5fe49a0e2694b0755a504870", - "_tpl": "5c18b90d2e2216152142466b", - "parentId": "5fe49a0e2694b0755a504871", - "slotId": "mod_sight_front", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504873", - "_tpl": "5c48a2852e221602b21d5923", - "parentId": "5fe49a0e2694b0755a504875", - "slotId": "mod_barrel" - }, { - "_id": "5fe49a0e2694b0755a504872", - "_tpl": "5c48a2a42e221602b66d1e07", - "parentId": "5fe49a0e2694b0755a504873", - "slotId": "mod_muzzle" - }, { - "_id": "5fe49a0e2694b0755a504874", - "_tpl": "5c18b9192e2216398b5a8104", - "parentId": "5fe49a0e2694b0755a504875", - "slotId": "mod_sight_rear", - "upd": { - "Sight": { - "ScopesCurrentCalibPointIndexes": [ - 0 - ], - "ScopesSelectedModes": [ - 0 - ], - "SelectedScope": 0 - } - } - }, { - "_id": "5fe49a0e2694b0755a504878", - "_tpl": "5963866b86f7747bfa1c4462" - }, { - "_id": "5fe49a0e2694b0755a504877", - "_tpl": "5963866286f7747bf429b572" - }, { - "_id": "60dca3da42ad9b706b369aca", - "_tpl": "602543c13fee350cd564d032" + "favoriteItems": [], + "items": [ + { + "_id": "6613e1cf291a2e76b00269a8", + "_tpl": "55d7217a4bdc2d86028b456d" + }, { + "_id": "6613e1cf291a2e76b002698d", + "_tpl": "5447a9cd4bdc2dbd208b4567", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "FirstPrimaryWeapon" + }, { + "_id": "6613e1cf291a2e76b0026980", + "_tpl": "55d4b9964bdc2d1d4e8b456e", + "parentId": "6613e1cf291a2e76b002698d", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026982", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b002698d", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026981", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026982", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 } - ], - "questRaidItems": "5fe49a0e2694b0755a504877", - "questStashItems": "5fe49a0e2694b0755a504878", - "sortingTable": "60dca3da42ad9b706b369aca", - "stash": "5fe49a0e2694b0755a504876" + }, { + "_id": "6613e1cf291a2e76b0026989", + "_tpl": "55d355e64bdc2d962f8b4569", + "parentId": "6613e1cf291a2e76b002698d", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026985", + "_tpl": "55d3632e4bdc2d972f8b4569", + "parentId": "6613e1cf291a2e76b0026989", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026983", + "_tpl": "544a38634bdc2d58388b4568", + "parentId": "6613e1cf291a2e76b0026985", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026984", + "_tpl": "5ae30e795acfc408fb139a0b", + "parentId": "6613e1cf291a2e76b0026985", + "slotId": "mod_gas_block" + }, { + "_id": "6613e1cf291a2e76b0026987", + "_tpl": "5ae30db85acfc408fb139a05", + "parentId": "6613e1cf291a2e76b0026989", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026986", + "_tpl": "637f57a68d137b27f70c4968", + "parentId": "6613e1cf291a2e76b0026987", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026988", + "_tpl": "5ae30bad5acfc400185c2dc4", + "parentId": "6613e1cf291a2e76b0026989", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b002698b", + "_tpl": "5649be884bdc2d79388b4577", + "parentId": "6613e1cf291a2e76b002698d", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b002698a", + "_tpl": "55d4ae6c4bdc2d8b2f8b456e", + "parentId": "6613e1cf291a2e76b002698b", + "slotId": "mod_stock_000" + }, { + "_id": "6613e1cf291a2e76b002698c", + "_tpl": "55d44fd14bdc2d962f8b456e", + "parentId": "6613e1cf291a2e76b002698d", + "slotId": "mod_charge" + }, { + "_id": "6613e1cf291a2e76b002698e", + "_tpl": "54491bb74bdc2d09088b4567", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "Scabbard" + }, { + "_id": "6613e1cf291a2e76b002698f", + "_tpl": "572b7fa524597762b747ce82", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "FaceCover" + }, { + "_id": "6613e1cf291a2e76b0026990", + "_tpl": "5aa2a7e8e5b5b00016327c16", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "Headwear" + }, { + "_id": "6613e1cf291a2e76b0026998", + "_tpl": "5c0e9f2c86f77432297fe0a3", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "TacticalVest" + }, { + "_id": "6613e1cf291a2e76b0026992", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026998", + "slotId": "1", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026991", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026992", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026994", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026998", + "slotId": "2", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026993", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026994", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026996", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026998", + "slotId": "3", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026995", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026996", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026997", + "_tpl": "5755356824597772cb798962", + "parentId": "6613e1cf291a2e76b0026998", + "slotId": "4", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026999", + "_tpl": "5857a8bc2459772bad15db29", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "SecuredContainer" + }, { + "_id": "6613e1cf291a2e76b002699d", + "_tpl": "5e9dcf5986f7746c417435b3", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "Backpack" + }, { + "_id": "6613e1cf291a2e76b002699a", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613e1cf291a2e76b002699d", + "slotId": "main", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613e1cf291a2e76b002699b", + "_tpl": "590c5f0d86f77413997acfab", + "parentId": "6613e1cf291a2e76b002699d", + "slotId": "main", + "location": { + "x": 1, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b002699c", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b002699d", + "slotId": "main", + "location": { + "x": 2, + "y": 0, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613e1cf291a2e76b00269a2", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "ArmorVest" + }, { + "_id": "6613e1cf291a2e76b002699e", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613e1cf291a2e76b00269a2", + "slotId": "Soft_armor_front" + }, { + "_id": "6613e1cf291a2e76b002699f", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613e1cf291a2e76b00269a2", + "slotId": "Soft_armor_back" + }, { + "_id": "6613e1cf291a2e76b00269a0", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613e1cf291a2e76b00269a2", + "slotId": "Soft_armor_left" + }, { + "_id": "6613e1cf291a2e76b00269a1", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613e1cf291a2e76b00269a2", + "slotId": "soft_armor_right" + }, { + "_id": "6613e1cf291a2e76b00269a6", + "_tpl": "627a4e6b255f7527fb05a0f6", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "Pockets" + }, { + "_id": "6613e1cf291a2e76b00269a3", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613e1cf291a2e76b00269a6", + "slotId": "pocket1", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269a4", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613e1cf291a2e76b00269a6", + "slotId": "pocket2", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269a5", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613e1cf291a2e76b00269a6", + "slotId": "pocket3", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269a7", + "_tpl": "5645bcc04bdc2d363b8b4572", + "parentId": "6613e1cf291a2e76b00269a8", + "slotId": "Earpiece" + }, { + "_id": "6613e1cf291a2e76b0026acc", + "_tpl": "5811ce772459770e9e5f9532" + }, { + "_id": "6613e1cf291a2e76b00269a9", + "_tpl": "590c5f0d86f77413997acfab", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269aa", + "_tpl": "5e9dcf5986f7746c417435b3", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 9, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ab", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ad", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 4, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ac", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269ad", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b00269af", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ae", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b00269af", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b00269b0", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613e1cf291a2e76b00269b1", + "_tpl": "590c661e86f7741e566b646a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 31, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b2", + "_tpl": "5755356824597772cb798962", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 31, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b3", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b5", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 15, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b4", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b00269b5", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b00269b6", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269b7", + "_tpl": "590c5f0d86f77413997acfab", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 1, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b9", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269b8", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b00269b9", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b00269ba", + "_tpl": "58d3db5386f77426186285a0", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 13, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269bb", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613e1cf291a2e76b00269bc", + "_tpl": "590c661e86f7741e566b646a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269bd", + "_tpl": "5ab8f39486f7745cd93a1cca", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 25, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269be", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269bf", + "_tpl": "58d3db5386f77426186285a0", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 13, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c1", + "_tpl": "5bfeaa0f0db834001b734927", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c0", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b00269c1", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613e1cf291a2e76b00269c2", + "_tpl": "5e4d34ca86f774264f758330", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 11, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c3", + "_tpl": "5aa2a7e8e5b5b00016327c16", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c4", + "_tpl": "5c0e9f2c86f77432297fe0a3", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c5", + "_tpl": "590c5f0d86f77413997acfab", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c6", + "_tpl": "5aa2a7e8e5b5b00016327c16", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269cb", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269c7", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613e1cf291a2e76b00269cb", + "slotId": "Soft_armor_front" + }, { + "_id": "6613e1cf291a2e76b00269c8", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613e1cf291a2e76b00269cb", + "slotId": "Soft_armor_back" + }, { + "_id": "6613e1cf291a2e76b00269c9", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613e1cf291a2e76b00269cb", + "slotId": "Soft_armor_left" + }, { + "_id": "6613e1cf291a2e76b00269ca", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613e1cf291a2e76b00269cb", + "slotId": "soft_armor_right" + }, { + "_id": "6613e1cf291a2e76b00269cc", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269cd", + "_tpl": "5755356824597772cb798962", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 31, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269cf", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ce", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269cf", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b00269d0", + "_tpl": "5e4d34ca86f774264f758330", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 9, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269d1", + "_tpl": "5d403f9186f7743cac3f229b", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269d2", + "_tpl": "5c0e9f2c86f77432297fe0a3", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 0, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269d7", + "_tpl": "5648a7494bdc2d9d488b4583", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269d3", + "_tpl": "65703d866584602f7d057a8a", + "parentId": "6613e1cf291a2e76b00269d7", + "slotId": "Soft_armor_front" + }, { + "_id": "6613e1cf291a2e76b00269d4", + "_tpl": "65703fa06584602f7d057a8e", + "parentId": "6613e1cf291a2e76b00269d7", + "slotId": "Soft_armor_back" + }, { + "_id": "6613e1cf291a2e76b00269d5", + "_tpl": "65703fe46a912c8b5c03468b", + "parentId": "6613e1cf291a2e76b00269d7", + "slotId": "Soft_armor_left" + }, { + "_id": "6613e1cf291a2e76b00269d6", + "_tpl": "657040374e67e8ec7a0d261c", + "parentId": "6613e1cf291a2e76b00269d7", + "slotId": "soft_armor_right" + }, { + "_id": "6613e1cf291a2e76b00269d8", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269d9", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269da", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269db", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269dc", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269dd", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269df", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 5, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269de", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269df", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b00269e0", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269e1", + "_tpl": "5e9dcf5986f7746c417435b3", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 9, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e2", + "_tpl": "590c695186f7741e566b64a2", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e3", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e4", + "_tpl": "590c695186f7741e566b64a2", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e5", + "_tpl": "5751a25924597722c463c472", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e7", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e6", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269e7", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b00269e9", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269e8", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269e9", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b00269eb", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ea", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269eb", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b00269ed", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ec", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269ed", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b00269ef", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 1, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269ee", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269ef", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b00269f0", + "_tpl": "5755383e24597772cb798966", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269f2", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 25, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269f1", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b00269f2", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b00269f3", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269f4", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 1, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269f5", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269f6", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269f7", + "_tpl": "5696686a4bdc2da3298b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613e1cf291a2e76b00269f8", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269fa", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269f9", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269fa", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b00269fc", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b00269fb", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b00269fc", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b00269fd", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269fe", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b00269ff", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 8, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 50 + } + }, { + "_id": "6613e1cf291a2e76b0026a00", + "_tpl": "5755356824597772cb798962", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 31, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a01", + "_tpl": "5e831507ea0a7c419c2f9bd9", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a02", + "_tpl": "5449016a4bdc2d6f028b456f", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 1, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 250000 + } + }, { + "_id": "6613e1cf291a2e76b0026a03", + "_tpl": "5449016a4bdc2d6f028b456f", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 1, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 250000 + } + }, { + "_id": "6613e1cf291a2e76b0026a05", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a04", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026a05", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a06", + "_tpl": "5e8488fa988a8701445df1e4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a07", + "_tpl": "569668774bdc2da2298b4568", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613e1cf291a2e76b0026a09", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a08", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a09", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a0b", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a0a", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a0b", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a0d", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a0c", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a0d", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a0f", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a0e", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a0f", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a10", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a11", + "_tpl": "5a0c27731526d80618476ac4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 15, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a12", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 26, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a13", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 28, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a14", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 26, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a15", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 27, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a16", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a17", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a18", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 17, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a19", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 1, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a1a", + "_tpl": "5755356824597772cb798962", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 31, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a1b", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a1c", + "_tpl": "5d02778e86f774203e7dedbe", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a21", + "_tpl": "5c0e655586f774045612eeb2", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 17, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a1d", + "_tpl": "656fad8c498d1b7e3e071da0", + "parentId": "6613e1cf291a2e76b0026a21", + "slotId": "Front_plate" + }, { + "_id": "6613e1cf291a2e76b0026a1e", + "_tpl": "656fad8c498d1b7e3e071da0", + "parentId": "6613e1cf291a2e76b0026a21", + "slotId": "Back_plate" + }, { + "_id": "6613e1cf291a2e76b0026a1f", + "_tpl": "6570e025615f54368b04fcb0", + "parentId": "6613e1cf291a2e76b0026a21", + "slotId": "Soft_armor_front" + }, { + "_id": "6613e1cf291a2e76b0026a20", + "_tpl": "6570e0610b57c03ec90b96ef", + "parentId": "6613e1cf291a2e76b0026a21", + "slotId": "Soft_armor_back" + }, { + "_id": "6613e1cf291a2e76b0026a22", + "_tpl": "5c165d832e2216398b5a7e36", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a23", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a24", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a25", + "_tpl": "5af0454c86f7746bf20992e8", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 33, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a26", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a27", + "_tpl": "5ab8f39486f7745cd93a1cca", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 25, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a28", + "_tpl": "557ff21e4bdc2d89578b4586", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a29", + "_tpl": "5bfebc5e0db834001a6694e5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a2a", + "_tpl": "57c5ac0824597754771e88a9", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a2e", + "_tpl": "5aa7d03ae5b5b00016327db5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a2b", + "_tpl": "654a90aff4f81a421b0a7c86", + "parentId": "6613e1cf291a2e76b0026a2e", + "slotId": "helmet_top" + }, { + "_id": "6613e1cf291a2e76b0026a2c", + "_tpl": "654a91068e1ce698150fd1e2", + "parentId": "6613e1cf291a2e76b0026a2e", + "slotId": "helmet_back" + }, { + "_id": "6613e1cf291a2e76b0026a2d", + "_tpl": "654a9189bcc67a392b056c79", + "parentId": "6613e1cf291a2e76b0026a2e", + "slotId": "helmet_ears" + }, { + "_id": "6613e1cf291a2e76b0026a32", + "_tpl": "5aa7d03ae5b5b00016327db5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a2f", + "_tpl": "654a90aff4f81a421b0a7c86", + "parentId": "6613e1cf291a2e76b0026a32", + "slotId": "helmet_top" + }, { + "_id": "6613e1cf291a2e76b0026a30", + "_tpl": "654a91068e1ce698150fd1e2", + "parentId": "6613e1cf291a2e76b0026a32", + "slotId": "helmet_back" + }, { + "_id": "6613e1cf291a2e76b0026a31", + "_tpl": "654a9189bcc67a392b056c79", + "parentId": "6613e1cf291a2e76b0026a32", + "slotId": "helmet_ears" + }, { + "_id": "6613e1cf291a2e76b0026a33", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a34", + "_tpl": "544fb37f4bdc2dee738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a35", + "_tpl": "58d3db5386f77426186285a0", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a36", + "_tpl": "58d3db5386f77426186285a0", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a37", + "_tpl": "58d3db5386f77426186285a0", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a39", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 24, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a38", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026a39", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a3a", + "_tpl": "5d1b371186f774253763a656", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a3b", + "_tpl": "5d1b36a186f7742523398433", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a3c", + "_tpl": "60098ad7c2240c0fe85c570a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 2, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a3d", + "_tpl": "557ff21e4bdc2d89578b4586", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a3e", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 29, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613e1cf291a2e76b0026a3f", + "_tpl": "5d02778e86f774203e7dedbe", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 32, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a40", + "_tpl": "5d5d940f86f7742797262046", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 27, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a41", + "_tpl": "57cd379a24597778e7682ecf", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 26, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a47", + "_tpl": "544a5caa4bdc2d1a388b4568", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a42", + "_tpl": "656f9fa0498d1b7e3e071d98", + "parentId": "6613e1cf291a2e76b0026a47", + "slotId": "Front_plate" + }, { + "_id": "6613e1cf291a2e76b0026a43", + "_tpl": "656f9fa0498d1b7e3e071d98", + "parentId": "6613e1cf291a2e76b0026a47", + "slotId": "Back_plate" + }, { + "_id": "6613e1cf291a2e76b0026a44", + "_tpl": "6570e83223c1f638ef0b0ede", + "parentId": "6613e1cf291a2e76b0026a47", + "slotId": "Soft_armor_front" + }, { + "_id": "6613e1cf291a2e76b0026a45", + "_tpl": "6570e87c23c1f638ef0b0ee2", + "parentId": "6613e1cf291a2e76b0026a47", + "slotId": "Soft_armor_back" + }, { + "_id": "6613e1cf291a2e76b0026a46", + "_tpl": "6570e90b3a5689d85f08db97", + "parentId": "6613e1cf291a2e76b0026a47", + "slotId": "Groin" + }, { + "_id": "6613e1cf291a2e76b0026a48", + "_tpl": "5d5d85c586f774279a21cbdb", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 22, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a49", + "_tpl": "5e2af4a786f7746d3f3c3400", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a4a", + "_tpl": "570fd6c2d2720bc6458b457f", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 26, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a4b", + "_tpl": "5448be9a4bdc2dfd2f8b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a4c", + "_tpl": "5448be9a4bdc2dfd2f8b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a4d", + "_tpl": "590c657e86f77412b013051d", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a50", + "_tpl": "5d5e9c74a4b9364855191c40", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 17, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a4e", + "_tpl": "657f8b94f92cd718b70154ff", + "parentId": "6613e1cf291a2e76b0026a50", + "slotId": "Helmet_top" + }, { + "_id": "6613e1cf291a2e76b0026a4f", + "_tpl": "657f8b43f92cd718b70154fb", + "parentId": "6613e1cf291a2e76b0026a50", + "slotId": "Helmet_back" + }, { + "_id": "6613e1cf291a2e76b0026a52", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 26, + "r": 1, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a51", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026a52", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a53", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a54", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a55", + "_tpl": "590c678286f77426c9660122", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a57", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 24, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a56", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026a57", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a58", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 29, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613e1cf291a2e76b0026a59", + "_tpl": "5e8488fa988a8701445df1e4", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 36, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a5a", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 26, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 60 + } + }, { + "_id": "6613e1cf291a2e76b0026a5b", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 26, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a5c", + "_tpl": "5c0e530286f7747fa1419862", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a5d", + "_tpl": "5c0e530286f7747fa1419862", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a5e", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 25, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026a5f", + "_tpl": "5696686a4bdc2da3298b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 2, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 500 + } + }, { + "_id": "6613e1cf291a2e76b0026a61", + "_tpl": "5bfeaa0f0db834001b734927", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a60", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026a61", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613e1cf291a2e76b0026a63", + "_tpl": "5bfeaa0f0db834001b734927", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 19, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a62", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026a63", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613e1cf291a2e76b0026a65", + "_tpl": "5bfeaa0f0db834001b734927", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 20, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a64", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026a65", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613e1cf291a2e76b0026a66", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 19, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a67", + "_tpl": "5448fee04bdc2dbc018b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 29, + "r": 0, + "isSearched": true + }, + "upd": { + "FoodDrink": { + "HpPercent": 60 + } + } + }, { + "_id": "6613e1cf291a2e76b0026a68", + "_tpl": "544fb3364bdc2d34748b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 34, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a6a", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a69", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a6a", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a6c", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 7, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a6b", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a6c", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a6e", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 6, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a6d", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a6e", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a6f", + "_tpl": "544fb3f34bdc2d03748b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a70", + "_tpl": "544fb3f34bdc2d03748b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 30, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a71", + "_tpl": "5e2af47786f7746d404f3aaa", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 38, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a72", + "_tpl": "5e2af4a786f7746d3f3c3400", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 37, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a73", + "_tpl": "5e2af47786f7746d404f3aaa", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 39, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a74", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 16, + "r": 0, + "isSearched": true + }, + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a75", + "_tpl": "5448be9a4bdc2dfd2f8b456a", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 4, + "y": 21, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a76", + "_tpl": "5645bcc04bdc2d363b8b4572", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 23, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a77", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 8, + "y": 29, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a78", + "_tpl": "57347da92459774491567cf5", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 29, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a79", + "_tpl": "544fb25a4bdc2dfb738b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 9, + "y": 35, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a82", + "_tpl": "5cadc190ae921500103bb3b6", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 5, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a7b", + "_tpl": "5cadc1c6ae9215000f2775a4", + "parentId": "6613e1cf291a2e76b0026a82", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026a7a", + "_tpl": "5cadc390ae921500126a77f1", + "parentId": "6613e1cf291a2e76b0026a7b", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026a7c", + "_tpl": "5cadc431ae921500113bb8d5", + "parentId": "6613e1cf291a2e76b0026a82", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026a7f", + "_tpl": "5cadc55cae921500103bb3be", + "parentId": "6613e1cf291a2e76b0026a82", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026a7d", + "_tpl": "5cadd940ae9215051e1c2316", + "parentId": "6613e1cf291a2e76b0026a7f", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026a7e", + "_tpl": "5cadd919ae921500126a77f3", + "parentId": "6613e1cf291a2e76b0026a7f", + "slotId": "mod_sight_front" + }, { + "_id": "6613e1cf291a2e76b0026a81", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026a82", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026a80", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a81", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a8b", + "_tpl": "5cadc190ae921500103bb3b6", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 4, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a84", + "_tpl": "5cadc1c6ae9215000f2775a4", + "parentId": "6613e1cf291a2e76b0026a8b", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026a83", + "_tpl": "5cadc390ae921500126a77f1", + "parentId": "6613e1cf291a2e76b0026a84", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026a85", + "_tpl": "5cadc431ae921500113bb8d5", + "parentId": "6613e1cf291a2e76b0026a8b", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026a88", + "_tpl": "5cadc55cae921500103bb3be", + "parentId": "6613e1cf291a2e76b0026a8b", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026a86", + "_tpl": "5cadd940ae9215051e1c2316", + "parentId": "6613e1cf291a2e76b0026a88", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026a87", + "_tpl": "5cadd919ae921500126a77f3", + "parentId": "6613e1cf291a2e76b0026a88", + "slotId": "mod_sight_front" + }, { + "_id": "6613e1cf291a2e76b0026a8a", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026a8b", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026a89", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a8a", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026a94", + "_tpl": "5926bb2186f7744b1c6c6e60", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 7, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a8d", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026a94", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026a8c", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a8d", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a92", + "_tpl": "5926c0df86f77462f647f764", + "parentId": "6613e1cf291a2e76b0026a94", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026a8e", + "_tpl": "5926c36d86f77467a92a8629", + "parentId": "6613e1cf291a2e76b0026a92", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026a8f", + "_tpl": "5926d2be86f774134d668e4e", + "parentId": "6613e1cf291a2e76b0026a92", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026a90", + "_tpl": "5926d3c686f77410de68ebc8", + "parentId": "6613e1cf291a2e76b0026a92", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b0026a91", + "_tpl": "5926e16e86f7742f5a0f7ecb", + "parentId": "6613e1cf291a2e76b0026a92", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026a93", + "_tpl": "5926c32286f774616e42de99", + "parentId": "6613e1cf291a2e76b0026a94", + "slotId": "mod_charge" + }, { + "_id": "6613e1cf291a2e76b0026a9d", + "_tpl": "5926bb2186f7744b1c6c6e60", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 6, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a96", + "_tpl": "5d2f213448f0355009199284", + "parentId": "6613e1cf291a2e76b0026a9d", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026a95", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026a96", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 20 + } + }, { + "_id": "6613e1cf291a2e76b0026a9b", + "_tpl": "5926c0df86f77462f647f764", + "parentId": "6613e1cf291a2e76b0026a9d", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026a97", + "_tpl": "5926c36d86f77467a92a8629", + "parentId": "6613e1cf291a2e76b0026a9b", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026a98", + "_tpl": "5926d2be86f774134d668e4e", + "parentId": "6613e1cf291a2e76b0026a9b", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026a99", + "_tpl": "5926d3c686f77410de68ebc8", + "parentId": "6613e1cf291a2e76b0026a9b", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b0026a9a", + "_tpl": "5926e16e86f7742f5a0f7ecb", + "parentId": "6613e1cf291a2e76b0026a9b", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026a9c", + "_tpl": "5926c32286f774616e42de99", + "parentId": "6613e1cf291a2e76b0026a9d", + "slotId": "mod_charge" + }, { + "_id": "6613e1cf291a2e76b0026aa6", + "_tpl": "5cadc190ae921500103bb3b6", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 3, + "y": 3, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026a9f", + "_tpl": "5cadc1c6ae9215000f2775a4", + "parentId": "6613e1cf291a2e76b0026aa6", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026a9e", + "_tpl": "5cadc390ae921500126a77f1", + "parentId": "6613e1cf291a2e76b0026a9f", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026aa0", + "_tpl": "5cadc431ae921500113bb8d5", + "parentId": "6613e1cf291a2e76b0026aa6", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026aa3", + "_tpl": "5cadc55cae921500103bb3be", + "parentId": "6613e1cf291a2e76b0026aa6", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026aa1", + "_tpl": "5cadd940ae9215051e1c2316", + "parentId": "6613e1cf291a2e76b0026aa3", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026aa2", + "_tpl": "5cadd919ae921500126a77f3", + "parentId": "6613e1cf291a2e76b0026aa3", + "slotId": "mod_sight_front" + }, { + "_id": "6613e1cf291a2e76b0026aa5", + "_tpl": "5cadc2e0ae9215051e1c21e7", + "parentId": "6613e1cf291a2e76b0026aa6", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026aa4", + "_tpl": "64b7bbb74b75259c590fa897", + "parentId": "6613e1cf291a2e76b0026aa5", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 17 + } + }, { + "_id": "6613e1cf291a2e76b0026aaf", + "_tpl": "5e870397991fd70db46995c8", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 16, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026aa8", + "_tpl": "5e87071478f43e51ca2de5e1", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026aa7", + "_tpl": "5e8708d4ae379e67d22e0102", + "parentId": "6613e1cf291a2e76b0026aa8", + "slotId": "mod_sight_front" + }, { + "_id": "6613e1cf291a2e76b0026aa9", + "_tpl": "5e87076ce2db31558c75a11d", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026aab", + "_tpl": "5e87080c81c4ed43e83cefda", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026aaa", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613e1cf291a2e76b0026aab", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 8 + } + }, { + "_id": "6613e1cf291a2e76b0026aac", + "_tpl": "5e87116b81c4ed43e83cefdd", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b0026aad", + "_tpl": "5e87114fe2db31558c75a120", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "mod_mount" + }, { + "_id": "6613e1cf291a2e76b0026aae", + "_tpl": "560d5e524bdc2d25448b4571", + "parentId": "6613e1cf291a2e76b0026aaf", + "slotId": "patron_in_weapon" + }, { + "_id": "6613e1cf291a2e76b0026ab4", + "_tpl": "5bfea6e90db834001b7347f3", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 18, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026ab1", + "_tpl": "5bfeaa0f0db834001b734927", + "parentId": "6613e1cf291a2e76b0026ab4", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026ab0", + "_tpl": "58dd3ad986f77403051cba8f", + "parentId": "6613e1cf291a2e76b0026ab1", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 10 + } + }, { + "_id": "6613e1cf291a2e76b0026ab2", + "_tpl": "5bfeb32b0db834001a6694d9", + "parentId": "6613e1cf291a2e76b0026ab4", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b0026ab3", + "_tpl": "5bfebc320db8340019668d79", + "parentId": "6613e1cf291a2e76b0026ab4", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026abd", + "_tpl": "5c488a752e221602b412af63", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 5, + "y": 27, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026ab5", + "_tpl": "5c48a2c22e221602b313fb6c", + "parentId": "6613e1cf291a2e76b0026abd", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026ab7", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026abd", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026ab6", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026ab7", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026ab9", + "_tpl": "5c48a14f2e2216152006edd7", + "parentId": "6613e1cf291a2e76b0026abd", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026ab8", + "_tpl": "5c18b90d2e2216152142466b", + "parentId": "6613e1cf291a2e76b0026ab9", + "slotId": "mod_sight_front" + }, { + "_id": "6613e1cf291a2e76b0026abb", + "_tpl": "5c48a2852e221602b21d5923", + "parentId": "6613e1cf291a2e76b0026abd", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026aba", + "_tpl": "5c48a2a42e221602b66d1e07", + "parentId": "6613e1cf291a2e76b0026abb", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026abc", + "_tpl": "5c18b9192e2216398b5a8104", + "parentId": "6613e1cf291a2e76b0026abd", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026acb", + "_tpl": "5447a9cd4bdc2dbd208b4567", + "parentId": "6613e1cf291a2e76b0026acc", + "slotId": "hideout", + "location": { + "x": 0, + "y": 14, + "r": 0, + "isSearched": true + } + }, { + "_id": "6613e1cf291a2e76b0026abe", + "_tpl": "55d4b9964bdc2d1d4e8b456e", + "parentId": "6613e1cf291a2e76b0026acb", + "slotId": "mod_pistol_grip" + }, { + "_id": "6613e1cf291a2e76b0026ac0", + "_tpl": "55d4887d4bdc2d962f8b4570", + "parentId": "6613e1cf291a2e76b0026acb", + "slotId": "mod_magazine" + }, { + "_id": "6613e1cf291a2e76b0026abf", + "_tpl": "54527a984bdc2d4e668b4567", + "parentId": "6613e1cf291a2e76b0026ac0", + "slotId": "cartridges", + "upd": { + "StackObjectsCount": 30 + } + }, { + "_id": "6613e1cf291a2e76b0026ac7", + "_tpl": "55d355e64bdc2d962f8b4569", + "parentId": "6613e1cf291a2e76b0026acb", + "slotId": "mod_reciever" + }, { + "_id": "6613e1cf291a2e76b0026ac3", + "_tpl": "55d3632e4bdc2d972f8b4569", + "parentId": "6613e1cf291a2e76b0026ac7", + "slotId": "mod_barrel" + }, { + "_id": "6613e1cf291a2e76b0026ac1", + "_tpl": "544a38634bdc2d58388b4568", + "parentId": "6613e1cf291a2e76b0026ac3", + "slotId": "mod_muzzle" + }, { + "_id": "6613e1cf291a2e76b0026ac2", + "_tpl": "5ae30e795acfc408fb139a0b", + "parentId": "6613e1cf291a2e76b0026ac3", + "slotId": "mod_gas_block" + }, { + "_id": "6613e1cf291a2e76b0026ac5", + "_tpl": "5ae30db85acfc408fb139a05", + "parentId": "6613e1cf291a2e76b0026ac7", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026ac4", + "_tpl": "637f57a68d137b27f70c4968", + "parentId": "6613e1cf291a2e76b0026ac5", + "slotId": "mod_handguard" + }, { + "_id": "6613e1cf291a2e76b0026ac6", + "_tpl": "5ae30bad5acfc400185c2dc4", + "parentId": "6613e1cf291a2e76b0026ac7", + "slotId": "mod_sight_rear" + }, { + "_id": "6613e1cf291a2e76b0026ac9", + "_tpl": "5649be884bdc2d79388b4577", + "parentId": "6613e1cf291a2e76b0026acb", + "slotId": "mod_stock" + }, { + "_id": "6613e1cf291a2e76b0026ac8", + "_tpl": "55d4ae6c4bdc2d8b2f8b456e", + "parentId": "6613e1cf291a2e76b0026ac9", + "slotId": "mod_stock_000" + }, { + "_id": "6613e1cf291a2e76b0026aca", + "_tpl": "55d44fd14bdc2d962f8b456e", + "parentId": "6613e1cf291a2e76b0026acb", + "slotId": "mod_charge" + }, { + "_id": "6613e1cf291a2e76b0026acf", + "_tpl": "602543c13fee350cd564d032" + }, { + "_id": "6613e1cf291a2e76b0026ace", + "_tpl": "5963866b86f7747bfa1c4462" + }, { + "_id": "6613e1cf291a2e76b0026acd", + "_tpl": "5963866286f7747bf429b572" + } + ], + "questRaidItems": "6613e1cf291a2e76b0026acd", + "questStashItems": "6613e1cf291a2e76b0026ace", + "sortingTable": "6613e1cf291a2e76b0026acf", + "stash": "6613e1cf291a2e76b0026acc" }, "Notes": { "Notes": [] diff --git a/project/assets/database/traders/5a7c2eca46aef81a7ca2145d/assort.json b/project/assets/database/traders/5a7c2eca46aef81a7ca2145d/assort.json index bf6e7552..8dab2ce1 100644 --- a/project/assets/database/traders/5a7c2eca46aef81a7ca2145d/assort.json +++ b/project/assets/database/traders/5a7c2eca46aef81a7ca2145d/assort.json @@ -2630,7 +2630,7 @@ "slotId": "hideout", "upd": { "StackObjectsCount": 11956, - "BuyRestrictionMax": "8", + "BuyRestrictionMax": 8, "BuyRestrictionCurrent": 0 } }, @@ -4567,7 +4567,7 @@ "slotId": "hideout", "upd": { "StackObjectsCount": 5962, - "BuyRestrictionMax": "4", + "BuyRestrictionMax": 4, "BuyRestrictionCurrent": 0 } }, diff --git a/project/assets/images/quests/65f773082e9cf257e2717145.jpg b/project/assets/images/quests/65f773082e9cf257e2717145.jpg new file mode 100644 index 00000000..22405c1f Binary files /dev/null and b/project/assets/images/quests/65f773082e9cf257e2717145.jpg differ diff --git a/project/gulpfile.mjs b/project/gulpfile.mjs index 0b09ed47..32a27680 100644 --- a/project/gulpfile.mjs +++ b/project/gulpfile.mjs @@ -155,27 +155,32 @@ const downloadPnpm = async () => const copyLicense = () => gulp.src([licenseFile]).pipe(rename("LICENSE-Server.txt")).pipe(gulp.dest(buildDir)); /** - * Writes the latest Git commit hash to the core.json configuration file. + * Writes the latest build data to the core.json and build.json configuration files. */ -const writeCommitHashToCoreJSON = async () => +const writeBuildDataToJSON = async () => { try { - const coreJSONPath = path.resolve(dataDir, "configs", "core.json"); - const coreJSON = await fs.readFile(coreJSONPath, "utf8"); - const parsed = JSON.parse(coreJSON); - // Fetch the latest Git commit hash const gitResult = await exec("git rev-parse HEAD", { stdout: "pipe" }); - // Update the commit hash in the core.json object - parsed.commit = gitResult.stdout.trim() || ""; + // Update core.json + const coreJSONPath = path.resolve(dataDir, "configs", "core.json"); + const coreJSON = await fs.readFile(coreJSONPath, "utf8"); + const coreParsed = JSON.parse(coreJSON); - // Add build timestamp - parsed.buildTime = new Date().getTime(); + coreParsed.commit = gitResult.stdout.trim() || ""; + coreParsed.buildTime = new Date().getTime(); + await fs.writeFile(coreJSONPath, JSON.stringify(coreParsed, null, 4)); - // Write the updated object back to core.json - await fs.writeFile(coreJSONPath, JSON.stringify(parsed, null, 4)); + // Write build.json + const buildJsonPath = path.join("obj", "ide", "build.json"); + const buildInfo = {}; + + buildInfo.commit = coreParsed.commit; + buildInfo.buildTime = coreParsed.buildTime; + buildInfo.akiVersion = coreParsed.akiVersion; + await fs.writeFile(buildJsonPath, JSON.stringify(buildInfo, null, 4)); } catch (error) { @@ -195,7 +200,7 @@ const createHashFile = async () => }; // Combine all tasks into addAssets -const addAssets = gulp.series(copyAssets, downloadPnpm, copyLicense, writeCommitHashToCoreJSON, createHashFile); +const addAssets = gulp.series(copyAssets, downloadPnpm, copyLicense, writeBuildDataToJSON, createHashFile); /** * Cleans the build directory. @@ -313,9 +318,9 @@ const build = (packagingType) => cleanBuild, validateJSONs, compile, + addAssets, fetchPackageImage, anonPackaging, - addAssets, updateBuildProperties, cleanCompiled, ]; diff --git a/project/package.json b/project/package.json index eaeae684..8df289bc 100644 --- a/project/package.json +++ b/project/package.json @@ -1,6 +1,6 @@ { "name": "aki-server", - "version": "3.8.0", + "version": "3.8.1", "author": "SPT-AKI Server", "license": "NCSA", "main": "obj/bundle.js", @@ -27,12 +27,13 @@ "run:build": "gulp run:build", "run:debug": "gulp run:debug", "run:profiler": "gulp run:profiler", - "gen:types": "tsc -p tsconfig.typedef.json", + "gen:types": "tsc -p tsconfig.typedef.json --resolveJsonModule", "gen:docs": "typedoc --options ./typedoc.json --entryPointStrategy expand ./src" }, "dependencies": { "atomically": "~1.7", "buffer-crc32": "^1.0.0", + "closest-match": "~1.3", "date-fns": "~2.30", "date-fns-tz": "~2.0", "i18n": "~0.15", diff --git a/project/src/callbacks/BotCallbacks.ts b/project/src/callbacks/BotCallbacks.ts index 3867921a..966104ac 100644 --- a/project/src/callbacks/BotCallbacks.ts +++ b/project/src/callbacks/BotCallbacks.ts @@ -4,6 +4,7 @@ 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"; import { IBotBase } from "@spt-aki/models/eft/common/tables/IBotBase"; +import { Difficulties } from "@spt-aki/models/eft/common/tables/IBotType"; import { IGetBodyResponseData } from "@spt-aki/models/eft/httpResponse/IGetBodyResponseData"; import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil"; @@ -44,6 +45,15 @@ export class BotCallbacks return this.httpResponse.noBody(this.botController.getBotDifficulty(type, difficulty)); } + /** + * Handle singleplayer/settings/bot/difficulties + * @returns dictionary of every bot and its diffiulty settings + */ + public getAllBotDifficulties(url: string, info: IEmptyRequestData, sessionID: string): Record + { + return this.httpResponse.noBody(this.botController.getAllBotDifficulties()); + } + /** * Handle client/game/bot/generate * @returns IGetBodyResponseData diff --git a/project/src/callbacks/DialogueCallbacks.ts b/project/src/callbacks/DialogueCallbacks.ts index aef83abf..5b0e620b 100644 --- a/project/src/callbacks/DialogueCallbacks.ts +++ b/project/src/callbacks/DialogueCallbacks.ts @@ -6,6 +6,7 @@ import { IEmptyRequestData } from "@spt-aki/models/eft/common/IEmptyRequestData" import { IAcceptFriendRequestData, ICancelFriendRequestData, + IDeclineFriendRequestData, } from "@spt-aki/models/eft/dialog/IAcceptFriendRequestData"; import { IChatServer } from "@spt-aki/models/eft/dialog/IChatServer"; import { IClearMailMessageRequest } from "@spt-aki/models/eft/dialog/IClearMailMessageRequest"; @@ -186,7 +187,16 @@ export class DialogueCallbacks implements OnUpdate sessionID: string, ): IGetBodyResponseData { - return this.httpResponse.getBody({ status: 0, requestid: "12345", retryAfter: 600 }); + return this.httpResponse.getBody({ status: 0, requestId: "12345", retryAfter: 600 }); + } + + /** + * Handle client/friend/request/accept-all + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public acceptAllFriendRequests(url: string, request: IEmptyRequestData, sessionID: string): INullResponseData + { + return this.httpResponse.nullResponse(); } /** @@ -202,6 +212,19 @@ export class DialogueCallbacks implements OnUpdate return this.httpResponse.getBody(true); } + /** + * Handle client/friend/request/decline + */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars + public declineFriendRequest( + url: string, + request: IDeclineFriendRequestData, + sessionID: string, + ): IGetBodyResponseData + { + return this.httpResponse.getBody(true); + } + /** * Handle client/friend/request/cancel */ diff --git a/project/src/callbacks/InraidCallbacks.ts b/project/src/callbacks/InraidCallbacks.ts index 005284c5..87a5dec2 100644 --- a/project/src/callbacks/InraidCallbacks.ts +++ b/project/src/callbacks/InraidCallbacks.ts @@ -65,15 +65,6 @@ export class InraidCallbacks return this.httpResponse.noBody(this.inraidController.getInraidConfig().raidMenuSettings); } - /** - * Handle singleplayer/settings/weapon/durability - * @returns - */ - public getWeaponDurability(): string - { - return this.httpResponse.noBody(this.inraidController.getInraidConfig().save.durability); - } - /** * Handle singleplayer/airdrop/config * @returns JSON as string diff --git a/project/src/controllers/BotController.ts b/project/src/controllers/BotController.ts index 42f740d0..b89d64f2 100644 --- a/project/src/controllers/BotController.ts +++ b/project/src/controllers/BotController.ts @@ -13,6 +13,7 @@ import { IBotCore } from "@spt-aki/models/eft/common/tables/IBotCore"; import { Difficulty } from "@spt-aki/models/eft/common/tables/IBotType"; import { IGetRaidConfigurationRequestData } from "@spt-aki/models/eft/match/IGetRaidConfigurationRequestData"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; +import { WildSpawnTypeNumber } from "@spt-aki/models/enums/WildSpawnTypeNumber"; import { BotGenerationDetails } from "@spt-aki/models/spt/bots/BotGenerationDetails"; import { IBotConfig } from "@spt-aki/models/spt/config/IBotConfig"; import { IPmcConfig } from "@spt-aki/models/spt/config/IPmcConfig"; @@ -83,19 +84,20 @@ export class BotController /** * Get bot difficulty settings - * adjust PMC settings to ensure they engage the correct bot types + * Adjust PMC settings to ensure they engage the correct bot types * @param type what bot the server is requesting settings for * @param diffLevel difficulty level server requested settings for + * @param ignoreRaidSettings should raid settings chosen pre-raid be ignored * @returns Difficulty object */ - public getBotDifficulty(type: string, diffLevel: string): Difficulty + public getBotDifficulty(type: string, diffLevel: string, ignoreRaidSettings = false): Difficulty { let difficulty = diffLevel.toLowerCase(); const raidConfig = this.applicationContext.getLatestValue(ContextVariableType.RAID_CONFIGURATION)?.getValue< IGetRaidConfigurationRequestData >(); - if (!raidConfig) + if (!(raidConfig || ignoreRaidSettings)) { this.logger.error( this.localisationService.getText("bot-missing_application_context", "RAID_CONFIGURATION"), @@ -104,7 +106,7 @@ export class BotController // Check value chosen in pre-raid difficulty dropdown // If value is not 'asonline', change requested difficulty to be what was chosen in dropdown - const botDifficultyDropDownValue = raidConfig.wavesSettings.botDifficulty.toLowerCase(); + const botDifficultyDropDownValue = raidConfig?.wavesSettings.botDifficulty.toLowerCase() ?? "asonline"; if (botDifficultyDropDownValue !== "asonline") { difficulty = this.botDifficultyHelper.convertBotDifficultyDropdownToBotDifficulty( @@ -140,6 +142,37 @@ export class BotController return difficultySettings; } + public getAllBotDifficulties(): Record + { + const result = {}; + + const botDb = this.databaseServer.getTables().bots.types; + const botTypes = Object.keys(WildSpawnTypeNumber).filter((v) => Number.isNaN(Number(v))); + for (let botType of botTypes) + { + const enumType = botType.toLowerCase(); + // sptBear/sptUsec need to be converted into `usec`/`bear` so we can read difficulty settings from bots/types + botType = this.botHelper.isBotPmc(botType) + ? this.botHelper.getPmcSideByRole(botType).toLowerCase() + : botType.toLowerCase(); + + const botDetails = botDb[botType]; + if (!botDetails?.difficulty) + { + continue; + } + + const botDifficulties = Object.keys(botDetails.difficulty); + result[enumType] = {}; + for (const difficulty of botDifficulties) + { + result[enumType][difficulty] = this.getBotDifficulty(enumType, difficulty, true); + } + } + + return result; + } + /** * Generate bot profiles and store in cache * @param sessionId Session id diff --git a/project/src/controllers/BuildController.ts b/project/src/controllers/BuildController.ts index a337b9f5..b43ec7cb 100644 --- a/project/src/controllers/BuildController.ts +++ b/project/src/controllers/BuildController.ts @@ -147,7 +147,7 @@ export class BuildController this.removePlayerBuild(request.id, sessionID); } - protected removePlayerBuild(id: string, sessionID: string): void + protected removePlayerBuild(idToRemove: string, sessionID: string): void { const profile = this.saveServer.getProfile(sessionID); const weaponBuilds = profile.userbuilds.weaponBuilds; @@ -155,7 +155,7 @@ export class BuildController const magazineBuilds = profile.userbuilds.magazineBuilds; // Check for id in weapon array first - const matchingWeaponBuild = weaponBuilds.find((x) => x.Id === id); + const matchingWeaponBuild = weaponBuilds.find((weaponBuild) => weaponBuild.Id === idToRemove); if (matchingWeaponBuild) { weaponBuilds.splice(weaponBuilds.indexOf(matchingWeaponBuild), 1); @@ -164,7 +164,7 @@ export class BuildController } // Id not found in weapons, try equipment - const matchingEquipmentBuild = equipmentBuilds.find((x) => x.Id === id); + const matchingEquipmentBuild = equipmentBuilds.find((equipmentBuild) => equipmentBuild.Id === idToRemove); if (matchingEquipmentBuild) { equipmentBuilds.splice(equipmentBuilds.indexOf(matchingEquipmentBuild), 1); @@ -173,7 +173,7 @@ export class BuildController } // Id not found in weapons/equipment, try mags - const matchingMagazineBuild = magazineBuilds.find((x) => x.Id === id); + const matchingMagazineBuild = magazineBuilds.find((magBuild) => magBuild.Id === idToRemove); if (matchingMagazineBuild) { magazineBuilds.splice(magazineBuilds.indexOf(matchingMagazineBuild), 1); @@ -182,7 +182,9 @@ export class BuildController } // Not found in weapons,equipment or magazines, not good - this.logger.error(`Unable to delete preset, cannot find ${id} in weapon, equipment or magazine presets`); + this.logger.error( + `Unable to delete preset, cannot find ${idToRemove} in weapon, equipment or magazine presets`, + ); } /** diff --git a/project/src/controllers/DialogueController.ts b/project/src/controllers/DialogueController.ts index 9013825c..6bc4546b 100644 --- a/project/src/controllers/DialogueController.ts +++ b/project/src/controllers/DialogueController.ts @@ -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((x) => x._id === profile.characters.pmc.sessionId) + && !dialog.Users?.find((userDialog) => userDialog._id === profile.characters.pmc.sessionId) ) { if (!dialog.Users) @@ -230,9 +230,9 @@ export class DialogueController { result.push(...dialogUsers); - // Player doesnt exist, add them in before returning - if (!result.find((x) => x._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; result.push({ _id: fullProfile.info.id, @@ -278,7 +278,7 @@ export class DialogueController */ protected messagesHaveUncollectedRewards(messages: Message[]): boolean { - return messages.some((x) => x.items?.data?.length > 0); + return messages.some((message) => message.items?.data?.length > 0); } /** @@ -391,7 +391,7 @@ export class DialogueController { const timeNow = this.timeUtil.getTimestamp(); const dialogs = this.dialogueHelper.getDialogsForProfile(sessionId); - return dialogs[dialogueId].messages.filter((x) => timeNow < (x.dt + x.maxStorageTime)); + return dialogs[dialogueId].messages.filter((message) => timeNow < (message.dt + message.maxStorageTime)); } /** @@ -401,7 +401,7 @@ export class DialogueController */ protected getMessagesWithAttachments(messages: Message[]): Message[] { - return messages.filter((x) => x.items?.data?.length > 0); + return messages.filter((message) => message.items?.data?.length > 0); } /** diff --git a/project/src/controllers/GameController.ts b/project/src/controllers/GameController.ts index 1cede6dc..cafdf078 100644 --- a/project/src/controllers/GameController.ts +++ b/project/src/controllers/GameController.ts @@ -39,6 +39,7 @@ import { GiftService } from "@spt-aki/services/GiftService"; import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService"; import { LocalisationService } from "@spt-aki/services/LocalisationService"; import { OpenZoneService } from "@spt-aki/services/OpenZoneService"; +import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService"; import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService"; import { RaidTimeAdjustmentService } from "@spt-aki/services/RaidTimeAdjustmentService"; import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService"; @@ -78,6 +79,7 @@ export class GameController @inject("ItemBaseClassService") protected itemBaseClassService: ItemBaseClassService, @inject("GiftService") protected giftService: GiftService, @inject("RaidTimeAdjustmentService") protected raidTimeAdjustmentService: RaidTimeAdjustmentService, + @inject("ProfileActivityService") protected profileActivityService: ProfileActivityService, @inject("ApplicationContext") protected applicationContext: ApplicationContext, @inject("ConfigServer") protected configServer: ConfigServer, ) @@ -109,6 +111,8 @@ export class GameController // Store client start time in app context this.applicationContext.addValue(ContextVariableType.CLIENT_START_TIMESTAMP, startTimeStampMS); + this.profileActivityService.setActivityTimestamp(sessionID); + if (this.coreConfig.fixes.fixShotgunDispersion) { this.fixShotgunDispersions(); @@ -203,12 +207,16 @@ export class GameController this.hideoutHelper.setHideoutImprovementsToCompleted(pmcProfile); this.hideoutHelper.unlockHideoutWallInProfile(pmcProfile); this.profileFixerService.addMissingIdsToBonuses(pmcProfile); + this.profileFixerService.fixBitcoinProductionTime(pmcProfile); } this.logProfileDetails(fullProfile); this.adjustLabsRaiderSpawnRate(); + this.adjustHideoutCraftTimes(); + this.adjustHideoutBuildTimes(); + this.removePraporTestMessage(); this.saveActiveModsToProfile(fullProfile); @@ -240,6 +248,46 @@ export class GameController } } + protected adjustHideoutCraftTimes(): void + { + const craftTimeOverrideSeconds = this.hideoutConfig.overrideCraftTimeSeconds; + if (craftTimeOverrideSeconds === -1) + { + return; + } + + for (const craft of this.databaseServer.getTables().hideout.production) + { + // Only adjust crafts ABOVE the override + if (craft.productionTime > craftTimeOverrideSeconds) + { + craft.productionTime = craftTimeOverrideSeconds; + } + } + } + + protected adjustHideoutBuildTimes(): void + { + const craftTimeOverrideSeconds = this.hideoutConfig.overrideBuildTimeSeconds; + if (craftTimeOverrideSeconds === -1) + { + return; + } + + for (const area of this.databaseServer.getTables().hideout.areas) + { + for (const stageKey of Object.keys(area.stages)) + { + const stage = area.stages[stageKey]; + // Only adjust crafts ABOVE the override + if (stage.constructionTime > craftTimeOverrideSeconds) + { + stage.constructionTime = craftTimeOverrideSeconds; + } + } + } + } + protected adjustLocationBotValues(): void { const mapsDb = this.databaseServer.getTables().locations; @@ -436,7 +484,7 @@ export class GameController */ public getServer(sessionId: string): IServerDetails[] { - return [{ ip: this.httpConfig.ip, port: this.httpConfig.port }]; + return [{ ip: this.httpConfig.backendIp, port: Number.parseInt(this.httpConfig.backendPort) }]; } /** @@ -460,6 +508,7 @@ export class GameController */ public getKeepAlive(sessionId: string): IGameKeepAliveResponse { + this.profileActivityService.setActivityTimestamp(sessionId); return { msg: "OK", utc_time: new Date().getTime() / 1000 }; } @@ -915,7 +964,9 @@ export class GameController protected logProfileDetails(fullProfile: IAkiProfile): void { this.logger.debug(`Profile made with: ${fullProfile.aki.version}`); - this.logger.debug(`Server version: ${this.coreConfig.akiVersion} ${this.coreConfig.commit}`); + this.logger.debug( + `Server version: ${globalThis.G_AKIVERSION || this.coreConfig.akiVersion} ${globalThis.G_COMMIT}`, + ); this.logger.debug(`Debug enabled: ${globalThis.G_DEBUG_CONFIGURATION}`); this.logger.debug(`Mods enabled: ${globalThis.G_MODS_ENABLED}`); } diff --git a/project/src/controllers/HealthController.ts b/project/src/controllers/HealthController.ts index bed64766..f69ade0e 100644 --- a/project/src/controllers/HealthController.ts +++ b/project/src/controllers/HealthController.ts @@ -127,6 +127,9 @@ export class HealthController const consumedItemMaxResource = this.itemHelper.getItem(itemToConsume._tpl)[1]._props.MaxResource; if (consumedItemMaxResource > 1) { + // Ensure item has a upd object + this.itemHelper.addUpdObjectToItem(itemToConsume); + if (itemToConsume.upd.FoodDrink === undefined) { itemToConsume.upd.FoodDrink = { HpPercent: consumedItemMaxResource - request.count }; diff --git a/project/src/controllers/HideoutController.ts b/project/src/controllers/HideoutController.ts index 64a42525..d6d27841 100644 --- a/project/src/controllers/HideoutController.ts +++ b/project/src/controllers/HideoutController.ts @@ -48,6 +48,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer"; import { FenceService } from "@spt-aki/services/FenceService"; import { LocalisationService } from "@spt-aki/services/LocalisationService"; import { PlayerService } from "@spt-aki/services/PlayerService"; +import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService"; import { HashUtil } from "@spt-aki/utils/HashUtil"; import { HttpResponseUtil } from "@spt-aki/utils/HttpResponseUtil"; import { JsonUtil } from "@spt-aki/utils/JsonUtil"; @@ -79,6 +80,7 @@ export class HideoutController @inject("HideoutHelper") protected hideoutHelper: HideoutHelper, @inject("ScavCaseRewardGenerator") protected scavCaseRewardGenerator: ScavCaseRewardGenerator, @inject("LocalisationService") protected localisationService: LocalisationService, + @inject("ProfileActivityService") protected profileActivityService: ProfileActivityService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("JsonUtil") protected jsonUtil: JsonUtil, @inject("FenceService") protected fenceService: FenceService, @@ -1323,7 +1325,13 @@ export class HideoutController { for (const sessionID in this.saveServer.getProfiles()) { - if ("Hideout" in this.saveServer.getProfile(sessionID).characters.pmc) + if ( + "Hideout" in this.saveServer.getProfile(sessionID).characters.pmc + && this.profileActivityService.activeWithinLastMinutes( + sessionID, + this.hideoutConfig.updateProfileHideoutWhenActiveWithinMinutes, + ) + ) { this.hideoutHelper.updatePlayerHideout(sessionID); } diff --git a/project/src/controllers/InraidController.ts b/project/src/controllers/InraidController.ts index 6f9be86f..ba2d94ad 100644 --- a/project/src/controllers/InraidController.ts +++ b/project/src/controllers/InraidController.ts @@ -96,7 +96,21 @@ export class InraidController public addPlayer(sessionID: string, info: IRegisterPlayerRequestData): void { this.applicationContext.addValue(ContextVariableType.REGISTER_PLAYER_REQUEST, info); - this.saveServer.getProfile(sessionID).inraid.location = info.locationId; + const profile = this.saveServer.getProfile(sessionID); + if (!profile) + { + this.logger.error(`No profile found with Id of: ${sessionID}`); + + return; + } + if (!profile.inraid) + { + profile.inraid = { character: sessionID, location: info.locationId }; + + return; + } + + profile.inraid.location = info.locationId; } /** @@ -661,6 +675,12 @@ export class InraidController const pmcData = serverProfile.characters.pmc; const dialogueTemplates = this.databaseServer.getTables().traders[traderId].dialogue; + if (!dialogueTemplates) + { + this.logger.error(`Unable to deliver items as trader ${traderId} has no "dialogue" data`); + + return; + } const messageId = this.randomUtil.getArrayValue(dialogueTemplates.itemsDelivered); const messageStoreTime = this.timeUtil.getHoursAsSeconds(this.traderConfig.fence.btrDeliveryExpireHours); diff --git a/project/src/controllers/InsuranceController.ts b/project/src/controllers/InsuranceController.ts index 6e903a5c..7bb44a3e 100644 --- a/project/src/controllers/InsuranceController.ts +++ b/project/src/controllers/InsuranceController.ts @@ -23,6 +23,7 @@ import { SaveServer } from "@spt-aki/servers/SaveServer"; import { InsuranceService } from "@spt-aki/services/InsuranceService"; import { MailSendService } from "@spt-aki/services/MailSendService"; import { PaymentService } from "@spt-aki/services/PaymentService"; +import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService"; import { HashUtil } from "@spt-aki/utils/HashUtil"; import { MathUtil } from "@spt-aki/utils/MathUtil"; import { RandomUtil } from "@spt-aki/utils/RandomUtil"; @@ -50,6 +51,7 @@ export class InsuranceController @inject("PaymentService") protected paymentService: PaymentService, @inject("InsuranceService") protected insuranceService: InsuranceService, @inject("MailSendService") protected mailSendService: MailSendService, + @inject("RagfairPriceService") protected ragfairPriceService: RagfairPriceService, @inject("ConfigServer") protected configServer: ConfigServer, ) { @@ -102,7 +104,10 @@ export class InsuranceController const insuranceTime = time || this.timeUtil.getTimestamp(); const profileInsuranceDetails = this.saveServer.getProfile(sessionID).insurance; - this.logger.debug(`Found ${profileInsuranceDetails.length} insurance packages in profile ${sessionID}`, true); + if (profileInsuranceDetails.length > 0) + { + this.logger.debug(`Found ${profileInsuranceDetails.length} insurance packages in profile ${sessionID}`); + } return profileInsuranceDetails.filter((insured) => insuranceTime >= insured.scheduledTime); } @@ -196,7 +201,7 @@ export class InsuranceController !this.itemHelper.isAttachmentAttached(item) ); - // Process all items that are not attached, attachments. Those are handled separately, by value. + // Process all items that are not attached, attachments; those are handled separately, by value. if (hasRegularItems) { this.processRegularItems(insured, toDelete, parentAttachmentsMap); @@ -453,7 +458,7 @@ export class InsuranceController } /** - * Sorts the attachment items by their max price in descending order. + * Sorts the attachment items by their dynamic price in descending order. * * @param attachments The array of attachments items. * @returns An array of items enriched with their max price and common locale-name. @@ -463,8 +468,8 @@ export class InsuranceController return attachments.map((item) => ({ ...item, name: this.itemHelper.getItemName(item._tpl), - maxPrice: this.itemHelper.getItemMaxPrice(item._tpl), - })).sort((a, b) => b.maxPrice - a.maxPrice); + dynamicPrice: this.ragfairPriceService.getDynamicItemPrice(item._tpl, this.roubleTpl, item, null, false), + })).sort((a, b) => b.dynamicPrice - a.dynamicPrice); } /** @@ -477,7 +482,7 @@ export class InsuranceController let index = 1; for (const attachment of attachments) { - this.logger.debug(`Attachment ${index}: "${attachment.name}" - Price: ${attachment.maxPrice}`); + this.logger.debug(`Attachment ${index}: "${attachment.name}" - Price: ${attachment.dynamicPrice}`); index++; } } @@ -515,8 +520,8 @@ export class InsuranceController const valuableChild = attachments.find(({ _id }) => _id === attachmentsId); if (valuableChild) { - const { name, maxPrice } = valuableChild; - this.logger.debug(`Marked attachment "${name}" for removal - Max Price: ${maxPrice}`); + const { name, dynamicPrice } = valuableChild; + this.logger.debug(`Marked attachment "${name}" for removal - Dyanmic Price: ${dynamicPrice}`); toDelete.add(attachmentsId); } } @@ -543,10 +548,16 @@ export class InsuranceController */ protected sendMail(sessionID: string, insurance: Insurance): void { + const labsId = "laboratory"; // After all of the item filtering that we've done, if there are no items remaining, the insurance has // successfully "failed" to return anything and an appropriate message should be sent to the player. const traderDialogMessages = this.databaseServer.getTables().traders[insurance.traderId].dialogue; - if (insurance.systemData?.location.toLowerCase() === "laboratory") + + // Map is labs + insurance is disabled in base.json + if ( + insurance.systemData?.location.toLowerCase() === labsId + && !this.databaseServer.getTables().locations[labsId].base.Insurance + ) { // Trader has labs-specific messages // Wipe out returnable items @@ -711,9 +722,9 @@ export class InsuranceController } } -// Represents an insurance item that has had it's common locale-name and max price added to it. +// Represents an insurance item that has had it's common locale-name and value added to it. interface EnrichedItem extends Item { name: string; - maxPrice: number; + dynamicPrice: number; } diff --git a/project/src/controllers/LauncherController.ts b/project/src/controllers/LauncherController.ts index e3a1b441..0e280622 100644 --- a/project/src/controllers/LauncherController.ts +++ b/project/src/controllers/LauncherController.ts @@ -172,8 +172,18 @@ export class LauncherController return sessionID; } + /** + * Handle launcher requesting profile be wiped + * @param info IRegisterData + * @returns Session id + */ public wipe(info: IRegisterData): string { + if (!this.coreConfig.allowProfileWipe) + { + return; + } + const sessionID = this.login(info); if (sessionID) diff --git a/project/src/controllers/MatchController.ts b/project/src/controllers/MatchController.ts index 4869e4b8..60b69751 100644 --- a/project/src/controllers/MatchController.ts +++ b/project/src/controllers/MatchController.ts @@ -173,7 +173,7 @@ export class MatchController if (extractName && this.extractWasViaCoop(extractName) && this.traderConfig.fence.coopExtractGift.sendGift) { - this.handleCoopExtract(pmcData, extractName); + this.handleCoopExtract(sessionId, pmcData, extractName); this.sendCoopTakenFenceMessage(sessionId); } } @@ -225,10 +225,11 @@ export class MatchController /** * Handle when a player extracts using a coop extract - add rep to fence + * @param sessionId Session/player id * @param pmcData Profile * @param extractName Name of extract taken */ - protected handleCoopExtract(pmcData: IPmcData, extractName: string): void + protected handleCoopExtract(sessionId: string, pmcData: IPmcData, extractName: string): void { if (!pmcData.CoopExtractCounts) { @@ -256,6 +257,11 @@ export class MatchController // Check if new standing has leveled up trader this.traderHelper.lvlUp(fenceId, pmcData); pmcData.TradersInfo[fenceId].loyaltyLevel = Math.max(pmcData.TradersInfo[fenceId].loyaltyLevel, 1); + + // Copy updated fence rep values into scav profile to ensure consistency + const scavData: IPmcData = this.profileHelper.getScavProfile(sessionId); + scavData.TradersInfo[fenceId].standing = pmcData.TradersInfo[fenceId].standing; + scavData.TradersInfo[fenceId].loyaltyLevel = pmcData.TradersInfo[fenceId].loyaltyLevel; } /** @@ -313,6 +319,7 @@ export class MatchController this.logger.debug( `Car extract: ${extractName} used, total times taken: ${pmcData.CarExtractCounts[extractName]}`, ); + // Copy updated fence rep values into scav profile to ensure consistency const scavData: IPmcData = this.profileHelper.getScavProfile(sessionId); scavData.TradersInfo[fenceId].standing = pmcData.TradersInfo[fenceId].standing; diff --git a/project/src/controllers/ProfileController.ts b/project/src/controllers/ProfileController.ts index bed75009..4d225831 100644 --- a/project/src/controllers/ProfileController.ts +++ b/project/src/controllers/ProfileController.ts @@ -394,7 +394,19 @@ export class ProfileController */ public getFriends(info: ISearchFriendRequestData, sessionID: string): ISearchFriendResponse[] { - return [{ _id: this.hashUtil.generate(), Info: { Level: 1, Side: "Bear", Nickname: info.nickname } }]; + const profile = this.saveServer.getProfile(sessionID); + + // return some of the current player info for now + return [{ + _id: profile.characters.pmc._id, + aid: profile.characters.pmc.aid, + Info: { + Nickname: info.nickname, + Side: "Bear", + Level: 1, + MemberCategory: profile.characters.pmc.Info.MemberCategory, + }, + }]; } /** @@ -422,6 +434,7 @@ export class ProfileController { const player = this.profileHelper.getFullProfile(sessionId); const playerPmc = player.characters.pmc; + const playerScav = player.characters.scav; // return player for now return { @@ -458,8 +471,8 @@ export class ProfileController }, scavStats: { eft: { - totalInGameTime: player.characters.scav.Stats.Eft.TotalInGameTime, - overAllCounters: player.characters.scav.Stats.Eft.OverallCounters, + totalInGameTime: playerScav.Stats.Eft.TotalInGameTime, + overAllCounters: playerScav.Stats.Eft.OverallCounters, }, }, }; diff --git a/project/src/di/Container.ts b/project/src/di/Container.ts index 30ab1fb1..e3235f1f 100644 --- a/project/src/di/Container.ts +++ b/project/src/di/Container.ts @@ -90,7 +90,9 @@ import { BotHelper } from "@spt-aki/helpers/BotHelper"; import { BotWeaponGeneratorHelper } from "@spt-aki/helpers/BotWeaponGeneratorHelper"; import { ContainerHelper } from "@spt-aki/helpers/ContainerHelper"; import { SptCommandoCommands } from "@spt-aki/helpers/Dialogue/Commando/SptCommandoCommands"; -import { GiveSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveSptCommand"; +import { GiveSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand"; +import { ProfileSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand"; +import { TraderSptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand"; import { CommandoDialogueChatBot } from "@spt-aki/helpers/Dialogue/CommandoDialogueChatBot"; import { SptDialogueChatBot } from "@spt-aki/helpers/Dialogue/SptDialogueChatBot"; import { DialogueHelper } from "@spt-aki/helpers/DialogueHelper"; @@ -213,6 +215,7 @@ import { OpenZoneService } from "@spt-aki/services/OpenZoneService"; import { PaymentService } from "@spt-aki/services/PaymentService"; import { PlayerService } from "@spt-aki/services/PlayerService"; import { PmcChatResponseService } from "@spt-aki/services/PmcChatResponseService"; +import { ProfileActivityService } from "@spt-aki/services/ProfileActivityService"; import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService"; import { ProfileSnapshotService } from "@spt-aki/services/ProfileSnapshotService"; import { RagfairCategoriesService } from "@spt-aki/services/RagfairCategoriesService"; @@ -238,6 +241,7 @@ import { OnUpdateModService } from "@spt-aki/services/mod/onUpdate/OnUpdateModSe 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"; import { DatabaseImporter } from "@spt-aki/utils/DatabaseImporter"; import { EncodingUtil } from "@spt-aki/utils/EncodingUtil"; import { HashUtil } from "@spt-aki/utils/HashUtil"; @@ -374,6 +378,8 @@ export class Container // SptCommando Commands depContainer.registerType("SptCommand", "GiveSptCommand"); + depContainer.registerType("SptCommand", "TraderSptCommand"); + depContainer.registerType("SptCommand", "ProfileSptCommand"); } private static registerUtils(depContainer: DependencyContainer): void @@ -405,6 +411,7 @@ export class Container depContainer.register("HttpFileUtil", HttpFileUtil, { lifecycle: Lifecycle.Singleton }); depContainer.register("ModLoadOrder", ModLoadOrder, { lifecycle: Lifecycle.Singleton }); depContainer.register("ModTypeCheck", ModTypeCheck, { lifecycle: Lifecycle.Singleton }); + depContainer.register("CompareUtil", CompareUtil, { lifecycle: Lifecycle.Singleton }); } private static registerRouters(depContainer: DependencyContainer): void @@ -596,7 +603,13 @@ export class Container lifecycle: Lifecycle.Singleton, }); // SptCommands - depContainer.register("GiveSptCommand", GiveSptCommand); + depContainer.register("GiveSptCommand", GiveSptCommand, { lifecycle: Lifecycle.Singleton }); + depContainer.register("TraderSptCommand", TraderSptCommand, { + lifecycle: Lifecycle.Singleton, + }); + depContainer.register("ProfileSptCommand", ProfileSptCommand, { + lifecycle: Lifecycle.Singleton, + }); } private static registerLoaders(depContainer: DependencyContainer): void @@ -747,6 +760,10 @@ export class Container depContainer.register("GiftService", GiftService); depContainer.register("MailSendService", MailSendService); depContainer.register("RaidTimeAdjustmentService", RaidTimeAdjustmentService); + + depContainer.register("ProfileActivityService", ProfileActivityService, { + lifecycle: Lifecycle.Singleton, + }); } private static registerServers(depContainer: DependencyContainer): void diff --git a/project/src/generators/BotEquipmentModGenerator.ts b/project/src/generators/BotEquipmentModGenerator.ts index b439054f..3ba207da 100644 --- a/project/src/generators/BotEquipmentModGenerator.ts +++ b/project/src/generators/BotEquipmentModGenerator.ts @@ -234,8 +234,8 @@ export class BotEquipmentModGenerator } // Get the front/back/side weights based on bots level - const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find((x) => - settings.botLevel >= x.levelRange.min && settings.botLevel <= x.levelRange.max + const plateSlotWeights = settings.botEquipmentConfig?.armorPlateWeighting?.find((armorWeight) => + settings.botLevel >= armorWeight.levelRange.min && settings.botLevel <= armorWeight.levelRange.max ); if (!plateSlotWeights) { @@ -261,10 +261,10 @@ export class BotEquipmentModGenerator const chosenArmorPlateLevel = this.weightedRandomHelper.getWeightedValue(plateWeights); // Convert the array of ids into database items - const platesFromDb = existingPlateTplPool.map((x) => this.itemHelper.getItem(x)[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((x) => x._props.armorClass === chosenArmorPlateLevel); + const filteredPlates = platesFromDb.filter((item) => item._props.armorClass === chosenArmorPlateLevel); if (filteredPlates.length === 0) { this.logger.debug( @@ -306,7 +306,7 @@ export class BotEquipmentModGenerator // Only return the items ids result.result = Result.SUCCESS; - result.plateModTpls = filteredPlates.map((x) => x._id); + result.plateModTpls = filteredPlates.map((item) => item._id); return result; } @@ -468,8 +468,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((x) => x._name === "mod_handguard") - && !weapon.find((x) => x.slotId === "mod_launcher") + modSlot === "mod_handguard" && modToAddTemplate._props.Slots.find((slot) => + slot._name === "mod_handguard" + ) + && !weapon.find((item) => item.slotId === "mod_launcher") ) { // Needed for handguards with lower @@ -479,8 +481,8 @@ 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((x) => - x._name.includes("mod_stock") || botEquipConfig.forceStock + modSlot === "mod_stock" && (modToAddTemplate._props.Slots.find((slot) => + slot._name.includes("mod_stock") || botEquipConfig.forceStock )) ) { @@ -957,17 +959,25 @@ export class BotEquipmentModGenerator // You'd have a mod being picked without any sub-mods in its chain, possibly resulting in missing required mods not being added if (matchingMod) { - // Mod isnt in existing mod pool + // Mod is in existing mod pool if (itemModPool[modSlot].includes(matchingMod._tpl)) { // Found mod on preset + it already exists in mod pool return [matchingMod._tpl]; } - // Mod isnt in existing pool, only add if its got no children - if (this.itemHelper.getItem(matchingMod._tpl)[1]._props.Slots.length === 0) + // Check the filter of the slot to ensure a chosen mod fits + 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 + if ( + this.itemHelper.getItem(matchingMod._tpl)[1]._props.Slots.length === 0 + && parentSlotCompatibleItems.includes(matchingMod._tpl) + ) { - // Mod has no children + // Mod has no children and matches parent filters, can be used return [matchingMod._tpl]; } } @@ -1098,12 +1108,12 @@ export class BotEquipmentModGenerator } /** - * Log errors if mod is not compatible with slot - * @param modToAdd template of mod to check - * @param slotAddedToTemplate slot the item will be placed in - * @param modSlot slot the mod will fill - * @param parentTemplate template of the mods being added - * @param botRole + * Check if mod exists in db + is for a required slot + * @param modToAdd Db template of mod to check + * @param slotAddedToTemplate Slot object the item will be placed as child into + * @param modSlot Slot the mod will fill + * @param parentTemplate Db template of the mods being added + * @param botRole Bots wildspawntype (assault/pmcBot etc) * @returns true if valid */ protected isModValidForSlot( @@ -1114,31 +1124,31 @@ export class BotEquipmentModGenerator botRole: string, ): boolean { - const modBeingAddedTemplate = modToAdd[1]; + const modBeingAddedDbTemplate = modToAdd[1]; - // Mod lacks template item - if (!modBeingAddedTemplate) + // Mod lacks db template object + if (!modBeingAddedDbTemplate) { this.logger.error( this.localisationService.getText("bot-no_item_template_found_when_adding_mod", { - modId: modBeingAddedTemplate._id, + modId: modBeingAddedDbTemplate?._id ?? "UNKNOWN", modSlot: modSlot, }), ); - this.logger.debug(`Item -> ${parentTemplate._id}; Slot -> ${modSlot}`); + this.logger.debug(`Item -> ${parentTemplate?._id}; Slot -> ${modSlot}`); return false; } - // Mod isn't a valid item + // Mod has invalid db item if (!modToAdd[0]) { - // Slot must be filled, show warning + // Parent slot must be filled but db object is invalid, show warning and return false if (slotAddedToTemplate._required) { this.logger.warning( this.localisationService.getText("bot-unable_to_add_mod_item_invalid", { - itemName: modBeingAddedTemplate._name, + itemName: modBeingAddedDbTemplate?._name ?? "UNKNOWN", modSlot: modSlot, parentItemName: parentTemplate._name, botRole: botRole, @@ -1149,6 +1159,7 @@ export class BotEquipmentModGenerator return false; } + // Mod was found in db return true; } @@ -1165,7 +1176,7 @@ export class BotEquipmentModGenerator botEquipBlacklist: EquipmentFilterDetails, ): void { - const desiredSlotObject = modTemplate._props.Slots.find((x) => x._name.includes(desiredSlotName)); + const desiredSlotObject = modTemplate._props.Slots.find((slot) => slot._name.includes(desiredSlotName)); if (desiredSlotObject) { const supportedSubMods = desiredSlotObject._props.filters[0].Filter; @@ -1251,7 +1262,7 @@ export class BotEquipmentModGenerator const blacklist = this.itemFilterService.getBlacklistedItems().concat( botEquipBlacklist.equipment[modSlot] || [], ); - result = allowedMods.filter((x) => !blacklist.includes(x)); + result = allowedMods.filter((tpl) => !blacklist.includes(tpl)); return result; } @@ -1277,7 +1288,7 @@ export class BotEquipmentModGenerator weaponName: parentTemplate._name, }), ); - const camoraSlots = parentTemplate._props.Slots.filter((x) => x._name.startsWith("camora")); + const camoraSlots = parentTemplate._props.Slots.filter((slot) => slot._name.startsWith("camora")); // Attempt to generate camora slots for item modPool[parentTemplate._id] = {}; @@ -1411,16 +1422,16 @@ 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((x) => - ["mod_scope", "mod_scope_000"].includes(x._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((x) => - x._props.filters[0].Filter.every((x) => - this.itemHelper.isOfBaseclasses(x, whitelistedSightTypes) - || this.itemHelper.isOfBaseclass(x, BaseClasses.MOUNT) + scopeSlot?.every((slot) => + slot._props.filters[0].Filter.every((tpl) => + this.itemHelper.isOfBaseclasses(tpl, whitelistedSightTypes) + || this.itemHelper.isOfBaseclass(tpl, BaseClasses.MOUNT) ) ) ) diff --git a/project/src/generators/BotGenerator.ts b/project/src/generators/BotGenerator.ts index 0a9c5f93..dc572a86 100644 --- a/project/src/generators/BotGenerator.ts +++ b/project/src/generators/BotGenerator.ts @@ -258,13 +258,15 @@ export class BotGenerator * @param botJsonTemplate x.json from database * @param botGenerationDetails * @param botRole role of bot e.g. assault + * @param sessionId profile session id * @returns Nickname for bot */ + // TODO: Remove sessionId parameter from this function in v3.9.0 protected generateBotNickname( botJsonTemplate: IBotType, botGenerationDetails: BotGenerationDetails, botRole: string, - sessionId: string, + sessionId?: string, // @deprecated as of v3.8.1 ): string { const isPlayerScav = botGenerationDetails.isPlayerScav; @@ -273,9 +275,9 @@ export class BotGenerator this.randomUtil.getArrayValue(botJsonTemplate.lastName) || "" }`; name = name.trim(); - const playerProfile = this.profileHelper.getPmcProfile(sessionId); - // Simulate bot looking like a Player scav with the pmc name in brackets + // Simulate bot looking like a player scav with the PMC name in brackets. + // E.g. "ScavName (PMCName)" if (botRole === "assault" && this.randomUtil.getChance100(this.botConfig.chanceAssaultScavHasPlayerScavName)) { if (isPlayerScav) @@ -300,7 +302,7 @@ export class BotGenerator if (botGenerationDetails.isPmc && botGenerationDetails.allPmcsHaveSameNameAsPlayer) { const prefix = this.localisationService.getRandomTextThatMatchesPartialKey("pmc-name_prefix_"); - name = `${prefix} ${botGenerationDetails.playerName}`; + name = `${prefix} ${name}`; } return name; diff --git a/project/src/generators/BotLootGenerator.ts b/project/src/generators/BotLootGenerator.ts index e1c88ad9..9edadd85 100644 --- a/project/src/generators/BotLootGenerator.ts +++ b/project/src/generators/BotLootGenerator.ts @@ -98,6 +98,14 @@ export class BotLootGenerator ); const healingItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.healing.weights)); const drugItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.drugs.weights)); + + const foodItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.food.weights)); + const drinkItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.drink.weights)); + + const currencyItemCount = Number( + this.weightedRandomHelper.getWeightedValue(itemCounts.currency.weights), + ); + const stimItemCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.stims.weights)); const grenadeCount = Number(this.weightedRandomHelper.getWeightedValue(itemCounts.grenades.weights)); @@ -111,6 +119,10 @@ export class BotLootGenerator const containersBotHasAvailable = this.getAvailableContainersBotCanStoreItemsIn(botInventory); + // This set is passed as a reference to fill up the containers that are already full, this aliviates + // generation of the bots by avoiding checking the slots of containers we already know are full + const containersIdFull = new Set(); + // Special items this.addLootFromPool( this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SPECIAL, botJsonTemplate), @@ -119,6 +131,9 @@ export class BotLootGenerator botInventory, botRole, botItemLimits, + undefined, + undefined, + containersIdFull, ); // Healing items / Meds @@ -131,6 +146,7 @@ export class BotLootGenerator null, 0, isPmc, + containersIdFull, ); // Drugs @@ -143,6 +159,46 @@ export class BotLootGenerator null, 0, isPmc, + containersIdFull, + ); + + // Food + this.addLootFromPool( + this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.FOOD_ITEMS, botJsonTemplate), + containersBotHasAvailable, + foodItemCount, + botInventory, + botRole, + null, + 0, + isPmc, + containersIdFull, + ); + + // Drink + this.addLootFromPool( + this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.DRINK_ITEMS, botJsonTemplate), + containersBotHasAvailable, + drinkItemCount, + botInventory, + botRole, + null, + 0, + isPmc, + containersIdFull, + ); + + // Currency + this.addLootFromPool( + this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.CURRENCY_ITEMS, botJsonTemplate), + containersBotHasAvailable, + currencyItemCount, + botInventory, + botRole, + null, + 0, + isPmc, + containersIdFull, ); // Stims @@ -155,6 +211,7 @@ export class BotLootGenerator botItemLimits, 0, isPmc, + containersIdFull, ); // Grenades @@ -167,6 +224,7 @@ export class BotLootGenerator null, 0, isPmc, + containersIdFull, ); // Backpack - generate loot if they have one @@ -184,6 +242,7 @@ export class BotLootGenerator botRole, isPmc, botLevel, + containersIdFull, ); } @@ -196,6 +255,7 @@ export class BotLootGenerator botItemLimits, this.pmcConfig.maxBackpackLootTotalRub, isPmc, + containersIdFull, ); } @@ -212,6 +272,7 @@ export class BotLootGenerator botItemLimits, this.pmcConfig.maxVestLootTotalRub, isPmc, + containersIdFull, ); } @@ -225,19 +286,26 @@ export class BotLootGenerator botItemLimits, this.pmcConfig.maxPocketLootTotalRub, isPmc, + containersIdFull, ); // Secure - this.addLootFromPool( - this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate), - [EquipmentSlots.SECURED_CONTAINER], - 50, - botInventory, - botRole, - null, - -1, - isPmc, - ); + + // only add if not a pmc or is pmc and flag is true + if (!isPmc || (isPmc && this.pmcConfig.addSecureContainerLootFromBotConfig)) + { + this.addLootFromPool( + this.botLootCacheService.getLootFromCache(botRole, isPmc, LootCacheType.SECURE, botJsonTemplate), + [EquipmentSlots.SECURED_CONTAINER], + 50, + botInventory, + botRole, + null, + -1, + isPmc, + containersIdFull, + ); + } } /** @@ -282,19 +350,6 @@ export class BotLootGenerator true, ); - // eTG regen stim - this.addLootFromPool( - // eslint-disable-next-line @typescript-eslint/naming-convention - { "5c0e534186f7747fa1419867": 1 }, - [EquipmentSlots.SECURED_CONTAINER], - 2, - botInventory, - botRole, - null, - 0, - true, - ); - // AFAK this.addLootFromPool( // eslint-disable-next-line @typescript-eslint/naming-convention @@ -342,6 +397,7 @@ export class BotLootGenerator itemSpawnLimits: IItemSpawnLimitSettings = null, totalValueLimitRub = 0, isPmc = false, + containersIdFull = new Set(), ): void { // Loot pool has items @@ -434,6 +490,7 @@ export class BotLootGenerator itemToAddTemplate._id, itemWithChildrenToAdd, inventoryToAddItemsTo, + containersIdFull, ); // Handle when item cannot be added @@ -562,6 +619,7 @@ export class BotLootGenerator botRole: string, isPmc: boolean, botLevel: number, + containersIdFull?: Set, ): void { const chosenWeaponType = this.randomUtil.getArrayValue([ @@ -594,6 +652,7 @@ export class BotLootGenerator generatedWeapon.weapon[0]._tpl, [...generatedWeapon.weapon], botInventory, + containersIdFull, ); if (result !== ItemAddedResult.SUCCESS) diff --git a/project/src/generators/FenceBaseAssortGenerator.ts b/project/src/generators/FenceBaseAssortGenerator.ts index 1ad5fb76..25a3cf3d 100644 --- a/project/src/generators/FenceBaseAssortGenerator.ts +++ b/project/src/generators/FenceBaseAssortGenerator.ts @@ -14,6 +14,7 @@ import { ITraderConfig } from "@spt-aki/models/spt/config/ITraderConfig"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ConfigServer } from "@spt-aki/servers/ConfigServer"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; +import { FenceService } from "@spt-aki/services/FenceService"; import { ItemFilterService } from "@spt-aki/services/ItemFilterService"; import { SeasonalEventService } from "@spt-aki/services/SeasonalEventService"; import { HashUtil } from "@spt-aki/utils/HashUtil"; @@ -35,6 +36,7 @@ export class FenceBaseAssortGenerator @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("SeasonalEventService") protected seasonalEventService: SeasonalEventService, @inject("ConfigServer") protected configServer: ConfigServer, + @inject("FenceService") protected fenceService: FenceService, ) { this.traderConfig = this.configServer.getConfig(ConfigTypes.TRADER); @@ -74,7 +76,7 @@ export class FenceBaseAssortGenerator } } - // Only allow rigs with no slots (carrier rigs) + // Only allow rigs with no slots (carrier rigs) if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.VEST) && rootItemDb._props.Slots.length > 0) { continue; @@ -95,9 +97,22 @@ export class FenceBaseAssortGenerator upd: { StackObjectsCount: 9999999 }, }]; + // Ensure ammo is not above penetration limit value + if (this.itemHelper.isOfBaseclasses(rootItemDb._id, [BaseClasses.AMMO_BOX, BaseClasses.AMMO])) + { + if (this.isAmmoAbovePenetrationLimit(rootItemDb)) + { + continue; + } + } + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) { - this.itemHelper.addCartridgesToAmmoBox(itemWithChildrenToAdd, rootItemDb); + // Only add cartridges to box if box has no children + if (itemWithChildrenToAdd.length === 1) + { + this.itemHelper.addCartridgesToAmmoBox(itemWithChildrenToAdd, rootItemDb); + } } // Ensure IDs are unique @@ -110,7 +125,7 @@ export class FenceBaseAssortGenerator // Create barter scheme (price) const barterSchemeToAdd: IBarterScheme = { - count: Math.round(this.getItemPrice(rootItemDb._id, itemWithChildrenToAdd)), + count: Math.round(this.fenceService.getItemPrice(rootItemDb._id, itemWithChildrenToAdd)), _tpl: Money.ROUBLES, }; @@ -175,25 +190,51 @@ export class FenceBaseAssortGenerator } } - protected getItemPrice(itemTpl: string, items: Item[]): number + /** + * Check ammo in boxes + loose ammos has a penetration value above the configured value in trader.json / ammoMaxPenLimit + * @param rootItemDb Ammo box or ammo item from items.db + * @returns True if penetration value is above limit set in config + */ + protected isAmmoAbovePenetrationLimit(rootItemDb: ITemplateItem): boolean { - return this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.AMMO_BOX) - ? this.getAmmoBoxPrice(items) * this.traderConfig.fence.itemPriceMult - : this.handbookHelper.getTemplatePrice(itemTpl) * this.traderConfig.fence.itemPriceMult; - } - - protected getAmmoBoxPrice(items: Item[]): number - { - let total = 0; - for (const item of items) + const ammoPenetrationPower = this.getAmmoPenetrationPower(rootItemDb); + if (ammoPenetrationPower === null) { - if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO)) - { - total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd.StackObjectsCount ?? 1); - } + this.logger.warning(`Ammo: ${rootItemDb._id} has no penetration value, skipping`); + return false; } - return total; + return ammoPenetrationPower > this.traderConfig.fence.ammoMaxPenLimit; + } + + /** + * Get the penetration power value of an ammo, works with ammo boxes and raw ammos + * @param rootItemDb Ammo box or ammo item from items.db + * @returns Penetration power of passed in item, null if it doesnt have a power + */ + protected getAmmoPenetrationPower(rootItemDb: ITemplateItem): number + { + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO_BOX)) + { + const ammoTplInBox = rootItemDb._props.StackSlots[0]._props.filters[0].Filter[0]; + const ammoItemDb = this.itemHelper.getItem(ammoTplInBox); + if (!ammoItemDb[0]) + { + this.logger.warning(`Ammo: ${ammoTplInBox} not an item, skipping`); + return null; + } + + return ammoItemDb[1]._props.PenetrationPower; + } + + // Plain old ammo, get its pen property + if (this.itemHelper.isOfBaseclass(rootItemDb._id, BaseClasses.AMMO)) + { + return rootItemDb._props.PenetrationPower; + } + + // Not an ammobox or ammo + return null; } /** diff --git a/project/src/generators/LocationGenerator.ts b/project/src/generators/LocationGenerator.ts index cf523064..1b83642e 100644 --- a/project/src/generators/LocationGenerator.ts +++ b/project/src/generators/LocationGenerator.ts @@ -218,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((x) => - x.template.Id === chosenContainerId + const containerObject = staticRandomisableContainersOnMap.find((staticContainer) => + staticContainer.template.Id === chosenContainerId ); if (!containerObject) { @@ -262,10 +262,10 @@ export class LocationGenerator */ protected getRandomisableContainersOnMap(staticContainers: IStaticContainerData[]): IStaticContainerData[] { - return staticContainers.filter((x) => - x.probability !== 1 && !x.template.IsAlwaysSpawn + return staticContainers.filter((staticContainer) => + staticContainer.probability !== 1 && !staticContainer.template.IsAlwaysSpawn && !this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( - x.template.Items[0]._tpl, + staticContainer.template.Items[0]._tpl, ) ); } @@ -277,10 +277,10 @@ export class LocationGenerator */ protected getGuaranteedContainers(staticContainersOnMap: IStaticContainerData[]): IStaticContainerData[] { - return staticContainersOnMap.filter((x) => - x.probability === 1 || x.template.IsAlwaysSpawn + return staticContainersOnMap.filter((staticContainer) => + staticContainer.probability === 1 || staticContainer.template.IsAlwaysSpawn || this.locationConfig.containerRandomisationSettings.containerTypesToNotRandomise.includes( - x.template.Items[0]._tpl, + staticContainer.template.Items[0]._tpl, ) ); } @@ -659,7 +659,9 @@ export class LocationGenerator } // Filter out duplicate locationIds - chosenSpawnpoints = [...new Map(chosenSpawnpoints.map((x) => [x.locationId, x])).values()]; + chosenSpawnpoints = [ + ...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; @@ -702,7 +704,7 @@ export class LocationGenerator { if ( !seasonalEventActive && seasonalItemTplBlacklist.includes( - spawnPoint.template.Items.find((x) => x._id === itemDist.composedKey.key)._tpl, + spawnPoint.template.Items.find((item) => item._id === itemDist.composedKey.key)._tpl, ) ) { @@ -753,7 +755,9 @@ export class LocationGenerator for (const itemTpl of lootToForceSingleAmountOnMap) { // Get all spawn positions for item tpl in forced loot array - const items = forcedSpawnPoints.filter((x) => x.template.Items[0]._tpl === itemTpl); + const items = forcedSpawnPoints.filter((forcedSpawnPoint) => + forcedSpawnPoint.template.Items[0]._tpl === itemTpl + ); if (!items || items.length === 0) { this.logger.debug( @@ -776,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((x) => x.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; @@ -812,7 +816,9 @@ 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((x) => x.Id === locationTemplateToAdd.Id); + const existingLocation = lootLocationTemplates.find((spawnPoint) => + spawnPoint.Id === locationTemplateToAdd.Id + ); if (!existingLocation) { lootLocationTemplates.push(locationTemplateToAdd); @@ -839,7 +845,7 @@ export class LocationGenerator staticAmmoDist: Record, ): IContainerItem { - const chosenItem = spawnPoint.template.Items.find((x) => x._id === chosenComposedKey); + const chosenItem = spawnPoint.template.Items.find((item) => item._id === chosenComposedKey); const chosenTpl = chosenItem._tpl; const itemTemplate = this.itemHelper.getItem(chosenTpl)[1]; @@ -871,7 +877,7 @@ export class LocationGenerator // Create array with just magazine const magazineItem: Item[] = [{ _id: this.objectId.generate(), _tpl: chosenTpl }]; - if (this.randomUtil.getChance100(this.locationConfig.magazineLootHasAmmoChancePercent)) + if (this.randomUtil.getChance100(this.locationConfig.staticMagazineLootHasAmmoChancePercent)) { // Add randomised amount of cartridges this.itemHelper.fillMagazineWithRandomCartridge( @@ -942,7 +948,7 @@ export class LocationGenerator return items.find((v) => v._tpl === chosenTpl && v.parentId === undefined); } - return items.find((x) => x._tpl === chosenTpl); + return items.find((item) => item._tpl === chosenTpl); } // TODO: rewrite, BIG yikes diff --git a/project/src/generators/LootGenerator.ts b/project/src/generators/LootGenerator.ts index a73a0094..4b63f810 100644 --- a/project/src/generators/LootGenerator.ts +++ b/project/src/generators/LootGenerator.ts @@ -99,12 +99,16 @@ export class LootGenerator && options.itemTypeWhitelist.includes(x[1]._parent) ); - const randomisedItemCount = this.randomUtil.getInt(options.itemCount.min, options.itemCount.max); - for (let index = 0; index < randomisedItemCount; index++) + if (items.length > 0) { - if (!this.findAndAddRandomItemToLoot(items, itemTypeCounts, options, result)) + const randomisedItemCount = this.randomUtil.getInt(options.itemCount.min, options.itemCount.max); + for (let index = 0; index < randomisedItemCount; index++) { - index--; + if (!this.findAndAddRandomItemToLoot(items, itemTypeCounts, options, result)) + { + // Failed to add, reduce index so we get another attempt + index--; + } } } @@ -122,13 +126,22 @@ export class LootGenerator this.itemHelper.isOfBaseclass(preset._encyclopedia, BaseClasses.WEAPON) ); - for (let index = 0; index < randomisedWeaponPresetCount; index++) + if (weaponDefaultPresets.length > 0) { - if ( - !this.findAndAddRandomPresetToLoot(weaponDefaultPresets, itemTypeCounts, itemBlacklistArray, result) - ) + for (let index = 0; index < randomisedWeaponPresetCount; index++) { - index--; + if ( + !this.findAndAddRandomPresetToLoot( + weaponDefaultPresets, + itemTypeCounts, + itemBlacklistArray, + result, + ) + ) + { + // Failed to add, reduce index so we get another attempt + index--; + } } } } @@ -146,18 +159,24 @@ export class LootGenerator const levelFilteredArmorPresets = armorDefaultPresets.filter((armor) => this.armorIsDesiredProtectionLevel(armor, options) ); - for (let index = 0; index < randomisedArmorPresetCount; index++) + + // Add some armors to rewards + if (levelFilteredArmorPresets.length > 0) { - if ( - !this.findAndAddRandomPresetToLoot( - levelFilteredArmorPresets, - itemTypeCounts, - itemBlacklistArray, - result, - ) - ) + for (let index = 0; index < randomisedArmorPresetCount; index++) { - index--; + if ( + !this.findAndAddRandomPresetToLoot( + levelFilteredArmorPresets, + itemTypeCounts, + itemBlacklistArray, + result, + ) + ) + { + // Failed to add, reduce index so we get another attempt + index--; + } } } } @@ -166,10 +185,10 @@ export class LootGenerator } /** - * Filter armor items by their main plates protection level - * @param armor Armor preset - * @param options Loot request options - * @returns True item passes checks + * Filter armor items by their front plates protection level - top if its a helmet + * @param armor Armor preset to check + * @param options Loot request options - armor level etc + * @returns True if item has desired armor level */ protected armorIsDesiredProtectionLevel(armor: IPreset, options: LootRequest): boolean { @@ -290,68 +309,76 @@ export class LootGenerator /** * Find a random item in items.json and add to result array - * @param globalDefaultPresets presets to choose from - * @param itemTypeCounts item limit counts - * @param itemBlacklist items to skip - * @param result array to add found preset to + * @param presetPool Presets to choose from + * @param itemTypeCounts Item limit counts + * @param itemBlacklist Items to skip + * @param result Array to add chosen preset to * @returns true if preset was valid and added to pool */ protected findAndAddRandomPresetToLoot( - globalDefaultPresets: IPreset[], + presetPool: IPreset[], itemTypeCounts: Record, itemBlacklist: string[], result: LootItem[], ): boolean { - // Choose random preset and get details from item.json using encyclopedia value (encyclopedia === tplId) - const randomPreset = this.randomUtil.getArrayValue(globalDefaultPresets); - if (!randomPreset?._encyclopedia) + // Choose random preset and get details from item db using encyclopedia value (encyclopedia === tplId) + const chosenPreset = this.randomUtil.getArrayValue(presetPool); + if (!chosenPreset) { - this.logger.debug(`Airdrop - preset with id: ${randomPreset._id} lacks encyclopedia property, skipping`); + this.logger.warning("Unable to find random preset in given presets, skipping"); return false; } - const itemDetails = this.itemHelper.getItem(randomPreset._encyclopedia); - if (!itemDetails[0]) + // No `_encyclopedia` property, not possible to reliably get root item tpl + if (!chosenPreset?._encyclopedia) { - this.logger.debug(`Airdrop - Unable to find preset with tpl: ${randomPreset._encyclopedia}, skipping`); + this.logger.debug(`Preset with id: ${chosenPreset?._id} lacks encyclopedia property, skipping`); return false; } - // Skip blacklisted items - if (itemBlacklist.includes(randomPreset._items[0]._tpl)) + // Get preset root item db details via its `_encyclopedia` property + const itemDbDetails = this.itemHelper.getItem(chosenPreset._encyclopedia); + if (!itemDbDetails[0]) { - return false; - } - - // Some custom mod items are lacking a parent property - if (!itemDetails[1]._parent) - { - this.logger.error(this.localisationService.getText("loot-item_missing_parentid", itemDetails[1]?._name)); + this.logger.debug(`Unable to find preset with tpl: ${chosenPreset._encyclopedia}, skipping`); return false; } - // Check picked preset hasn't exceeded spawn limit - const itemLimitCount = itemTypeCounts[itemDetails[1]._parent]; + // Skip preset if root item is blacklisted + if (itemBlacklist.includes(chosenPreset._items[0]._tpl)) + { + return false; + } + + // Some custom mod items lack a parent property + if (!itemDbDetails[1]._parent) + { + this.logger.error(this.localisationService.getText("loot-item_missing_parentid", itemDbDetails[1]?._name)); + + return false; + } + + // Check chosen preset hasn't exceeded spawn limit + const itemLimitCount = itemTypeCounts[itemDbDetails[1]._parent]; if (itemLimitCount && itemLimitCount.current > itemLimitCount.max) { return false; } - const newLootItem: LootItem = { tpl: randomPreset._items[0]._tpl, isPreset: true, stackCount: 1 }; - - result.push(newLootItem); + // Add chosen preset tpl to result array + result.push({ tpl: chosenPreset._items[0]._tpl, isPreset: true, stackCount: 1 }); if (itemLimitCount) { - // increment item count as its in limit array + // Increment item count as item has been chosen and its inside itemLimitCount dictionary itemLimitCount.current++; } - // item added okay + // Item added okay return true; } @@ -364,10 +391,12 @@ export class LootGenerator { const itemsToReturn: Item[][] = []; - // choose a weapon to give to the player (weighted) + // Choose a weapon to give to the player (weighted) const chosenWeaponTpl = this.weightedRandomHelper.getWeightedValue( containerSettings.weaponRewardWeight, ); + + // Get itemDb details of weapon const weaponDetailsDb = this.itemHelper.getItem(chosenWeaponTpl); if (!weaponDetailsDb[0]) { @@ -378,24 +407,26 @@ export class LootGenerator return itemsToReturn; } - // Get weapon preset - default or choose a random one from all possible + // Get weapon preset - default or choose a random one from globals.json preset pool let chosenWeaponPreset = (containerSettings.defaultPresetsOnly) ? this.presetHelper.getDefaultPreset(chosenWeaponTpl) : this.randomUtil.getArrayValue(this.presetHelper.getPresets(chosenWeaponTpl)); + // No default preset found for weapon, choose a random one if (!chosenWeaponPreset) { this.logger.warning(`Default preset for weapon ${chosenWeaponTpl} not found, choosing random instead`); chosenWeaponPreset = this.randomUtil.getArrayValue(this.presetHelper.getPresets(chosenWeaponTpl)); } + // Clean up Ids to ensure they're all unique and prevent collisions const presetAndMods: Item[] = this.itemHelper.replaceIDs(chosenWeaponPreset._items); this.itemHelper.remapRootItemId(presetAndMods); // Add preset to return object itemsToReturn.push(presetAndMods); - // Get items related to chosen weapon + // Get a random collection of weapon mods related to chosen weawpon and add them to result array const linkedItemsToWeapon = this.ragfairLinkedItemService.getLinkedDbItems(chosenWeaponTpl); itemsToReturn.push( ...this.getSealedContainerWeaponModRewards(containerSettings, linkedItemsToWeapon, chosenWeaponPreset), diff --git a/project/src/generators/PMCLootGenerator.ts b/project/src/generators/PMCLootGenerator.ts index ff7d4f93..b4f1b765 100644 --- a/project/src/generators/PMCLootGenerator.ts +++ b/project/src/generators/PMCLootGenerator.ts @@ -192,7 +192,7 @@ export class PMCLootGenerator for (const itemToAdd of itemsToAdd) { - // If pmc has override, use that. Otherwise use flea price + // If pmc has price override, use that. Otherwise use flea price if (pmcPriceOverrides[itemToAdd._id]) { this.backpackLootPool[itemToAdd._id] = pmcPriceOverrides[itemToAdd._id]; @@ -270,13 +270,14 @@ export class PMCLootGenerator protected gcd(a: number, b: number): number { - while (b !== 0) + let x = a; + let y = b; + while (y !== 0) { - const temp = b; - b = a % b; - a = temp; + const temp = y; + y = x % y; + x = temp; } - - return a; + return x; } } diff --git a/project/src/generators/ScavCaseRewardGenerator.ts b/project/src/generators/ScavCaseRewardGenerator.ts index 8328edd5..6442f20d 100644 --- a/project/src/generators/ScavCaseRewardGenerator.ts +++ b/project/src/generators/ScavCaseRewardGenerator.ts @@ -96,11 +96,12 @@ export class ScavCaseRewardGenerator */ protected cacheDbItems(): void { + // TODO: pre-loop and get array of valid items, e.g. non-node/non-blacklisted, then loop over those results for below code + + // Get an array of seasonal items that should not be shown right now as seasonal event is not active + const inactiveSeasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems(); if (!this.dbItemsCache) { - // Get an array of seasonal items that should not be shown right now as seasonal event is not active - const seasonalItems = this.seasonalEventService.getInactiveSeasonalEventItems(); - this.dbItemsCache = Object.values(this.databaseServer.getTables().templates.items).filter((item) => { // Base "Item" item has no parent, ignore it @@ -129,7 +130,7 @@ export class ScavCaseRewardGenerator return false; } - // Globally blacklisted + // Globally reward-blacklisted if (this.itemFilterService.isItemRewardBlacklisted(item._id)) { return false; @@ -146,7 +147,7 @@ export class ScavCaseRewardGenerator return false; } - if (seasonalItems.includes(item._id)) + if (inactiveSeasonalItems.includes(item._id)) { return false; } @@ -176,6 +177,32 @@ export class ScavCaseRewardGenerator return false; } + // Skip item if item id is on blacklist + if ( + this.scavCaseConfig.rewardItemBlacklist.includes(item._id) + || this.itemFilterService.isItemBlacklisted(item._id) + ) + { + return false; + } + + // Globally reward-blacklisted + if (this.itemFilterService.isItemRewardBlacklisted(item._id)) + { + return false; + } + + if (!this.scavCaseConfig.allowBossItemsAsRewards && this.itemFilterService.isBossItem(item._id)) + { + return false; + } + + // Skip seasonal items + if (inactiveSeasonalItems.includes(item._id)) + { + return false; + } + // Skip ammo that doesn't stack as high as value in config if (item._props.StackMaxSize < this.scavCaseConfig.ammoRewards.minStackSize) { diff --git a/project/src/helpers/AssortHelper.ts b/project/src/helpers/AssortHelper.ts index 10c2ec65..6b0c2a29 100644 --- a/project/src/helpers/AssortHelper.ts +++ b/project/src/helpers/AssortHelper.ts @@ -37,6 +37,8 @@ export class AssortHelper flea = false, ): ITraderAssort { + let strippedTraderAssorts = traderAssorts; + // Trader assort does not always contain loyal_level_items if (!traderAssorts.loyal_level_items) { @@ -45,7 +47,7 @@ export class AssortHelper return traderAssorts; } - // Iterate over all assorts, removing items that don't fulfil the requirements + // Iterate over all assorts, removing items that haven't yet been unlocked by quests (ASSORTMENT_UNLOCK) for (const assortId in traderAssorts.loyal_level_items) { // Get quest id that unlocks assort + statuses quest can be in to show assort @@ -59,11 +61,11 @@ export class AssortHelper const questStatusInProfile = this.questHelper.getQuestStatus(pmcProfile, unlockValues.questId); if (!unlockValues.status.includes(questStatusInProfile)) { - traderAssorts = this.removeItemFromAssort(traderAssorts, assortId, flea); + strippedTraderAssorts = this.removeItemFromAssort(traderAssorts, assortId, flea); } } - return traderAssorts; + return strippedTraderAssorts; } /** @@ -108,24 +110,26 @@ export class AssortHelper */ public stripLockedLoyaltyAssort(pmcProfile: IPmcData, traderId: string, assort: ITraderAssort): ITraderAssort { + let strippedAssort = assort; + // Trader assort does not always contain loyal_level_items if (!assort.loyal_level_items) { this.logger.warning(this.localisationService.getText("assort-missing_loyalty_level_object", traderId)); - return assort; + return strippedAssort; } - // Remove items not unlocked from quest status change (ASSORTMENT_UNLOCK) + // Remove items restricted by loyalty levels above those reached by the player for (const itemId in assort.loyal_level_items) { if (assort.loyal_level_items[itemId] > pmcProfile.TradersInfo[traderId].loyaltyLevel) { - assort = this.removeItemFromAssort(assort, itemId); + strippedAssort = this.removeItemFromAssort(assort, itemId); } } - return assort; + return strippedAssort; } /** diff --git a/project/src/helpers/BotGeneratorHelper.ts b/project/src/helpers/BotGeneratorHelper.ts index a8620512..698a61de 100644 --- a/project/src/helpers/BotGeneratorHelper.ts +++ b/project/src/helpers/BotGeneratorHelper.ts @@ -532,12 +532,17 @@ export class BotGeneratorHelper rootItemTplId: string, itemWithChildren: Item[], inventory: Inventory, + containersIdFull?: Set, ): ItemAddedResult { /** Track how many containers are unable to be found */ let missingContainerCount = 0; for (const equipmentSlotId of equipmentSlots) { + if (containersIdFull?.has(equipmentSlotId)) + { + continue; + } // Get container to put item into const container = inventory.items.find((item) => item.slotId === equipmentSlotId); if (!container) @@ -583,8 +588,11 @@ export class BotGeneratorHelper const totalSlotGridCount = containerTemplate[1]._props.Grids.length; for (const slotGrid of containerTemplate[1]._props.Grids) { - // Grid is empty, skip - if (slotGrid._props.cellsH === 0 || slotGrid._props.cellsV === 0) + // Grid is empty, skip or item size is bigger than grid + if ( + (slotGrid._props.cellsH === 0 || slotGrid._props.cellsV === 0) + || (itemSize[0] * itemSize[1] > slotGrid._props.cellsV * slotGrid._props.cellsH) + ) { continue; } @@ -592,12 +600,6 @@ export class BotGeneratorHelper // Can't put item type in grid, skip all grids as we're assuming they have the same rules if (!this.itemAllowedInContainer(slotGrid, rootItemTplId)) { - // Only one possible slot and item is incompatible, exit function and inform caller - if (equipmentSlots.length === 1) - { - return ItemAddedResult.INCOMPATIBLE_ITEM; - } - // Multiple containers, maybe next one allows item, only break out of loop for this containers grids break; } @@ -653,15 +655,25 @@ export class BotGeneratorHelper // If we've checked all grids in container and reached this point, there's no space for item if (currentGridCount >= totalSlotGridCount) { - return ItemAddedResult.NO_SPACE; + break; } - currentGridCount++; + currentGridCount++; // No space in this grid, move to next container grid and try again } + + // if we got to this point, the item couldnt be placed on the container + if (containersIdFull) + { + // if the item was a one by one, we know it must be full. Or if the maps cant find a slot for a one by one + if ((itemSize[0] === 1 && itemSize[1] === 1)) + { + containersIdFull.add(equipmentSlotId); + } + } } - return ItemAddedResult.UNKNOWN; + return ItemAddedResult.NO_SPACE; } /** @@ -673,8 +685,8 @@ export class BotGeneratorHelper protected itemAllowedInContainer(slotGrid: Grid, itemTpl: string): boolean { const propFilters = slotGrid._props.filters; - const excludedFilter = propFilters[0]?.ExcludedFilter; - const filter = propFilters[0]?.Filter; + const excludedFilter = propFilters[0]?.ExcludedFilter ?? []; + const filter = propFilters[0]?.Filter ?? []; if (propFilters.length === 0) { @@ -688,19 +700,19 @@ export class BotGeneratorHelper const itemDetails = this.itemHelper.getItem(itemTpl)[1]; // if item to add is found in exclude filter, not allowed - if (excludedFilter.includes(itemDetails._parent)) + if (excludedFilter?.includes(itemDetails._parent)) { return false; } // If Filter array only contains 1 filter and its for basetype 'item', allow it - if (filter.length === 1 && filter.includes(BaseClasses.ITEM)) + if (filter?.length === 1 && filter.includes(BaseClasses.ITEM)) { return true; } // If allowed filter has something in it + filter doesnt have basetype 'item', not allowed - if (filter.length > 0 && !filter.includes(itemDetails._parent)) + if (filter?.length > 0 && !filter.includes(itemDetails._parent)) { return false; } diff --git a/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts b/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts new file mode 100644 index 00000000..c5f9b5c1 --- /dev/null +++ b/project/src/helpers/Dialogue/AbstractDialogueChatBot.ts @@ -0,0 +1,97 @@ +import { IChatCommand, ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand"; +import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot"; +import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; +import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; +import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; +import { MailSendService } from "@spt-aki/services/MailSendService"; + +export abstract class AbstractDialogueChatBot implements IDialogueChatBot +{ + public constructor( + protected logger: ILogger, + protected mailSendService: MailSendService, + protected chatCommands: IChatCommand[] | ICommandoCommand[], + ) + { + } + + /** + * @deprecated As of v3.7.6. Use registerChatCommand. + */ + // TODO: v3.9.0 - Remove registerCommandoCommand method. + public registerCommandoCommand(chatCommand: IChatCommand | ICommandoCommand): void + { + this.registerChatCommand(chatCommand); + } + + public registerChatCommand(chatCommand: IChatCommand | ICommandoCommand): void + { + if (this.chatCommands.some((cc) => cc.getCommandPrefix() === chatCommand.getCommandPrefix())) + { + throw new Error( + `The command "${chatCommand.getCommandPrefix()}" attempting to be registered already exists.`, + ); + } + this.chatCommands.push(chatCommand); + } + + public abstract getChatBot(): IUserDialogInfo; + + protected abstract getUnrecognizedCommandMessage(): string; + + public handleMessage(sessionId: string, request: ISendMessageRequest): string + { + if ((request.text ?? "").length === 0) + { + this.logger.error("Command came in as empty text! Invalid data!"); + return request.dialogId; + } + + const splitCommand = request.text.split(" "); + + const commandos = this.chatCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]); + if (commandos[0]?.getCommands().has(splitCommand[1])) + { + return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request); + } + + if (splitCommand[0].toLowerCase() === "help") + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + this.getChatBot(), + "The available commands will be listed below:", + ); + // due to BSG being dumb with messages we need a mandatory timeout between messages so they get out on the right order + setTimeout(() => + { + for (const chatCommand of this.chatCommands) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + this.getChatBot(), + `Commands available for "${chatCommand.getCommandPrefix()}" prefix:`, + ); + setTimeout(() => + { + for (const subCommand of chatCommand.getCommands()) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + this.getChatBot(), + `Subcommand ${subCommand}:\n${chatCommand.getCommandHelp(subCommand)}`, + ); + } + }, 1000); + } + }, 1000); + return request.dialogId; + } + + this.mailSendService.sendUserMessageToPlayer( + sessionId, + this.getChatBot(), + this.getUnrecognizedCommandMessage(), + ); + } +} diff --git a/project/src/helpers/Dialogue/Commando/ICommandoCommand.ts b/project/src/helpers/Dialogue/Commando/IChatCommand.ts similarity index 66% rename from project/src/helpers/Dialogue/Commando/ICommandoCommand.ts rename to project/src/helpers/Dialogue/Commando/IChatCommand.ts index 03083f3b..93a63487 100644 --- a/project/src/helpers/Dialogue/Commando/ICommandoCommand.ts +++ b/project/src/helpers/Dialogue/Commando/IChatCommand.ts @@ -1,7 +1,12 @@ import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; -export interface ICommandoCommand +/** + * @deprecated As of v3.7.6. Use IChatCommand. Will be removed in v3.9.0. + */ +// TODO: v3.9.0 - Remove ICommandoCommand. +export type ICommandoCommand = IChatCommand; +export interface IChatCommand { getCommandPrefix(): string; getCommandHelp(command: string): string; diff --git a/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts b/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts index 82017853..1c2a6f46 100644 --- a/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts +++ b/project/src/helpers/Dialogue/Commando/SptCommandoCommands.ts @@ -1,4 +1,4 @@ -import { ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/ICommandoCommand"; +import { IChatCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand"; import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand"; import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; @@ -8,7 +8,7 @@ import { ConfigServer } from "@spt-aki/servers/ConfigServer"; import { inject, injectAll, injectable } from "tsyringe"; @injectable() -export class SptCommandoCommands implements ICommandoCommand +export class SptCommandoCommands implements IChatCommand { constructor( @inject("ConfigServer") protected configServer: ConfigServer, @@ -31,7 +31,7 @@ export class SptCommandoCommands implements ICommandoCommand { if (this.sptCommands.some((c) => c.getCommand() === command.getCommand())) { - throw new Error(`The command ${command.getCommand()} being registered for SPT Commands already exists!`); + throw new Error(`The command "${command.getCommand()}" attempting to be registered already exists.`); } this.sptCommands.push(command); } diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts new file mode 100644 index 00000000..06624375 --- /dev/null +++ b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/GiveSptCommand.ts @@ -0,0 +1,288 @@ +import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; +import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand"; +import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; +import { PresetHelper } from "@spt-aki/helpers/PresetHelper"; +import { Item } from "@spt-aki/models/eft/common/tables/IItem"; +import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; +import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; +import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; +import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; +import { ItemFilterService } from "@spt-aki/services/ItemFilterService"; +import { LocaleService } from "@spt-aki/services/LocaleService"; +import { MailSendService } from "@spt-aki/services/MailSendService"; +import { HashUtil } from "@spt-aki/utils/HashUtil"; +import { JsonUtil } from "@spt-aki/utils/JsonUtil"; +import { closestMatch, distance } from "closest-match"; +import { inject, injectable } from "tsyringe"; + +@injectable() +export class GiveSptCommand implements ISptCommand +{ + /** + * Regex to account for all these cases: + * spt give "item name" 5 + * spt give templateId 5 + * spt give en "item name in english" 5 + * spt give es "nombre en español" 5 + * spt give 5 <== this is the reply when the algo isn't sure about an item + */ + private static commandRegex = /^spt give (((([a-z]{2,5}) )?"(.+)"|\w+) )?([0-9]+)$/; + private static maxAllowedDistance = 1.5; + + protected savedCommand: Map = new Map(); + + public constructor( + @inject("WinstonLogger") protected logger: ILogger, + @inject("ItemHelper") protected itemHelper: ItemHelper, + @inject("HashUtil") protected hashUtil: HashUtil, + @inject("JsonUtil") protected jsonUtil: JsonUtil, + @inject("PresetHelper") protected presetHelper: PresetHelper, + @inject("MailSendService") protected mailSendService: MailSendService, + @inject("LocaleService") protected localeService: LocaleService, + @inject("DatabaseServer") protected databaseServer: DatabaseServer, + @inject("ItemFilterService") protected itemFilterService: ItemFilterService, + ) + { + } + + public getCommand(): string + { + return "give"; + } + + public getCommandHelp(): string + { + return "spt give\n========\nSends items to the player through the message system.\n\n\tspt give [template ID] [quantity]\n\t\tEx: spt give 544fb25a4bdc2dfb738b4567 2\n\n\tspt give [\"item name\"] [quantity]\n\t\tEx: spt give \"pack of sugar\" 10\n\n\tspt give [locale] [\"item name\"] [quantity]\n\t\tEx: spt give fr \"figurine de chat\" 3"; + } + + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string + { + if (!GiveSptCommand.commandRegex.test(request.text)) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of give command. Use \"help\" for more information.", + ); + return request.dialogId; + } + + const result = GiveSptCommand.commandRegex.exec(request.text); + + let item: string; + let quantity: number; + let isItemName: boolean; + let locale: string; + + // This is a reply to a give request previously made pending a reply + if (result[1] === undefined) + { + if (!this.savedCommand.has(sessionId)) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of give command. Use \"help\" for more information.", + ); + return request.dialogId; + } + const savedCommand = this.savedCommand.get(sessionId); + if (+result[6] > savedCommand.potentialItemNames.length) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid selection. Outside of bounds! Use \"help\" for more information.", + ); + return request.dialogId; + } + item = savedCommand.potentialItemNames[+result[6] - 1]; + quantity = savedCommand.quantity; + locale = savedCommand.locale; + isItemName = true; + this.savedCommand.delete(sessionId); + } + else + { + // A new give request was entered, we need to ignore the old saved command + if (this.savedCommand.has(sessionId)) + { + this.savedCommand.delete(sessionId); + } + isItemName = result[5] !== undefined; + item = result[5] ? result[5] : result[2]; + quantity = +result[6]; + if (quantity <= 0) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + `Invalid quantity! Must be 1 or higher. Use \"help\" for more information.`, + ); + return request.dialogId; + } + + if (isItemName) + { + locale = result[4] ? result[4] : this.localeService.getDesiredGameLocale(); + if (!this.localeService.getServerSupportedLocales().includes(locale)) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + `Unknown locale "${locale}". Use \"help\" for more information.`, + ); + return request.dialogId; + } + + const localizedGlobal = this.databaseServer.getTables().locales.global[locale]; + + const closestItemsMatchedByName = closestMatch( + item.toLowerCase(), + this.itemHelper.getItems().filter((i) => i._type !== "Node").filter((i) => + !this.itemFilterService.isItemBlacklisted(i._id) + ).map((i) => localizedGlobal[`${i?._id} Name`]?.toLowerCase()).filter((i) => i !== undefined), + true, + ) as string[]; + + if (closestItemsMatchedByName === undefined || closestItemsMatchedByName.length === 0) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "That item could not be found. Please refine your request and try again.", + ); + return request.dialogId; + } + + if (closestItemsMatchedByName.length > 1) + { + let i = 1; + const slicedItems = closestItemsMatchedByName.slice(0, 10); + // max 10 item names and map them + const itemList = slicedItems.map((itemName) => `${i++}. ${itemName}`).join("\n"); + this.savedCommand.set(sessionId, new SavedCommand(quantity, slicedItems, locale)); + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + `Could not find exact match. Closest matches are:\n\n${itemList}\n\nUse "spt give [number]" to select one.`, + ); + return request.dialogId; + } + + const dist = distance(item, closestItemsMatchedByName[0]); + if (dist > GiveSptCommand.maxAllowedDistance) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + `Found a possible match for "${item}" but uncertain. Match: "${ + closestItemsMatchedByName[0] + }". Please refine your request and try again.`, + ); + return request.dialogId; + } + // Only one available so we get that entry and use it + item = closestItemsMatchedByName[0]; + } + } + + // If item is an item name, we need to search using that item name and the locale which one we want otherwise + // item is just the tplId. + const tplId = isItemName + ? this.itemHelper.getItems().filter((i) => !this.itemFilterService.isItemBlacklisted(i._id)).find((i) => + this.databaseServer.getTables().locales.global[locale][`${i?._id} Name`]?.toLowerCase() === item + )._id + : item; + + const checkedItem = this.itemHelper.getItem(tplId); + if (!checkedItem[0]) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "That item could not be found. Please refine your request and try again.", + ); + return request.dialogId; + } + + const itemsToSend: Item[] = []; + if ( + this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.WEAPON) + || this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.ARMOR) + || this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.VEST) + ) + { + const preset = this.presetHelper.getDefaultPreset(checkedItem[1]._id); + if (!preset) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "That weapon template ID could not be found. Please refine your request and try again.", + ); + return request.dialogId; + } + for (let i = 0; i < quantity; i++) + { + let items = this.jsonUtil.clone(preset._items); + items = this.itemHelper.replaceIDs(items); + itemsToSend.push(...items); + } + } + else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX)) + { + for (let i = 0; i < quantity; i++) + { + const ammoBoxArray: Item[] = []; + ammoBoxArray.push({ _id: this.hashUtil.generate(), _tpl: checkedItem[1]._id }); + // DO NOT generate the ammo box cartridges, the mail service does it for us! :) + // this.itemHelper.addCartridgesToAmmoBox(ammoBoxArray, checkedItem[1]); + itemsToSend.push(...ammoBoxArray); + } + } + else + { + if (checkedItem[1]._props.StackMaxSize === 1) + { + for (let i = 0; i < quantity; i++) + { + itemsToSend.push({ + _id: this.hashUtil.generate(), + _tpl: checkedItem[1]._id, + upd: this.itemHelper.generateUpdForItem(checkedItem[1]), + }); + } + } + else + { + const item: Item = { + _id: this.hashUtil.generate(), + _tpl: checkedItem[1]._id, + upd: this.itemHelper.generateUpdForItem(checkedItem[1]), + }; + item.upd.StackObjectsCount = quantity; + try + { + itemsToSend.push(...this.itemHelper.splitStack(item)); + } + catch + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Too many items requested. Please lower the amount and try again.", + ); + return request.dialogId; + } + } + } + + // Flag the items as FiR + this.itemHelper.setFoundInRaid(itemsToSend); + + this.mailSendService.sendSystemMessageToPlayer(sessionId, "SPT GIVE", itemsToSend); + return request.dialogId; + } +} diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts new file mode 100644 index 00000000..c51412a4 --- /dev/null +++ b/project/src/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand.ts @@ -0,0 +1,6 @@ +export class SavedCommand +{ + public constructor(public quantity: number, public potentialItemNames: string[], public locale: string) + { + } +} diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/GiveSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/GiveSptCommand.ts deleted file mode 100644 index 644c1835..00000000 --- a/project/src/helpers/Dialogue/Commando/SptCommands/GiveSptCommand.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand"; -import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; -import { PresetHelper } from "@spt-aki/helpers/PresetHelper"; -import { Item } from "@spt-aki/models/eft/common/tables/IItem"; -import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; -import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; -import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; -import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; -import { MailSendService } from "@spt-aki/services/MailSendService"; -import { HashUtil } from "@spt-aki/utils/HashUtil"; -import { JsonUtil } from "@spt-aki/utils/JsonUtil"; -import { inject, injectable } from "tsyringe"; - -@injectable() -export class GiveSptCommand implements ISptCommand -{ - public constructor( - @inject("WinstonLogger") protected logger: ILogger, - @inject("ItemHelper") protected itemHelper: ItemHelper, - @inject("HashUtil") protected hashUtil: HashUtil, - @inject("JsonUtil") protected jsonUtil: JsonUtil, - @inject("PresetHelper") protected presetHelper: PresetHelper, - @inject("MailSendService") protected mailSendService: MailSendService, - ) - { - } - - public getCommand(): string - { - return "give"; - } - - public getCommandHelp(): string - { - return "Usage: spt give tplId quantity"; - } - - public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string - { - const giveCommand = request.text.split(" "); - if (giveCommand[1] !== "give") - { - this.logger.error("Invalid action received for give command!"); - return request.dialogId; - } - - if (!giveCommand[2]) - { - this.mailSendService.sendUserMessageToPlayer( - sessionId, - commandHandler, - "Invalid use of give command! Template ID is missing. Use \"Help\" for more info", - ); - return request.dialogId; - } - const tplId = giveCommand[2]; - - if (!giveCommand[3]) - { - this.mailSendService.sendUserMessageToPlayer( - sessionId, - commandHandler, - "Invalid use of give command! Quantity is missing. Use \"Help\" for more info", - ); - return request.dialogId; - } - const quantity = giveCommand[3]; - - if (Number.isNaN(+quantity)) - { - this.mailSendService.sendUserMessageToPlayer( - sessionId, - commandHandler, - "Invalid use of give command! Quantity is not a valid integer. Use \"Help\" for more info", - ); - return request.dialogId; - } - - const checkedItem = this.itemHelper.getItem(tplId); - if (!checkedItem[0]) - { - this.mailSendService.sendUserMessageToPlayer( - sessionId, - commandHandler, - "Invalid template ID requested for give command. The item doesn't exist in the DB.", - ); - return request.dialogId; - } - - const itemsToSend: Item[] = []; - const preset = this.presetHelper.getDefaultPreset(checkedItem[1]._id); - if (preset) - { - for (let i = 0; i < +quantity; i++) - { - // Make sure IDs are unique before adding to array - prevent collisions - const presetToSend = this.itemHelper.replaceIDs(preset._items); - itemsToSend.push(...presetToSend); - } - } - else if (this.itemHelper.isOfBaseclass(checkedItem[1]._id, BaseClasses.AMMO_BOX)) - { - for (let i = 0; i < +quantity; i++) - { - const ammoBoxArray: Item[] = []; - ammoBoxArray.push({ _id: this.hashUtil.generate(), _tpl: checkedItem[1]._id }); - this.itemHelper.addCartridgesToAmmoBox(ammoBoxArray, checkedItem[1]); - itemsToSend.push(...ammoBoxArray); - } - } - else - { - const item: Item = { - _id: this.hashUtil.generate(), - _tpl: checkedItem[1]._id, - upd: { StackObjectsCount: +quantity, SpawnedInSession: true }, - }; - itemsToSend.push(...this.itemHelper.splitStack(item)); - } - - // Flag the items as FiR - this.itemHelper.setFoundInRaid(itemsToSend); - - this.mailSendService.sendSystemMessageToPlayer(sessionId, "Give command!", itemsToSend); - return request.dialogId; - } -} diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts new file mode 100644 index 00000000..025a205c --- /dev/null +++ b/project/src/helpers/Dialogue/Commando/SptCommands/ProfileCommand/ProfileSptCommand.ts @@ -0,0 +1,163 @@ +import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; +import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand"; +import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; +import { PresetHelper } from "@spt-aki/helpers/PresetHelper"; +import { ProfileHelper } from "@spt-aki/helpers/ProfileHelper"; +import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; +import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; +import { SkillTypes } from "@spt-aki/models/enums/SkillTypes"; +import { IProfileChangeEvent, ProfileChangeEventType } from "@spt-aki/models/spt/dialog/ISendMessageDetails"; +import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; +import { LocaleService } from "@spt-aki/services/LocaleService"; +import { MailSendService } from "@spt-aki/services/MailSendService"; +import { HashUtil } from "@spt-aki/utils/HashUtil"; +import { JsonUtil } from "@spt-aki/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; + +@injectable() +export class ProfileSptCommand implements ISptCommand +{ + /** + * Regex to account for all these cases: + * spt profile level 20 + * spt profile skill metabolism 10 + */ + private static commandRegex = + /^spt profile (?level|skill)((?<=.*skill) (?[\w]+)){0,1} (?(?!0+)[0-9]+)$/; + + protected savedCommand: SavedCommand; + + public constructor( + @inject("WinstonLogger") protected logger: ILogger, + @inject("ItemHelper") protected itemHelper: ItemHelper, + @inject("HashUtil") protected hashUtil: HashUtil, + @inject("JsonUtil") protected jsonUtil: JsonUtil, + @inject("PresetHelper") protected presetHelper: PresetHelper, + @inject("MailSendService") protected mailSendService: MailSendService, + @inject("LocaleService") protected localeService: LocaleService, + @inject("DatabaseServer") protected databaseServer: DatabaseServer, + @inject("ProfileHelper") protected profileHelper: ProfileHelper, + ) + { + } + + public getCommand(): string + { + return "profile"; + } + + public getCommandHelp(): string + { + return "spt profile\n========\nSets the profile level or skill to the desired level through the message system.\n\n\tspt profile level [desired level]\n\t\tEx: spt profile level 20\n\n\tspt profile skill [skill name] [quantity]\n\t\tEx: spt profile skill metabolism 51"; + } + + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string + { + if (!ProfileSptCommand.commandRegex.test(request.text)) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of trader command. Use \"help\" for more information.", + ); + return request.dialogId; + } + + const result = ProfileSptCommand.commandRegex.exec(request.text); + + const command: string = result.groups.command; + const skill: string = result.groups.skill; + const quantity: number = +result.groups.quantity; + + let event: IProfileChangeEvent; + switch (command) + { + case "level": + if (quantity < 1 || quantity > this.profileHelper.getMaxLevel()) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of profile command, the level was outside bounds: 1 to 70. Use \"help\" for more information.", + ); + return request.dialogId; + } + event = this.handleLevelCommand(quantity); + break; + case "skill": + { + const enumSkill = Object.values(SkillTypes).find((t) => + t.toLocaleLowerCase() === skill.toLocaleLowerCase() + ); + + if (enumSkill === undefined) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of profile command, the skill was not found. Use \"help\" for more information.", + ); + return request.dialogId; + } + + if (quantity < 0 || quantity > 51) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of profile command, the skill level was outside bounds: 1 to 51. Use \"help\" for more information.", + ); + return request.dialogId; + } + event = this.handleSkillCommand(enumSkill, quantity); + break; + } + default: + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + `If you are reading this, this is bad. Please report this to SPT staff with a screenshot. Command ${command}.`, + ); + return request.dialogId; + } + + this.mailSendService.sendSystemMessageToPlayer( + sessionId, + "A single ruble is being attached, required by BSG logic.", + [{ + _id: this.hashUtil.generate(), + _tpl: "5449016a4bdc2d6f028b456f", + upd: { StackObjectsCount: 1 }, + parentId: this.hashUtil.generate(), + slotId: "main", + }], + undefined, + [event], + ); + return request.dialogId; + } + + protected handleSkillCommand(skill: string, level: number): IProfileChangeEvent + { + const event: IProfileChangeEvent = { + _id: this.hashUtil.generate(), + Type: ProfileChangeEventType.SKILL_POINTS, + value: level * 100, + entity: skill, + }; + return event; + } + + protected handleLevelCommand(level: number): IProfileChangeEvent + { + const exp = this.profileHelper.getExperience(level); + const event: IProfileChangeEvent = { + _id: this.hashUtil.generate(), + Type: ProfileChangeEventType.PROFILE_LEVEL, + value: exp, + entity: null, + }; + return event; + } +} diff --git a/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts b/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts new file mode 100644 index 00000000..feb3c0b2 --- /dev/null +++ b/project/src/helpers/Dialogue/Commando/SptCommands/TraderCommand/TraderSptCommand.ts @@ -0,0 +1,114 @@ +import { SavedCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/GiveCommand/SavedCommand"; +import { ISptCommand } from "@spt-aki/helpers/Dialogue/Commando/SptCommands/ISptCommand"; +import { ItemHelper } from "@spt-aki/helpers/ItemHelper"; +import { PresetHelper } from "@spt-aki/helpers/PresetHelper"; +import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; +import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; +import { IProfileChangeEvent, ProfileChangeEventType } from "@spt-aki/models/spt/dialog/ISendMessageDetails"; +import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; +import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; +import { LocaleService } from "@spt-aki/services/LocaleService"; +import { MailSendService } from "@spt-aki/services/MailSendService"; +import { HashUtil } from "@spt-aki/utils/HashUtil"; +import { JsonUtil } from "@spt-aki/utils/JsonUtil"; +import { inject, injectable } from "tsyringe"; + +@injectable() +export class TraderSptCommand implements ISptCommand +{ + /** + * Regex to account for all these cases: + * spt trader prapor rep 100 + * spt trader mechanic spend 1000000 + */ + private static commandRegex = /^spt trader (?[\w]+) (?rep|spend) (?(?!0+)[0-9]+)$/; + + protected savedCommand: SavedCommand; + + public constructor( + @inject("WinstonLogger") protected logger: ILogger, + @inject("ItemHelper") protected itemHelper: ItemHelper, + @inject("HashUtil") protected hashUtil: HashUtil, + @inject("JsonUtil") protected jsonUtil: JsonUtil, + @inject("PresetHelper") protected presetHelper: PresetHelper, + @inject("MailSendService") protected mailSendService: MailSendService, + @inject("LocaleService") protected localeService: LocaleService, + @inject("DatabaseServer") protected databaseServer: DatabaseServer, + ) + { + } + + public getCommand(): string + { + return "trader"; + } + + public getCommandHelp(): string + { + return "spt trader\n========\nSets the reputation or money spent to the input quantity through the message system.\n\n\tspt trader [trader] rep [quantity]\n\t\tEx: spt trader prapor rep 2\n\n\tspt trader [trader] spend [quantity]\n\t\tEx: spt trader therapist spend 1000000"; + } + + public performAction(commandHandler: IUserDialogInfo, sessionId: string, request: ISendMessageRequest): string + { + if (!TraderSptCommand.commandRegex.test(request.text)) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of trader command. Use \"help\" for more information.", + ); + return request.dialogId; + } + + const result = TraderSptCommand.commandRegex.exec(request.text); + + const trader: string = result.groups.trader; + const command: string = result.groups.command; + const quantity: number = +result.groups.quantity; + + const dbTrader = Object.values(this.databaseServer.getTables().traders).find((t) => + t.base.nickname.toLocaleLowerCase() === trader.toLocaleLowerCase() + ); + if (dbTrader === undefined) + { + this.mailSendService.sendUserMessageToPlayer( + sessionId, + commandHandler, + "Invalid use of trader command, the trader was not found. Use \"help\" for more information.", + ); + return request.dialogId; + } + let profileChangeEventType: ProfileChangeEventType; + switch (command) + { + case "rep": + profileChangeEventType = ProfileChangeEventType.TRADER_STANDING; + break; + case "spend": + profileChangeEventType = ProfileChangeEventType.TRADER_SALES_SUM; + break; + } + + const event: IProfileChangeEvent = { + _id: this.hashUtil.generate(), + Type: profileChangeEventType, + value: quantity, + entity: dbTrader.base._id, + }; + + this.mailSendService.sendSystemMessageToPlayer( + sessionId, + "A single ruble is being attached, required by BSG logic.", + [{ + _id: this.hashUtil.generate(), + _tpl: "5449016a4bdc2d6f028b456f", + upd: { StackObjectsCount: 1 }, + parentId: this.hashUtil.generate(), + slotId: "main", + }], + undefined, + [event], + ); + return request.dialogId; + } +} diff --git a/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts b/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts index c000d186..db8018dc 100644 --- a/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts +++ b/project/src/helpers/Dialogue/CommandoDialogueChatBot.ts @@ -1,33 +1,22 @@ import { inject, injectAll, injectable } from "tsyringe"; -import { ICommandoCommand } from "@spt-aki/helpers/Dialogue/Commando/ICommandoCommand"; -import { IDialogueChatBot } from "@spt-aki/helpers/Dialogue/IDialogueChatBot"; -import { ISendMessageRequest } from "@spt-aki/models/eft/dialog/ISendMessageRequest"; +import { AbstractDialogueChatBot } from "@spt-aki/helpers/Dialogue/AbstractDialogueChatBot"; +import { IChatCommand } from "@spt-aki/helpers/Dialogue/Commando/IChatCommand"; import { IUserDialogInfo } from "@spt-aki/models/eft/profile/IAkiProfile"; import { MemberCategory } from "@spt-aki/models/enums/MemberCategory"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { MailSendService } from "@spt-aki/services/MailSendService"; @injectable() -export class CommandoDialogueChatBot implements IDialogueChatBot +export class CommandoDialogueChatBot extends AbstractDialogueChatBot { public constructor( - @inject("WinstonLogger") protected logger: ILogger, - @inject("MailSendService") protected mailSendService: MailSendService, - @injectAll("CommandoCommand") protected commandoCommands: ICommandoCommand[], + @inject("WinstonLogger") logger: ILogger, + @inject("MailSendService") mailSendService: MailSendService, + @injectAll("CommandoCommand") chatCommands: IChatCommand[], ) { - } - - public registerCommandoCommand(commandoCommand: ICommandoCommand): void - { - if (this.commandoCommands.some((cc) => cc.getCommandPrefix() === commandoCommand.getCommandPrefix())) - { - throw new Error( - `The commando command ${commandoCommand.getCommandPrefix()} being registered already exists!`, - ); - } - this.commandoCommands.push(commandoCommand); + super(logger, mailSendService, chatCommands); } public getChatBot(): IUserDialogInfo @@ -39,37 +28,8 @@ export class CommandoDialogueChatBot implements IDialogueChatBot }; } - public handleMessage(sessionId: string, request: ISendMessageRequest): string + protected getUnrecognizedCommandMessage(): string { - if ((request.text ?? "").length === 0) - { - this.logger.error("Commando command came in as empty text! Invalid data!"); - return request.dialogId; - } - - const splitCommand = request.text.split(" "); - - const commandos = this.commandoCommands.filter((c) => c.getCommandPrefix() === splitCommand[0]); - if (commandos[0]?.getCommands().has(splitCommand[1])) - { - return commandos[0].handle(splitCommand[1], this.getChatBot(), sessionId, request); - } - - if (splitCommand[0].toLowerCase() === "help") - { - const helpMessage = this.commandoCommands.map((c) => - `Help for ${c.getCommandPrefix()}:\n${ - Array.from(c.getCommands()).map((command) => c.getCommandHelp(command)).join("\n") - }` - ).join("\n"); - this.mailSendService.sendUserMessageToPlayer(sessionId, this.getChatBot(), helpMessage); - return request.dialogId; - } - - this.mailSendService.sendUserMessageToPlayer( - sessionId, - this.getChatBot(), - `Im sorry soldier, I dont recognize the command you are trying to use! Type "help" to see available commands.`, - ); + return `I'm sorry soldier, I don't recognize the command you are trying to use! Type "help" to see available commands.`; } } diff --git a/project/src/helpers/HideoutHelper.ts b/project/src/helpers/HideoutHelper.ts index 7793db80..bbd98544 100644 --- a/project/src/helpers/HideoutHelper.ts +++ b/project/src/helpers/HideoutHelper.ts @@ -595,7 +595,7 @@ export class HideoutHelper * @param applyHideoutManagementBonus should the hideout mgmt bonus be appled to the calculation * @returns Items craft time with bonuses subtracted */ - protected getAdjustedCraftTimeWithSkills( + public getAdjustedCraftTimeWithSkills( pmcData: IPmcData, recipeId: string, applyHideoutManagementBonus = false, @@ -613,13 +613,19 @@ export class HideoutHelper return undefined; } - // Seconds to deduct from crafts total time - let timeReductionSeconds = this.getSkillProductionTimeReduction( - pmcData, - recipe.productionTime, - SkillTypes.CRAFTING, - globalSkillsDb.Crafting.ProductionTimeReductionPerLevel, - ); + let timeReductionSeconds = 0; + + // Bitcoin farm is excluded from crafting skill cooldown reduction + if (recipeId !== HideoutHelper.bitcoinFarm) + { + // Seconds to deduct from crafts total time + timeReductionSeconds += this.getSkillProductionTimeReduction( + pmcData, + recipe.productionTime, + SkillTypes.CRAFTING, + globalSkillsDb.Crafting.ProductionTimeReductionPerLevel, + ); + } // Some crafts take into account hideout management, e.g. fuel, water/air filters if (applyHideoutManagementBonus) diff --git a/project/src/helpers/HttpServerHelper.ts b/project/src/helpers/HttpServerHelper.ts index d647c047..e0f6cadc 100644 --- a/project/src/helpers/HttpServerHelper.ts +++ b/project/src/helpers/HttpServerHelper.ts @@ -32,12 +32,12 @@ export class HttpServerHelper } /** - * Combine ip and port into url + * Combine ip and port into address * @returns url */ public buildUrl(): string { - return `${this.httpConfig.ip}:${this.httpConfig.port}`; + return `${this.httpConfig.backendIp}:${this.httpConfig.backendPort}`; } /** diff --git a/project/src/helpers/ItemHelper.ts b/project/src/helpers/ItemHelper.ts index a5d16f6c..19f572dc 100644 --- a/project/src/helpers/ItemHelper.ts +++ b/project/src/helpers/ItemHelper.ts @@ -3,7 +3,7 @@ import { inject, injectable } from "tsyringe"; import { HandbookHelper } from "@spt-aki/helpers/HandbookHelper"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { InsuredItem } from "@spt-aki/models/eft/common/tables/IBotBase"; -import { Item, Location, Repairable } from "@spt-aki/models/eft/common/tables/IItem"; +import { Item, Location, Repairable, Upd } from "@spt-aki/models/eft/common/tables/IItem"; import { IStaticAmmoDetails } from "@spt-aki/models/eft/common/tables/ILootBase"; import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; @@ -14,6 +14,7 @@ import { ItemBaseClassService } from "@spt-aki/services/ItemBaseClassService"; import { ItemFilterService } from "@spt-aki/services/ItemFilterService"; import { LocaleService } from "@spt-aki/services/LocaleService"; import { LocalisationService } from "@spt-aki/services/LocalisationService"; +import { CompareUtil } from "@spt-aki/utils/CompareUtil"; import { HashUtil } from "@spt-aki/utils/HashUtil"; import { JsonUtil } from "@spt-aki/utils/JsonUtil"; import { MathUtil } from "@spt-aki/utils/MathUtil"; @@ -46,9 +47,137 @@ export class ItemHelper @inject("ItemFilterService") protected itemFilterService: ItemFilterService, @inject("LocalisationService") protected localisationService: LocalisationService, @inject("LocaleService") protected localeService: LocaleService, + @inject("CompareUtil") protected compareUtil: CompareUtil, ) {} + /** + * This method will compare two items (with all its children) and see if the are equivalent. + * This method will NOT compare IDs on the items + * @param item1 first item with all its children to compare + * @param item2 second item with all its children to compare + * @param compareUpdProperties Upd properties to compare between the items + * @returns true if they are the same, false if they arent + */ + public isSameItems(item1: Item[], item2: Item[], compareUpdProperties?: Set): boolean + { + if (item1.length !== item2.length) + { + return false; + } + for (const itemOf1 of item1) + { + const itemOf2 = item2.find((i2) => i2._tpl === itemOf1._tpl); + if (itemOf2 === undefined) + { + return false; + } + if (!this.isSameItem(itemOf1, itemOf2, compareUpdProperties)) + { + return false; + } + } + return true; + } + + /** + * This method will compare two items and see if the are equivalent. + * This method will NOT compare IDs on the items + * @param item1 first item to compare + * @param item2 second item to compare + * @param compareUpdProperties Upd properties to compare between the items + * @returns true if they are the same, false if they arent + */ + public isSameItem(item1: Item, item2: Item, compareUpdProperties?: Set): boolean + { + if (item1._tpl !== item2._tpl) + { + return false; + } + + if (compareUpdProperties) + { + return Array.from(compareUpdProperties.values()).every((p) => + this.compareUtil.recursiveCompare(item1.upd?.[p], item2.upd?.[p]) + ); + } + + return this.compareUtil.recursiveCompare(item1.upd, item2.upd); + } + + /** + * Helper method to generate a Upd based on a template + * @param itemTemplate the item template to generate a Upd for + * @returns A Upd with all the default properties set + */ + public generateUpdForItem(itemTemplate: ITemplateItem): Upd + { + const itemProperties: Upd = {}; + + // armors, etc + if (itemTemplate._props.MaxDurability) + { + itemProperties.Repairable = { + Durability: itemTemplate._props.MaxDurability, + MaxDurability: itemTemplate._props.MaxDurability, + }; + } + + if (itemTemplate._props.HasHinge) + { + itemProperties.Togglable = { On: true }; + } + + if (itemTemplate._props.Foldable) + { + itemProperties.Foldable = { Folded: false }; + } + + if (itemTemplate._props.weapFireType?.length) + { + if (itemTemplate._props.weapFireType.includes("fullauto")) + { + itemProperties.FireMode = { FireMode: "fullauto" }; + } + else + { + itemProperties.FireMode = { FireMode: this.randomUtil.getArrayValue(itemTemplate._props.weapFireType) }; + } + } + + if (itemTemplate._props.MaxHpResource) + { + itemProperties.MedKit = { HpResource: itemTemplate._props.MaxHpResource }; + } + + if (itemTemplate._props.MaxResource && itemTemplate._props.foodUseTime) + { + itemProperties.FoodDrink = { HpPercent: itemTemplate._props.MaxResource }; + } + + if (itemTemplate._parent === BaseClasses.FLASHLIGHT) + { + itemProperties.Light = { IsActive: false, SelectedMode: 0 }; + } + else if (itemTemplate._parent === BaseClasses.TACTICAL_COMBO) + { + itemProperties.Light = { IsActive: false, SelectedMode: 0 }; + } + + if (itemTemplate._parent === BaseClasses.NIGHTVISION) + { + itemProperties.Togglable = { On: false }; + } + + // Togglable face shield + if (itemTemplate._props.HasHinge && itemTemplate._props.FaceShieldComponent) + { + itemProperties.Togglable = { On: false }; + } + + return itemProperties; + } + /** * Checks if an id is a valid item. Valid meaning that it's an item that be stored in stash * @param {string} tpl the template id / tpl @@ -429,19 +558,12 @@ export class ItemHelper if (repairable.Durability > repairable.MaxDurability) { this.logger.warning( - `Max durability: ${repairable.MaxDurability} for item id: ${item._id} was below Durability: ${repairable.Durability}, adjusting values to match`, + `Max durability: ${repairable.MaxDurability} for item id: ${item._id} was below durability: ${repairable.Durability}, adjusting values to match`, ); repairable.MaxDurability = repairable.Durability; } - // Armor - if (itemDetails._props.armorClass) - { - return repairable.MaxDurability / itemDetails._props.MaxDurability; - } - - // Weapon - // Get max dura from props, if it isnt there use repairable max dura value + // Attempt to get the max durability from _props. If not available, use Repairable max durability value instead. const maxDurability = (itemDetails._props.MaxDurability) ? itemDetails._props.MaxDurability : repairable.MaxDurability; @@ -1097,6 +1219,12 @@ export class ItemHelper const cartridgeDetails = this.getItem(cartridgeTpl); const cartridgeMaxStackSize = cartridgeDetails[1]._props.StackMaxSize; + // Exit if ammo already exists in box + if (ammoBox.find((item) => item._tpl === cartridgeTpl)) + { + return; + } + // Add new stack-size-correct items to ammo box let currentStoredCartridgeCount = 0; const maxPerStack = Math.min(ammoBoxMaxCartridgeCount, cartridgeMaxStackSize); @@ -1205,6 +1333,7 @@ export class ItemHelper const cartridgeTpl = this.drawAmmoTpl( chosenCaliber, staticAmmoDist, + weapon?._props.defAmmo, weapon?._props?.Chambers[0]?._props?.filters[0]?.Filter, ); this.fillMagazineWithCartridge(magazine, magTemplate, cartridgeTpl, minSizePercent); @@ -1313,12 +1442,14 @@ export class ItemHelper * Chose a randomly weighted cartridge that fits * @param caliber Desired caliber * @param staticAmmoDist Cartridges and thier weights + * @param fallbackCartridgeTpl If a cartridge cannot be found in the above staticAmmoDist param, use this instead * @param cartridgeWhitelist OPTIONAL whitelist for cartridges * @returns Tpl of cartridge */ protected drawAmmoTpl( caliber: string, staticAmmoDist: Record, + fallbackCartridgeTpl: string, cartridgeWhitelist: string[] = null, ): string { @@ -1326,14 +1457,20 @@ export class ItemHelper const ammos = staticAmmoDist[caliber]; if (!ammos) { - this.logger.error(`Missing caliber data for: ${caliber}`); + this.logger.error( + `Unable to pick a cartridge for caliber: ${caliber} as staticAmmoDist has no data. using fallback value of ${fallbackCartridgeTpl}`, + ); + + return fallbackCartridgeTpl; } if (!Array.isArray(ammos)) { this.logger.error( - `Unable to pick a cartridge for caliber ${caliber}, chosen staticAmmoDist data is not an array: ${ammos}`, + `Unable to pick a cartridge for caliber: ${caliber}, the chosen staticAmmoDist data is not an array. Using fallback value of ${fallbackCartridgeTpl}`, ); + + return fallbackCartridgeTpl; } for (const icd of ammos) @@ -1470,7 +1607,6 @@ export class ItemHelper const modItemDbDetails = this.getItem(modItemToAdd._tpl)[1]; // Include conflicting items of newly added mod in pool to be used for next mod choice - // biome-ignore lint/complexity/noForEach: modItemDbDetails._props.ConflictingItems.forEach(incompatibleModTpls.add, incompatibleModTpls); } @@ -1479,7 +1615,7 @@ export class ItemHelper /** * Get a compatible tpl from the array provided where it is not found in the provided incompatible mod tpls parameter - * @param possibleTpls Tpls to randomply choose from + * @param possibleTpls Tpls to randomly choose from * @param incompatibleModTpls Incompatible tpls to not allow * @returns Chosen tpl or null */ @@ -1666,7 +1802,7 @@ export class ItemHelper if (warningMessageWhenMissing) { - this.logger.warning(warningMessageWhenMissing); + this.logger.debug(warningMessageWhenMissing); } return true; diff --git a/project/src/helpers/PresetHelper.ts b/project/src/helpers/PresetHelper.ts index b7fc1eb4..d7149fc1 100644 --- a/project/src/helpers/PresetHelper.ts +++ b/project/src/helpers/PresetHelper.ts @@ -85,6 +85,17 @@ export class PresetHelper return id in this.databaseServer.getTables().globals.ItemPresets; } + /** + * Checks to see if the preset is of the given base class. + * @param id The id of the preset + * @param baseClass The BaseClasses enum to check against + * @returns True if the preset is of the given base class, false otherwise + */ + public isPresetBaseClass(id: string, baseClass: BaseClasses): boolean + { + return this.isPreset(id) && this.itemHelper.isOfBaseclass(this.getPreset(id)._encyclopedia, baseClass); + } + public hasPreset(templateId: string): boolean { return templateId in this.lookup; diff --git a/project/src/helpers/QuestHelper.ts b/project/src/helpers/QuestHelper.ts index aaeb5efe..2291f8c7 100644 --- a/project/src/helpers/QuestHelper.ts +++ b/project/src/helpers/QuestHelper.ts @@ -692,12 +692,12 @@ export class QuestHelper */ public getQuestWithOnlyLevelRequirementStartCondition(quest: IQuest): IQuest { - quest = this.jsonUtil.clone(quest); - quest.conditions.AvailableForStart = quest.conditions.AvailableForStart.filter((q) => + const updatedQuest = this.jsonUtil.clone(quest); + updatedQuest.conditions.AvailableForStart = updatedQuest.conditions.AvailableForStart.filter((q) => q.conditionType === "Level" ); - return quest; + return updatedQuest; } /** @@ -714,14 +714,22 @@ export class QuestHelper output: IItemEventRouterResponse = null, ): void { + let updatedOutput = output; + // Prepare response to send back to client - if (!output) + if (!updatedOutput) { - output = this.eventOutputHolder.getOutput(sessionID); + updatedOutput = this.eventOutputHolder.getOutput(sessionID); } this.updateQuestState(pmcData, QuestStatus.Fail, failRequest.qid); - const questRewards = this.applyQuestReward(pmcData, failRequest.qid, QuestStatus.Fail, sessionID, output); + const questRewards = this.applyQuestReward( + pmcData, + failRequest.qid, + QuestStatus.Fail, + sessionID, + updatedOutput, + ); // Create a dialog message for completing the quest. const quest = this.getQuestFromDb(failRequest.qid, pmcData); @@ -731,19 +739,23 @@ export class QuestHelper repeatableType.activeQuests ).find((activeQuest) => activeQuest._id === failRequest.qid); - if (matchingRepeatableQuest || quest) + // Quest found and no repeatable found + if (quest && !matchingRepeatableQuest) { - this.mailSendService.sendLocalisedNpcMessageToPlayer( - sessionID, - this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be null when repeatable quest has been moved to inactiveQuests - MessageType.QUEST_FAIL, - quest.failMessageText, - questRewards, - this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime), - ); + if (quest.failMessageText.trim().length > 0) + { + this.mailSendService.sendLocalisedNpcMessageToPlayer( + sessionID, + this.traderHelper.getTraderById(quest?.traderId ?? matchingRepeatableQuest?.traderId), // Can be null when repeatable quest has been moved to inactiveQuests + MessageType.QUEST_FAIL, + quest.failMessageText, + questRewards, + this.timeUtil.getHoursAsSeconds(this.questConfig.redeemTime), + ); + } } - output.profileChanges[sessionID].quests.push(...this.failedUnlocked(failRequest.qid, sessionID)); + updatedOutput.profileChanges[sessionID].quests.push(...this.failedUnlocked(failRequest.qid, sessionID)); } /** @@ -938,7 +950,7 @@ export class QuestHelper // Handled elsewhere, TODO: find and say here break; case QuestRewardType.STASH_ROWS: - this.logger.debug("Not implemented stash rows reward yet"); + this.profileHelper.addStashRowsBonusToProfile(sessionId, Number.parseInt(reward.value)); // add specified stash rows from quest reward - requires client restart break; case QuestRewardType.PRODUCTIONS_SCHEME: this.findAndAddHideoutProductionIdToProfile( diff --git a/project/src/helpers/TradeHelper.ts b/project/src/helpers/TradeHelper.ts index 59d9bd1c..19ad09ce 100644 --- a/project/src/helpers/TradeHelper.ts +++ b/project/src/helpers/TradeHelper.ts @@ -72,7 +72,7 @@ export class TradeHelper ): void { let offerItems: Item[] = []; - let buyCallback: { (buyCount: number); }; + let buyCallback: (buyCount: number) => void; if (buyRequestData.tid.toLocaleLowerCase() === "ragfair") { buyCallback = (buyCount: number) => @@ -158,6 +158,14 @@ export class TradeHelper ); } + // Check if trader has enough stock + if (itemPurchased.upd.StackObjectsCount < buyCount) + { + throw new Error( + `Unable to purchase ${buyCount} items, this would exceed the remaining stock left ${itemPurchased.upd.StackObjectsCount} from the traders assort: ${buyRequestData.tid} this refresh`, + ); + } + // Decrement trader item count itemPurchased.upd.StackObjectsCount -= buyCount; @@ -266,6 +274,14 @@ export class TradeHelper this.logger.debug(`Selling: id: ${matchingItemInInventory._id} tpl: ${matchingItemInInventory._tpl}`); + if (sellRequest.tid === Traders.FENCE) + { + this.fenceService.addItemsToFenceAssort( + profileWithItemsToSell.Inventory.items, + matchingItemInInventory, + ); + } + // Also removes children this.inventoryHelper.removeItem(profileWithItemsToSell, itemToBeRemoved.id, sessionID, output); } diff --git a/project/src/helpers/TraderHelper.ts b/project/src/helpers/TraderHelper.ts index 075e57fc..64d2f17d 100644 --- a/project/src/helpers/TraderHelper.ts +++ b/project/src/helpers/TraderHelper.ts @@ -272,7 +272,7 @@ export class TraderHelper public getTraderUpdateSeconds(traderId: string): number { const traderDetails = this.traderConfig.updateTime.find((x) => x.traderId === traderId); - if (!traderDetails) + if (!traderDetails || traderDetails.seconds.min === undefined || traderDetails.seconds.max === undefined) { this.logger.warning( this.localisationService.getText("trader-missing_trader_details_using_default_refresh_time", { diff --git a/project/src/ide/BleedingEdgeEntry.ts b/project/src/ide/BleedingEdgeEntry.ts index c177c186..94cdafdd 100644 --- a/project/src/ide/BleedingEdgeEntry.ts +++ b/project/src/ide/BleedingEdgeEntry.ts @@ -2,6 +2,7 @@ import "reflect-metadata"; import "source-map-support/register"; import { Program } from "@spt-aki/Program"; +import * as buildInfo from "./build.json"; globalThis.G_DEBUG_CONFIGURATION = true; globalThis.G_RELEASE_CONFIGURATION = true; @@ -10,5 +11,9 @@ globalThis.G_MODS_TRANSPILE_TS = true; globalThis.G_LOG_REQUESTS = true; globalThis.G_WATERMARK_ENABLED = true; +globalThis.G_AKIVERSION = buildInfo.akiVersion; +globalThis.G_COMMIT = buildInfo.commit; +globalThis.G_BUILDTIME = buildInfo.buildTime; + const program = new Program(); program.start(); diff --git a/project/src/ide/BleedingEdgeModsEntry.ts b/project/src/ide/BleedingEdgeModsEntry.ts index b90cf77f..badeb416 100644 --- a/project/src/ide/BleedingEdgeModsEntry.ts +++ b/project/src/ide/BleedingEdgeModsEntry.ts @@ -2,6 +2,7 @@ import "reflect-metadata"; import "source-map-support/register"; import { Program } from "@spt-aki/Program"; +import * as buildInfo from "./build.json"; globalThis.G_DEBUG_CONFIGURATION = true; globalThis.G_RELEASE_CONFIGURATION = true; @@ -10,5 +11,9 @@ globalThis.G_MODS_TRANSPILE_TS = true; globalThis.G_LOG_REQUESTS = true; globalThis.G_WATERMARK_ENABLED = true; +globalThis.G_AKIVERSION = buildInfo.akiVersion; +globalThis.G_COMMIT = buildInfo.commit; +globalThis.G_BUILDTIME = buildInfo.buildTime; + const program = new Program(); program.start(); diff --git a/project/src/ide/DebugEntry.ts b/project/src/ide/DebugEntry.ts index 33a37e75..5c4377ea 100644 --- a/project/src/ide/DebugEntry.ts +++ b/project/src/ide/DebugEntry.ts @@ -2,6 +2,7 @@ import "reflect-metadata"; import "source-map-support/register"; import { Program } from "@spt-aki/Program"; +import * as buildInfo from "./build.json"; globalThis.G_DEBUG_CONFIGURATION = true; globalThis.G_RELEASE_CONFIGURATION = true; @@ -10,5 +11,9 @@ globalThis.G_MODS_TRANSPILE_TS = true; globalThis.G_LOG_REQUESTS = true; globalThis.G_WATERMARK_ENABLED = false; +globalThis.G_AKIVERSION = buildInfo.akiVersion; +globalThis.G_COMMIT = buildInfo.commit; +globalThis.G_BUILDTIME = buildInfo.buildTime; + const program = new Program(); program.start(); diff --git a/project/src/ide/ReleaseEntry.ts b/project/src/ide/ReleaseEntry.ts index e45141dc..230e7d32 100644 --- a/project/src/ide/ReleaseEntry.ts +++ b/project/src/ide/ReleaseEntry.ts @@ -2,6 +2,7 @@ import "reflect-metadata"; import "source-map-support/register"; import { Program } from "@spt-aki/Program"; +import * as buildInfo from "./build.json"; globalThis.G_DEBUG_CONFIGURATION = false; globalThis.G_RELEASE_CONFIGURATION = true; @@ -10,5 +11,9 @@ globalThis.G_MODS_TRANSPILE_TS = true; globalThis.G_LOG_REQUESTS = false; globalThis.G_WATERMARK_ENABLED = false; +globalThis.G_AKIVERSION = buildInfo.akiVersion; +globalThis.G_COMMIT = buildInfo.commit; +globalThis.G_BUILDTIME = buildInfo.buildTime; + const program = new Program(); program.start(); diff --git a/project/src/ide/TestEntry.ts b/project/src/ide/TestEntry.ts index 9a1c53f4..dc4ca2a9 100644 --- a/project/src/ide/TestEntry.ts +++ b/project/src/ide/TestEntry.ts @@ -2,13 +2,21 @@ import "reflect-metadata"; import "source-map-support/register"; import { Program } from "@spt-aki/Program"; +// target run:profiler doesnt work with this here +// since this is the Test entry we can just remove +// it and leave those empty +// import * as buildInfo from "./build.json"; globalThis.G_DEBUG_CONFIGURATION = true; globalThis.G_RELEASE_CONFIGURATION = false; globalThis.G_MODS_ENABLED = true; globalThis.G_MODS_TRANSPILE_TS = false; globalThis.G_LOG_REQUESTS = true; -globalThis.G_WATERMARK_ENABLED = true; +globalThis.G_WATERMARK_ENABLED = false; + +globalThis.G_AKIVERSION = ""; +globalThis.G_COMMIT = ""; +globalThis.G_BUILDTIME = ""; const program = new Program(); program.start(); diff --git a/project/src/ide/build.json b/project/src/ide/build.json new file mode 100644 index 00000000..999634cd --- /dev/null +++ b/project/src/ide/build.json @@ -0,0 +1,5 @@ +{ + "akiVersion": "", + "commit": "", + "buildTime": 0 +} diff --git a/project/src/loaders/PreAkiModLoader.ts b/project/src/loaders/PreAkiModLoader.ts index a47a6eab..6d6f56d8 100644 --- a/project/src/loaders/PreAkiModLoader.ts +++ b/project/src/loaders/PreAkiModLoader.ts @@ -329,7 +329,7 @@ export class PreAkiModLoader implements IModLoader */ protected isModCombatibleWithAki(mod: IPackageJsonData): boolean { - const akiVersion = this.akiConfig.akiVersion; + const akiVersion = globalThis.G_AKIVERSION || this.akiConfig.akiVersion; const modName = `${mod.author}-${mod.name}`; // Error and prevent loading If no akiVersion property exists @@ -348,12 +348,12 @@ export class PreAkiModLoader implements IModLoader return false; } - // Error and prevent loading if semver is not satisfied + // Warning and allow loading if semver is not satisfied if (!semver.satisfies(akiVersion, mod.akiVersion)) { - this.logger.error(this.localisationService.getText("modloader-outdated_akiversion_field", modName)); + this.logger.warning(this.localisationService.getText("modloader-outdated_akiversion_field", modName)); - return false; + return true; } return true; @@ -617,7 +617,7 @@ export class PreAkiModLoader implements IModLoader this.logger.error( this.localisationService.getText("modloader-incompatible_mod_found", { author: mod.author, - modName: mod.name, + name: mod.name, incompatibleModName: incompatibleModName, }), ); diff --git a/project/src/models/eft/common/tables/IBotType.ts b/project/src/models/eft/common/tables/IBotType.ts index 0ca331da..d2f1bdec 100644 --- a/project/src/models/eft/common/tables/IBotType.ts +++ b/project/src/models/eft/common/tables/IBotType.ts @@ -130,6 +130,9 @@ export interface GenerationWeightingItems grenades: GenerationData; healing: GenerationData; drugs: GenerationData; + food: GenerationData; + drink: GenerationData; + currency: GenerationData; stims: GenerationData; backpackLoot: GenerationData; pocketLoot: GenerationData; diff --git a/project/src/models/eft/common/tables/IQuest.ts b/project/src/models/eft/common/tables/IQuest.ts index 65fabb1b..f544cb9f 100644 --- a/project/src/models/eft/common/tables/IQuest.ts +++ b/project/src/models/eft/common/tables/IQuest.ts @@ -169,6 +169,7 @@ export interface IQuestReward target?: string; items?: Item[]; loyaltyLevel?: number; + /** Hideout area id */ traderId?: string; unknown?: boolean; findInRaid?: boolean; diff --git a/project/src/models/eft/dialog/IAcceptFriendRequestData.ts b/project/src/models/eft/dialog/IAcceptFriendRequestData.ts index d12bd838..c55826ad 100644 --- a/project/src/models/eft/dialog/IAcceptFriendRequestData.ts +++ b/project/src/models/eft/dialog/IAcceptFriendRequestData.ts @@ -6,7 +6,11 @@ export interface ICancelFriendRequestData extends IBaseFriendRequest { } +export interface IDeclineFriendRequestData extends IBaseFriendRequest +{ +} + export interface IBaseFriendRequest { - request_id: string; + profileId: string; } diff --git a/project/src/models/eft/dialog/IFriendRequestSendResponse.ts b/project/src/models/eft/dialog/IFriendRequestSendResponse.ts index d83579bb..dee3ea8d 100644 --- a/project/src/models/eft/dialog/IFriendRequestSendResponse.ts +++ b/project/src/models/eft/dialog/IFriendRequestSendResponse.ts @@ -1,6 +1,6 @@ export interface IFriendRequestSendResponse { status: number; - requestid: string; + requestId: string; retryAfter: number; } diff --git a/project/src/models/eft/profile/IGetOtherProfileResponse.ts b/project/src/models/eft/profile/IGetOtherProfileResponse.ts index d6d6e826..50d7c975 100644 --- a/project/src/models/eft/profile/IGetOtherProfileResponse.ts +++ b/project/src/models/eft/profile/IGetOtherProfileResponse.ts @@ -1,5 +1,5 @@ import { OverallCounters, Skills } from "@spt-aki/models/eft/common/tables/IBotBase"; -import { Item } from "../common/tables/IItem"; +import { Item } from "@spt-aki/models/eft/common/tables/IItem"; export interface IGetOtherProfileResponse { diff --git a/project/src/models/eft/profile/ISearchFriendResponse.ts b/project/src/models/eft/profile/ISearchFriendResponse.ts index dfb1676a..a345c280 100644 --- a/project/src/models/eft/profile/ISearchFriendResponse.ts +++ b/project/src/models/eft/profile/ISearchFriendResponse.ts @@ -1,6 +1,7 @@ export interface ISearchFriendResponse { _id: string; + aid: number; Info: Info; } @@ -9,4 +10,5 @@ export interface Info Nickname: string; Side: string; Level: number; + MemberCategory: number; } diff --git a/project/src/models/enums/AmmoTypes.ts b/project/src/models/enums/AmmoTypes.ts index 8d24798c..3de62124 100644 --- a/project/src/models/enums/AmmoTypes.ts +++ b/project/src/models/enums/AmmoTypes.ts @@ -265,3 +265,9 @@ export enum Ammo26x75 WHITE_FLARE = "62389bc9423ed1685422dc57", YELLOW_FLARE = "62389be94d5d474bf712e709", } + +export enum Ammo68x51 +{ + SIG_FMJ = "6529302b8c26af6326029fb7", + SIG_HYBRID = "6529243824cbe3c74a05e5c1", +} diff --git a/project/src/models/enums/WeaponTypes.ts b/project/src/models/enums/WeaponTypes.ts index 873c26e9..e0ea6430 100644 --- a/project/src/models/enums/WeaponTypes.ts +++ b/project/src/models/enums/WeaponTypes.ts @@ -1,6 +1,7 @@ export enum Weapons127x55 { ASH_12 = "5cadfbf7ae92152ac412eeef", + RSH_12 = "633ec7c2a6918cb895019c6c", } export enum Weapons86x70 @@ -13,6 +14,8 @@ export enum Weapons9x39 { AS_VAL = "57c44b372459772d2b39b8ce", VSS_VINTOREZ = "57838ad32459774a17445cd2", + KBP_9A_91 = "644674a13d52156624001fbc", + VSK_94 = "645e0c6b3b381ede770e1cc9", } export enum Weapons762x54R @@ -22,6 +25,10 @@ export enum Weapons762x54R MOSIN_INFANTRY = "5bfd297f0db834001a669119", MOSIN_SNIPER = "5ae08f0a5acfc408fb1398a1", SV_98 = "55801eed4bdc2d89578b4588", + AVT_40 = "6410733d5dd49d77bd07847e", + SVT_40 = "643ea5b23db6f9f57107d9fd", + PKM = "64637076203536ad5600c990", + PKP = "64ca3d3954fc657e230529cc", } export enum Weapons762x51 @@ -60,6 +67,8 @@ export enum Weapons762x39 MK47_MUTANT = "606587252535c57a13424cfd", RD_704 = "628a60ae6b1d481ff772e9c8", VPO_136 = "59e6152586f77473dc057aa1", + RPD = "6513ef33e06849f06c0957ca", + RPDN = "65268d8ecb944ff1e90ea385", } export enum Weapons762x35 @@ -79,6 +88,8 @@ export enum Weapons556x45 SCARL_BLACK = "6184055050224f204c1da540", SCARL_FDE = "618428466ef05c2ce828f218", TX15_DML = "5d43021ca4b9362eab4b5e25", + AUG_A1 = "62e7c4fba689e8c9c50dfc38", + AUG_A3 = "63171672192e68c5460cebc5", } export enum Weapons545x39 @@ -95,6 +106,7 @@ export enum Weapons545x39 SAG_AK = "628b5638ad252a16da6dd245", SAG_AK_SHORT = "628b9c37a733087d0d7fe84b", RPK_16 = "5beed0f50db834001c062b12", + AK_12 = "6499849fc93611967b034949", } export enum Weapons57x28FN @@ -127,6 +139,7 @@ export enum Weapons9x33R export enum Weapons9x21 { SR_1MP = "59f98b4986f7746f546d2cef", + SR_2M = "62e14904c2699c0ec93adc47", } export enum Weapons9x19 @@ -147,6 +160,7 @@ export enum Weapons9x19 SAIGA_9 = "59f9cabd86f7743a10721f46", STM_9 = "60339954d62c9b14ed777c06", VECTOR_9MM = "5fc3f2d5900b1d5091531e57", + GLOCK_19X = "63088377b5cd696784087147", } export enum Weapons9x18 @@ -190,3 +204,14 @@ export enum Weapons23x75 { KS_23M = "5e848cc2988a8701445df1e8", } + +export enum Weapons68x51 +{ + MCX_SPEAR = "65290f395ae2ae97b80fdf2d", +} + +export enum Weapons40x46 +{ + M32A1 = "6275303a9f372d6ea97f9ec7", + FN40GL = "5e81ebcd8e146c7080625e15", +} diff --git a/project/src/models/spt/bots/IBotLootCache.ts b/project/src/models/spt/bots/IBotLootCache.ts index c2683770..8441b181 100644 --- a/project/src/models/spt/bots/IBotLootCache.ts +++ b/project/src/models/spt/bots/IBotLootCache.ts @@ -1,5 +1,3 @@ -import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; - export interface IBotLootCache { backpackLoot: Record; @@ -11,6 +9,9 @@ export interface IBotLootCache specialItems: Record; healingItems: Record; drugItems: Record; + foodItems: Record; + drinkItems: Record; + currencyItems: Record; stimItems: Record; grenadeItems: Record; } @@ -27,4 +28,7 @@ export enum LootCacheType DRUG_ITEMS = "DrugItems", STIM_ITEMS = "StimItems", GRENADE_ITEMS = "GrenadeItems", + FOOD_ITEMS = "FoodItems", + DRINK_ITEMS = "DrinkItems", + CURRENCY_ITEMS = "CurrencyItems", } diff --git a/project/src/models/spt/config/IBotConfig.ts b/project/src/models/spt/config/IBotConfig.ts index fd71175c..1ea1acc2 100644 --- a/project/src/models/spt/config/IBotConfig.ts +++ b/project/src/models/spt/config/IBotConfig.ts @@ -186,12 +186,9 @@ export interface IAdjustmentDetails edit: Record>; } -export interface IArmorPlateWeights +export interface IArmorPlateWeights extends Record { levelRange: MinMax; - frontPlateWeights: Record; - backPlateWeights: Record; - sidePlateWeights: Record; } export interface IRandomisedResourceDetails diff --git a/project/src/models/spt/config/ICoreConfig.ts b/project/src/models/spt/config/ICoreConfig.ts index de65c646..21f61368 100644 --- a/project/src/models/spt/config/ICoreConfig.ts +++ b/project/src/models/spt/config/ICoreConfig.ts @@ -9,6 +9,7 @@ export interface ICoreConfig extends IBaseConfig serverName: string; profileSaveIntervalSeconds: number; sptFriendNickname: string; + allowProfileWipe: boolean; bsgLogging: IBsgLogging; release: IRelease; fixes: IGameFixes; diff --git a/project/src/models/spt/config/IHideoutConfig.ts b/project/src/models/spt/config/IHideoutConfig.ts index 5d17a15b..0fc1caca 100644 --- a/project/src/models/spt/config/IHideoutConfig.ts +++ b/project/src/models/spt/config/IHideoutConfig.ts @@ -9,4 +9,8 @@ export interface IHideoutConfig extends IBaseConfig runIntervalValues: IRunIntervalValues; hoursForSkillCrafting: number; expCraftAmount: number; + overrideCraftTimeSeconds: number; + overrideBuildTimeSeconds: number; + /** Only process a profiles hideout crafts when it has been active in the last x minutes */ + updateProfileHideoutWhenActiveWithinMinutes: number; } diff --git a/project/src/models/spt/config/IHttpConfig.ts b/project/src/models/spt/config/IHttpConfig.ts index e1ddb9d5..f1130624 100644 --- a/project/src/models/spt/config/IHttpConfig.ts +++ b/project/src/models/spt/config/IHttpConfig.ts @@ -2,10 +2,14 @@ import { IBaseConfig } from "@spt-aki/models/spt/config/IBaseConfig"; export interface IHttpConfig extends IBaseConfig { - webSocketPingDelayMs: number; kind: "aki-http"; + /** Address used by webserver */ ip: string; port: number; + /** Address used by game client to connect to */ + backendIp: string; + backendPort: string; + webSocketPingDelayMs: number; logRequests: boolean; /** e.g. "Aki_Data/Server/images/traders/579dc571d53a0658a154fbec.png": "Aki_Data/Server/images/traders/NewTraderImage.png" */ serverImagePathOverride: Record; diff --git a/project/src/models/spt/config/IInRaidConfig.ts b/project/src/models/spt/config/IInRaidConfig.ts index 0f836fcb..f3dd433a 100644 --- a/project/src/models/spt/config/IInRaidConfig.ts +++ b/project/src/models/spt/config/IInRaidConfig.ts @@ -42,5 +42,4 @@ export interface Save { /** Should loot gained from raid be saved */ loot: boolean; - durability: boolean; } diff --git a/project/src/models/spt/config/ILocationConfig.ts b/project/src/models/spt/config/ILocationConfig.ts index fee9de50..e282ba0f 100644 --- a/project/src/models/spt/config/ILocationConfig.ts +++ b/project/src/models/spt/config/ILocationConfig.ts @@ -36,8 +36,10 @@ export interface ILocationConfig extends IBaseConfig /** How full must a random static magazine be %*/ minFillStaticMagazinePercent: number; allowDuplicateItemsInStaticContainers: boolean; - /** Chance loose/static magazines have ammo in them */ + /** Chance loose magazines have ammo in them TODO - rename to dynamicMagazineLootHasAmmoChancePercent */ magazineLootHasAmmoChancePercent: number; + /** Chance static magazines have ammo in them */ + staticMagazineLootHasAmmoChancePercent: number; /** Key: map, value: loose loot ids to ignore */ looseLootBlacklist: Record; /** Key: map, value: settings to control how long scav raids are*/ diff --git a/project/src/models/spt/config/IPmcConfig.ts b/project/src/models/spt/config/IPmcConfig.ts index bae06a7f..571c42c5 100644 --- a/project/src/models/spt/config/IPmcConfig.ts +++ b/project/src/models/spt/config/IPmcConfig.ts @@ -48,6 +48,8 @@ export interface IPmcConfig extends IBaseConfig /** Force a number of healing items into PMCs secure container to ensure they can heal */ forceHealingItemsIntoSecure: boolean; allPMCsHavePlayerNameWithRandomPrefixChance: number; + /** Should secure container loot from usec.json/bear.json be added to pmc bots secure */ + addSecureContainerLootFromBotConfig: boolean; } export interface PmcTypes diff --git a/project/src/models/spt/config/ITraderConfig.ts b/project/src/models/spt/config/ITraderConfig.ts index 1e972fbe..a4e98cb2 100644 --- a/project/src/models/spt/config/ITraderConfig.ts +++ b/project/src/models/spt/config/ITraderConfig.ts @@ -46,6 +46,8 @@ export interface FenceConfig presetSlotsToRemoveChancePercent: Record; /** Block seasonal items from appearing when season is inactive */ blacklistSeasonalItems: boolean; + /** Max pen value allowed to be listed on flea - affects ammo + ammo boxes */ + ammoMaxPenLimit: number; blacklist: string[]; coopExtractGift: CoopExtractReward; btrDeliveryExpireHours: number; diff --git a/project/src/models/spt/dialog/ISendMessageDetails.ts b/project/src/models/spt/dialog/ISendMessageDetails.ts index 1f9f0d05..13d8957e 100644 --- a/project/src/models/spt/dialog/ISendMessageDetails.ts +++ b/project/src/models/spt/dialog/ISendMessageDetails.ts @@ -34,7 +34,17 @@ export interface ISendMessageDetails export interface IProfileChangeEvent { _id: string; - Type: "TraderSalesSum" | "TraderStanding" | "ProfileLevel" | "SkillPoints" | "ExamineAllItems" | "UnlockTrader"; + Type: ProfileChangeEventType; value: number; entity?: string; } + +export enum ProfileChangeEventType +{ + TRADER_SALES_SUM = "TraderSalesSum", + TRADER_STANDING = "TraderStanding", + PROFILE_LEVEL = "ProfileLevel", + SKILL_POINTS = "SkillPoints", + EXAMINE_ALL_ITEMS = "ExamineAllItems", + UNLOCK_TRADER = "UnlockTrader", +} diff --git a/project/src/models/spt/fence/ICreateFenceAssortsResult.ts b/project/src/models/spt/fence/ICreateFenceAssortsResult.ts new file mode 100644 index 00000000..b81fd1cb --- /dev/null +++ b/project/src/models/spt/fence/ICreateFenceAssortsResult.ts @@ -0,0 +1,9 @@ +import { Item } from "@spt-aki/models/eft/common/tables/IItem"; +import { IBarterScheme } from "@spt-aki/models/eft/common/tables/ITrader"; + +export interface ICreateFenceAssortsResult +{ + sptItems: Item[][]; + barter_scheme: Record; + loyal_level_items: Record; +} diff --git a/project/src/routers/dynamic/BotDynamicRouter.ts b/project/src/routers/dynamic/BotDynamicRouter.ts index df65c79b..323912c4 100644 --- a/project/src/routers/dynamic/BotDynamicRouter.ts +++ b/project/src/routers/dynamic/BotDynamicRouter.ts @@ -23,6 +23,13 @@ export class BotDynamicRouter extends DynamicRouter return this.botCallbacks.getBotDifficulty(url, info, sessionID); }, ), + new RouteAction( + "/singleplayer/settings/bot/difficulties/", + (url: string, info: any, sessionID: string, output: string): any => + { + return this.botCallbacks.getAllBotDifficulties(url, info, sessionID); + }, + ), new RouteAction( "/singleplayer/settings/bot/maxCap", (url: string, info: any, sessionID: string, output: string): any => diff --git a/project/src/routers/static/DialogStaticRouter.ts b/project/src/routers/static/DialogStaticRouter.ts index a22acc6d..61ef74c9 100644 --- a/project/src/routers/static/DialogStaticRouter.ts +++ b/project/src/routers/static/DialogStaticRouter.ts @@ -115,6 +115,13 @@ export class DialogStaticRouter extends StaticRouter return this.dialogueCallbacks.sendFriendRequest(url, info, sessionID); }, ), + new RouteAction( + "/client/friend/request/accept-all", + (url: string, info: any, sessionID: string, output: string): any => + { + return this.dialogueCallbacks.acceptAllFriendRequests(url, info, sessionID); + }, + ), new RouteAction( "/client/friend/request/accept", (url: string, info: any, sessionID: string, output: string): any => @@ -122,6 +129,13 @@ export class DialogStaticRouter extends StaticRouter return this.dialogueCallbacks.acceptFriendRequest(url, info, sessionID); }, ), + new RouteAction( + "/client/friend/request/decline", + (url: string, info: any, sessionID: string, output: string): any => + { + return this.dialogueCallbacks.declineFriendRequest(url, info, sessionID); + }, + ), new RouteAction( "/client/friend/request/cancel", (url: string, info: any, sessionID: string, output: string): any => diff --git a/project/src/routers/static/InraidStaticRouter.ts b/project/src/routers/static/InraidStaticRouter.ts index f2835755..a0f77653 100644 --- a/project/src/routers/static/InraidStaticRouter.ts +++ b/project/src/routers/static/InraidStaticRouter.ts @@ -20,13 +20,6 @@ export class InraidStaticRouter extends StaticRouter return this.inraidCallbacks.getRaidEndState(); }, ), - new RouteAction( - "/singleplayer/settings/weapon/durability", - (url: string, info: any, sessionID: string, output: string): any => - { - return this.inraidCallbacks.getWeaponDurability(); - }, - ), new RouteAction( "/singleplayer/settings/raid/menu", (url: string, info: any, sessionID: string, output: string): any => diff --git a/project/src/servers/ConfigServer.ts b/project/src/servers/ConfigServer.ts index 85c4cb6f..ccd67d62 100644 --- a/project/src/servers/ConfigServer.ts +++ b/project/src/servers/ConfigServer.ts @@ -53,7 +53,7 @@ export class ConfigServer } } - this.logger.info(`Commit hash: ${(this.configs[ConfigTypes.CORE] as ICoreConfig).commit || "DEBUG"}`); - this.logger.info(`Build date: ${(this.configs[ConfigTypes.CORE] as ICoreConfig).buildTime || "DEBUG"}`); + this.logger.info(`Commit hash: ${globalThis.G_COMMIT || "DEBUG"}`); + this.logger.info(`Build date: ${globalThis.G_BUILDTIME || "DEBUG"}`); } } diff --git a/project/src/servers/HttpServer.ts b/project/src/servers/HttpServer.ts index 421c7ae4..ac371cd5 100644 --- a/project/src/servers/HttpServer.ts +++ b/project/src/servers/HttpServer.ts @@ -17,6 +17,7 @@ import { LocalisationService } from "@spt-aki/services/LocalisationService"; export class HttpServer { protected httpConfig: IHttpConfig; + protected started: boolean; constructor( @inject("WinstonLogger") protected logger: ILogger, @@ -37,6 +38,8 @@ export class HttpServer */ public load(): void { + this.started = false; + /* create server */ const httpServer: Server = http.createServer(); @@ -45,12 +48,10 @@ export class HttpServer this.handleRequest(req, res); }); - this.databaseServer.getTables().server.ip = this.httpConfig.ip; - this.databaseServer.getTables().server.port = this.httpConfig.port; - /* Config server to listen on a port */ httpServer.listen(this.httpConfig.port, this.httpConfig.ip, () => { + this.started = true; this.logger.success( this.localisationService.getText("started_webserver_success", this.httpServerHelper.getBackendUrl()), ); @@ -81,18 +82,20 @@ export class HttpServer if (this.httpConfig.logRequests) { - // TODO: Extend to include 192.168 / 10.10 ranges or check subnet - const isLocalRequest = req.socket.remoteAddress.startsWith("127.0.0"); - if (isLocalRequest) + const isLocalRequest = this.isLocalRequest(req.socket.remoteAddress); + if (typeof isLocalRequest !== "undefined") { - this.logger.info(this.localisationService.getText("client_request", req.url)); - } - else - { - this.logger.info(this.localisationService.getText("client_request_ip", { - ip: req.socket.remoteAddress, - url: req.url.replaceAll("/", "\\"), // Localisation service escapes `/` into hex code `/` - })); + if (isLocalRequest) + { + this.logger.info(this.localisationService.getText("client_request", req.url)); + } + else + { + this.logger.info(this.localisationService.getText("client_request_ip", { + ip: req.socket.remoteAddress, + url: req.url.replaceAll("/", "\\"), // Localisation service escapes `/` into hex code `/` + })); + } } } @@ -106,6 +109,23 @@ export class HttpServer } } + /** + * Check against hardcoded values that determine its from a local address + * @param remoteAddress Address to check + * @returns True if its local + */ + protected isLocalRequest(remoteAddress: string): boolean + { + if (!remoteAddress) + { + return undefined; + } + + return remoteAddress.startsWith("127.0.0") + || remoteAddress.startsWith("192.168.") + || remoteAddress.startsWith("localhost"); + } + protected getCookies(req: IncomingMessage): Record { const found: Record = {}; @@ -123,4 +143,9 @@ export class HttpServer return found; } + + public isStarted(): boolean + { + return this.started; + } } diff --git a/project/src/servers/WebSocketServer.ts b/project/src/servers/WebSocketServer.ts index 4dce9dee..03b05769 100644 --- a/project/src/servers/WebSocketServer.ts +++ b/project/src/servers/WebSocketServer.ts @@ -32,14 +32,25 @@ export class WebSocketServer protected httpConfig: IHttpConfig; protected defaultNotification: INotification = { type: NotificationType.PING, eventId: "ping" }; + protected webSocketServer: WebSocket.Server; protected webSockets: Record = {}; protected websocketPingHandler = null; + public getWebSocketServer(): WebSocket.Server + { + return this.webSocketServer; + } + + public getSessionWebSocket(sessionID: string): WebSocket.WebSocket + { + return this.webSockets[sessionID]; + } + public setupWebSocket(httpServer: http.Server): void { - const webSocketServer = new WebSocket.Server({ server: httpServer }); + this.webSocketServer = new WebSocket.Server({ server: httpServer }); - webSocketServer.addListener("listening", () => + this.webSocketServer.addListener("listening", () => { this.logger.success( this.localisationService.getText("websocket-started", this.httpServerHelper.getWebsocketUrl()), @@ -49,7 +60,7 @@ export class WebSocketServer ); }); - webSocketServer.addListener("connection", this.wsOnConnection.bind(this)); + this.webSocketServer.addListener("connection", this.wsOnConnection.bind(this)); } public sendMessage(sessionID: string, output: INotification): void @@ -101,7 +112,7 @@ export class WebSocketServer const logger = this.logger; const msgToLog = this.localisationService.getText("websocket-received_message", playerInfoText); - ws.on("message", function message(msg) + ws.on("message", (msg) => { logger.info(`${msgToLog} ${msg}`); }); diff --git a/project/src/servers/http/AkiHttpListener.ts b/project/src/servers/http/AkiHttpListener.ts index 34913e49..8ff17214 100644 --- a/project/src/servers/http/AkiHttpListener.ts +++ b/project/src/servers/http/AkiHttpListener.ts @@ -64,10 +64,11 @@ export class AkiHttpListener implements IHttpListener // determine if the payload is compressed. All PUT requests are, and POST requests without // debug = 1 are as well. This should be fixed. // let compressed = req.headers["content-encoding"] === "deflate"; - const compressed = req.method === "PUT" || req.headers.debug !== "1"; + const requestIsCompressed = req.headers.requestcompressed !== "0"; + const requestCompressed = req.method === "PUT" || requestIsCompressed; - const value = compressed ? zlib.inflateSync(buffer) : buffer; - if (req.headers.debug === "1") + const value = requestCompressed ? zlib.inflateSync(buffer) : buffer; + if (!requestIsCompressed) { this.logger.debug(value.toString(), true); } @@ -107,7 +108,7 @@ export class AkiHttpListener implements IHttpListener let handled = false; // Check if this is a debug request, if so just send the raw response without transformation - if (req.headers.debug === "1") + if (req.headers.responsecompressed === "0") { this.sendJson(resp, output, sessionID); } diff --git a/project/src/services/BotLootCacheService.ts b/project/src/services/BotLootCacheService.ts index 44d08524..f64ca5d4 100644 --- a/project/src/services/BotLootCacheService.ts +++ b/project/src/services/BotLootCacheService.ts @@ -59,28 +59,48 @@ export class BotLootCacheService this.addLootToCache(botRole, isPmc, botJsonTemplate); } + let result = undefined; switch (lootType) { case LootCacheType.SPECIAL: - return this.lootCache[botRole].specialItems; + result = this.lootCache[botRole].specialItems; + break; case LootCacheType.BACKPACK: - return this.lootCache[botRole].backpackLoot; + result = this.lootCache[botRole].backpackLoot; + break; case LootCacheType.POCKET: - return this.lootCache[botRole].pocketLoot; + result = this.lootCache[botRole].pocketLoot; + break; case LootCacheType.VEST: - return this.lootCache[botRole].vestLoot; + result = this.lootCache[botRole].vestLoot; + break; case LootCacheType.SECURE: - return this.lootCache[botRole].secureLoot; + result = this.lootCache[botRole].secureLoot; + break; case LootCacheType.COMBINED: - return this.lootCache[botRole].combinedPoolLoot; + result = this.lootCache[botRole].combinedPoolLoot; + break; case LootCacheType.HEALING_ITEMS: - return this.lootCache[botRole].healingItems; + result = this.lootCache[botRole].healingItems; + break; case LootCacheType.GRENADE_ITEMS: - return this.lootCache[botRole].grenadeItems; + result = this.lootCache[botRole].grenadeItems; + break; case LootCacheType.DRUG_ITEMS: - return this.lootCache[botRole].drugItems; + result = this.lootCache[botRole].drugItems; + break; + case LootCacheType.FOOD_ITEMS: + result = this.lootCache[botRole].foodItems; + break; + case LootCacheType.DRINK_ITEMS: + result = this.lootCache[botRole].drinkItems; + break; + case LootCacheType.CURRENCY_ITEMS: + result = this.lootCache[botRole].currencyItems; + break; case LootCacheType.STIM_ITEMS: - return this.lootCache[botRole].stimItems; + result = this.lootCache[botRole].stimItems; + break; default: this.logger.error( this.localisationService.getText("bot-loot_type_not_found", { @@ -91,6 +111,8 @@ export class BotLootCacheService ); break; } + + return this.jsonUtil.clone(result); } /** @@ -206,7 +228,7 @@ export class BotLootCacheService ? botJsonTemplate.generation.items.drugs.whitelist : {}; - // no whitelist, find and assign from combined item pool + // no drugs whitelist, find and assign from combined item pool if (Object.keys(drugItems).length === 0) { for (const [tpl, weight] of Object.entries(combinedLootPool)) @@ -219,6 +241,63 @@ export class BotLootCacheService } } + // Assign whitelisted food to bot if any exist + const foodItems: Record = + (Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0) + ? botJsonTemplate.generation.items.food.whitelist + : {}; + + // No food whitelist, find and assign from combined item pool + if (Object.keys(foodItems).length === 0) + { + for (const [tpl, weight] of Object.entries(combinedLootPool)) + { + const itemTemplate = this.itemHelper.getItem(tpl)[1]; + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.FOOD)) + { + foodItems[tpl] = weight; + } + } + } + + // Assign whitelisted drink to bot if any exist + const drinkItems: Record = + (Object.keys(botJsonTemplate.generation.items.food.whitelist)?.length > 0) + ? botJsonTemplate.generation.items.food.whitelist + : {}; + + // No drink whitelist, find and assign from combined item pool + if (Object.keys(drinkItems).length === 0) + { + for (const [tpl, weight] of Object.entries(combinedLootPool)) + { + const itemTemplate = this.itemHelper.getItem(tpl)[1]; + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.DRINK)) + { + drinkItems[tpl] = weight; + } + } + } + + // Assign whitelisted currency to bot if any exist + const currencyItems: Record = + (Object.keys(botJsonTemplate.generation.items.currency.whitelist)?.length > 0) + ? botJsonTemplate.generation.items.currency.whitelist + : {}; + + // No currency whitelist, find and assign from combined item pool + if (Object.keys(currencyItems).length === 0) + { + for (const [tpl, weight] of Object.entries(combinedLootPool)) + { + const itemTemplate = this.itemHelper.getItem(tpl)[1]; + if (this.itemHelper.isOfBaseclass(itemTemplate._id, BaseClasses.MONEY)) + { + currencyItems[tpl] = weight; + } + } + } + // Assign whitelisted stims to bot if any exist const stimItems: Record = (Object.keys(botJsonTemplate.generation.items.stims.whitelist)?.length > 0) @@ -257,7 +336,7 @@ export class BotLootCacheService } } - // Get backpack loot (excluding magazines, bullets, grenades and healing items) + // Get backpack loot (excluding magazines, bullets, grenades, drink, food and healing/stim items) const filteredBackpackItems = {}; for (const itemKey of Object.keys(backpackLootPool)) { @@ -272,6 +351,9 @@ export class BotLootCacheService || this.isMagazine(itemTemplate._props) || this.isMedicalItem(itemTemplate._props) || this.isGrenade(itemTemplate._props) + || this.isFood(itemTemplate._id) + || this.isDrink(itemTemplate._id) + || this.isCurrency(itemTemplate._id) ) { // Is type we dont want as backpack loot, skip @@ -281,7 +363,7 @@ export class BotLootCacheService filteredBackpackItems[itemKey] = backpackLootPool[itemKey]; } - // Get pocket loot (excluding magazines, bullets, grenades, medical and healing items) + // Get pocket loot (excluding magazines, bullets, grenades, drink, food medical and healing/stim items) const filteredPocketItems = {}; for (const itemKey of Object.keys(pocketLootPool)) { @@ -296,6 +378,9 @@ export class BotLootCacheService || this.isMagazine(itemTemplate._props) || this.isMedicalItem(itemTemplate._props) || this.isGrenade(itemTemplate._props) + || this.isFood(itemTemplate._id) + || this.isDrink(itemTemplate._id) + || this.isCurrency(itemTemplate._id) || !("Height" in itemTemplate._props) // lacks height || !("Width" in itemTemplate._props) // lacks width ) @@ -306,7 +391,7 @@ export class BotLootCacheService filteredPocketItems[itemKey] = pocketLootPool[itemKey]; } - // Get vest loot (excluding magazines, bullets, grenades, medical and healing items) + // Get vest loot (excluding magazines, bullets, grenades, medical and healing/stim items) const filteredVestItems = {}; for (const itemKey of Object.keys(vestLootPool)) { @@ -321,6 +406,9 @@ export class BotLootCacheService || this.isMagazine(itemTemplate._props) || this.isMedicalItem(itemTemplate._props) || this.isGrenade(itemTemplate._props) + || this.isFood(itemTemplate._id) + || this.isDrink(itemTemplate._id) + || this.isCurrency(itemTemplate._id) ) { continue; @@ -331,6 +419,9 @@ export class BotLootCacheService this.lootCache[botRole].healingItems = healingItems; this.lootCache[botRole].drugItems = drugItems; + this.lootCache[botRole].foodItems = foodItems; + this.lootCache[botRole].drinkItems = drinkItems; + this.lootCache[botRole].currencyItems = currencyItems; this.lootCache[botRole].stimItems = stimItems; this.lootCache[botRole].grenadeItems = grenadeItems; @@ -416,6 +507,21 @@ export class BotLootCacheService return ("ThrowType" in props); } + protected isFood(tpl: string): boolean + { + return this.itemHelper.isOfBaseclass(tpl, BaseClasses.FOOD); + } + + protected isDrink(tpl: string): boolean + { + return this.itemHelper.isOfBaseclass(tpl, BaseClasses.DRINK); + } + + protected isCurrency(tpl: string): boolean + { + return this.itemHelper.isOfBaseclass(tpl, BaseClasses.MONEY); + } + /** * Check if a bot type exists inside the loot cache * @param botRole role to check for @@ -442,6 +548,9 @@ export class BotLootCacheService specialItems: {}, grenadeItems: {}, drugItems: {}, + foodItems: {}, + drinkItems: {}, + currencyItems: {}, healingItems: {}, stimItems: {}, }; diff --git a/project/src/services/FenceService.ts b/project/src/services/FenceService.ts index db4f83b7..413c6c9d 100644 --- a/project/src/services/FenceService.ts +++ b/project/src/services/FenceService.ts @@ -3,16 +3,17 @@ 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"; -import { MinMax } from "@spt-aki/models/common/MinMax"; import { IFenceLevel } from "@spt-aki/models/eft/common/IGlobals"; import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; -import { Item, Repairable, Upd } from "@spt-aki/models/eft/common/tables/IItem"; +import { Item, Repairable } from "@spt-aki/models/eft/common/tables/IItem"; import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; import { IBarterScheme, ITraderAssort } from "@spt-aki/models/eft/common/tables/ITrader"; import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; +import { Money } from "@spt-aki/models/enums/Money"; import { Traders } from "@spt-aki/models/enums/Traders"; import { IItemDurabilityCurrentMax, ITraderConfig } from "@spt-aki/models/spt/config/ITraderConfig"; +import { ICreateFenceAssortsResult } from "@spt-aki/models/spt/fence/ICreateFenceAssortsResult"; import { IFenceAssortGenerationValues, IGenerationAssortValues, @@ -43,9 +44,21 @@ export class FenceService /** Assorts shown on a separate tab when you max out fence rep */ protected fenceDiscountAssort: ITraderAssort = undefined; - /** Hydrated on initial assort generation as part of generateFenceAssorts() */ + /** Desired baseline counts - Hydrated on initial assort generation as part of generateFenceAssorts() */ protected desiredAssortCounts: IFenceAssortGenerationValues; + protected fenceItemUpdCompareProperties = new Set([ + "Buff", + "Repairable", + "RecodableComponent", + "Key", + "Resource", + "MedKit", + "FoodDrink", + "Dogtag", + "RepairKit", + ]); + constructor( @inject("WinstonLogger") protected logger: ILogger, @inject("JsonUtil") protected jsonUtil: JsonUtil, @@ -71,6 +84,33 @@ export class FenceService this.fenceAssort = assort; } + /** + * Replace discount fence assort with new assort + * @param assort New assorts to replace old with + */ + public setDiscountFenceAssort(assort: ITraderAssort): void + { + this.fenceDiscountAssort = assort; + } + + /** + * Get main fence assort + * @return ITraderAssort + */ + public getMainFenceAssort(): ITraderAssort + { + return this.fenceAssort; + } + + /** + * Get discount fence assort + * @return ITraderAssort + */ + public getDiscountFenceAssort(): ITraderAssort + { + return this.fenceDiscountAssort; + } + /** * Replace high rep level fence assort with new assort * @param discountAssort New assorts to replace old with @@ -115,6 +155,72 @@ export class FenceService return assort; } + /** + * Adds to fence assort a single item (with its children) + * @param items the items to add with all its childrens + * @param mainItem the most parent item of the array + */ + public addItemsToFenceAssort(items: Item[], mainItem: Item): void + { + // HUGE THANKS TO LACYWAY AND LEAVES FOR PROVIDING THIS SOLUTION FOR SPT TO IMPLEMENT!! + // Copy the item and its children + let clonedItems = this.jsonUtil.clone(this.itemHelper.findAndReturnChildrenAsItems(items, mainItem._id)); + const root = clonedItems[0]; + + const cost = this.getItemPrice(root._tpl, clonedItems); + + // Fix IDs + clonedItems = this.itemHelper.reparentItemAndChildren(root, clonedItems); + root.parentId = "hideout"; + if (root.upd?.SpawnedInSession !== undefined) + { + root.upd.SpawnedInSession = false; + } + + // Clean up the items + delete root.location; + + const createAssort: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} }; + createAssort.barter_scheme[root._id] = [[{ count: cost, _tpl: Money.ROUBLES }]]; + createAssort.sptItems.push(clonedItems); + createAssort.loyal_level_items[root._id] = 1; + + this.updateFenceAssorts(createAssort, this.fenceAssort); + } + + /** + * Calculates the overall price for an item (with all its children) + * @param itemTpl the item tpl to calculate the fence price for + * @param items the items (with its children) to calculate fence price for + * @returns the fence price of the item + */ + public getItemPrice(itemTpl: string, items: Item[]): number + { + return this.itemHelper.isOfBaseclass(itemTpl, BaseClasses.AMMO_BOX) + ? this.getAmmoBoxPrice(items) * this.traderConfig.fence.itemPriceMult + : this.handbookHelper.getTemplatePrice(itemTpl) * this.traderConfig.fence.itemPriceMult; + } + + /** + * Calculate the overall price for an ammo box, where only one item is + * the ammo box itself and every other items are the bullets in that box + * @param items the ammo box (and all its children ammo items) + * @returns the price of the ammo box + */ + protected getAmmoBoxPrice(items: Item[]): number + { + let total = 0; + for (const item of items) + { + if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.AMMO)) + { + total += this.handbookHelper.getTemplatePrice(item._tpl) * (item.upd.StackObjectsCount ?? 1); + } + } + + return total; + } + /** * Adjust all items contained inside an assort by a multiplier * @param assort (clone)Assort that contains items with prices to adjust @@ -180,7 +286,7 @@ export class FenceService ): void { // Is preset - if (item.upd.sptPresetId) + if (item.upd?.sptPresetId) { if (assort.barter_scheme[item._id]) { @@ -231,16 +337,23 @@ export class FenceService this.deleteRandomAssorts(itemCountToReplace, this.fenceAssort); this.deleteRandomAssorts(discountItemCountToReplace, this.fenceDiscountAssort); - // Get count of what item pools need new items (item/weapon/equipment) - const itemCountsToReplace = this.getCountOfItemsToGenerate(); + const normalItemCountsToGenerate = this.getItemCountsToGenerate( + this.fenceAssort.items, + this.desiredAssortCounts.normal, + ); + const newItems = this.createAssorts(normalItemCountsToGenerate, 1); - const newItems = this.createFenceAssortSkeleton(); - this.createAssorts(itemCountsToReplace.normal, newItems, 1); - this.fenceAssort.items.push(...newItems.items); + // Push newly generated assorts into existing data + this.updateFenceAssorts(newItems, this.fenceAssort); - const newDiscountItems = this.createFenceAssortSkeleton(); - this.createAssorts(itemCountsToReplace.discount, newDiscountItems, 2); - this.fenceDiscountAssort.items.push(...newDiscountItems.items); + const discountItemCountsToGenerate = this.getItemCountsToGenerate( + this.fenceDiscountAssort.items, + this.desiredAssortCounts.discount, + ); + const newDiscountItems = this.createAssorts(discountItemCountsToGenerate, 2); + + // Push newly generated discount assorts into existing data + this.updateFenceAssorts(newDiscountItems, this.fenceDiscountAssort); // Add new barter items to fence barter scheme for (const barterItemKey in newItems.barter_scheme) @@ -271,6 +384,64 @@ export class FenceService this.incrementPartialRefreshTime(); } + /** + * Handle the process of folding new assorts into existing assorts, when a new assort exists already, increment its StackObjectsCount instead + * @param newFenceAssorts Assorts to fold into existing fence assorts + * @param existingFenceAssorts Current fence assorts new assorts will be added to + */ + protected updateFenceAssorts(newFenceAssorts: ICreateFenceAssortsResult, existingFenceAssorts: ITraderAssort): void + { + for (const itemWithChildren of newFenceAssorts.sptItems) + { + // Find the root item + const newRootItem = itemWithChildren.find((item) => item.slotId === "hideout"); + + // Find a matching root item with same tpl in existing assort + const existingRootItem = existingFenceAssorts.items.find((item) => + item._tpl === newRootItem._tpl && item.slotId === "hideout" + ); + + // Check if same type of item exists + its on list of item types to always stack + if (existingRootItem && this.itemInPreventDupeCategoryList(newRootItem._tpl)) + { + const existingFullItemTree = this.itemHelper.findAndReturnChildrenAsItems( + existingFenceAssorts.items, + existingRootItem._id, + ); + if ( + this.itemHelper.isSameItems( + itemWithChildren, + existingFullItemTree, + this.fenceItemUpdCompareProperties, + ) + ) + { + // Guard against a missing stack count + if (!existingRootItem.upd.StackObjectsCount) + { + existingRootItem.upd.StackObjectsCount = 1; + } + + // Merge new items count into existing, dont add new loyalty/barter data as it already exists + existingRootItem.upd.StackObjectsCount += newRootItem?.upd?.StackObjectsCount ?? 1; + + continue; + } + } + + // if the upd doesnt exist just initialize it + if (newRootItem.upd === undefined) + { + newRootItem.upd = {}; + } + // New assort to be added to existing assorts + existingFenceAssorts.items.push(...itemWithChildren); + existingFenceAssorts.barter_scheme[newRootItem._id] = newFenceAssorts.barter_scheme[newRootItem._id]; + existingFenceAssorts.loyal_level_items[newRootItem._id] = + newFenceAssorts.loyal_level_items[newRootItem._id]; + } + } + /** * Increment fence next refresh timestamp by current timestamp + partialRefreshTimeSeconds from config */ @@ -281,18 +452,18 @@ export class FenceService } /** - * Compare the current fence offer count to what the config wants it to be, - * If value is lower add extra count to value to generate more items to fill gap - * @param existingItemCountToReplace count of items to generate - * @returns number of items to generate + * Get values that will hydrate the passed in assorts back to the desired counts + * @param assortItems Current assorts after items have been removed + * @param generationValues Base counts assorts should be adjusted to + * @returns IGenerationAssortValues object with adjustments needed to reach desired state */ - protected getCountOfItemsToGenerate(): IFenceAssortGenerationValues + protected getItemCountsToGenerate( + assortItems: Item[], + generationValues: IGenerationAssortValues, + ): IGenerationAssortValues { - const currentItemAssortCount = Object.keys(this.fenceAssort.loyal_level_items).length; - - const rootPresetItems = this.fenceAssort.items.filter((item) => - item.slotId === "hideout" && item.upd.sptPresetId - ); + const allRootItems = assortItems.filter((item) => item.slotId === "hideout"); + const rootPresetItems = allRootItems.filter((item) => item?.upd?.sptPresetId); // Get count of weapons const currentWeaponPresetCount = rootPresetItems.reduce((count, item) => @@ -306,60 +477,19 @@ export class FenceService return this.itemHelper.armorItemCanHoldMods(item._tpl) ? count + 1 : count; }, 0); - const itemCountToGenerate = Math.max(this.desiredAssortCounts.normal.item - currentItemAssortCount, 0); - const weaponCountToGenerate = Math.max( - this.desiredAssortCounts.normal.weaponPreset - currentWeaponPresetCount, - 0, - ); - const equipmentCountToGenerate = Math.max( - this.desiredAssortCounts.normal.equipmentPreset - currentEquipmentPresetCount, - 0, - ); + // Normal item count is total count minus weapon + armor count + const nonPresetItemAssortCount = allRootItems.length - (currentWeaponPresetCount + currentEquipmentPresetCount); - const normalValues: IGenerationAssortValues = { + // Get counts of items to generate, never let values fall below 0 + const itemCountToGenerate = Math.max(generationValues.item - nonPresetItemAssortCount, 0); + const weaponCountToGenerate = Math.max(generationValues.weaponPreset - currentWeaponPresetCount, 0); + const equipmentCountToGenerate = Math.max(generationValues.equipmentPreset - currentEquipmentPresetCount, 0); + + return { item: itemCountToGenerate, weaponPreset: weaponCountToGenerate, equipmentPreset: equipmentCountToGenerate, }; - - // Discount tab handling - const currentDiscountItemAssortCount = Object.keys(this.fenceDiscountAssort.loyal_level_items).length; - const rootDiscountPresetItems = this.fenceDiscountAssort.items.filter((item) => - item.slotId === "hideout" && item.upd.sptPresetId - ); - - // Get count of weapons - const currentDiscountWeaponPresetCount = rootDiscountPresetItems.reduce((count, item) => - { - return this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.WEAPON) ? count + 1 : count; - }, 0); - - // Get count of equipment - const currentDiscountEquipmentPresetCount = rootDiscountPresetItems.reduce((count, item) => - { - return this.itemHelper.armorItemCanHoldMods(item._tpl) ? count + 1 : count; - }, 0); - - const itemDiscountCountToGenerate = Math.max( - this.desiredAssortCounts.discount.item - currentDiscountItemAssortCount, - 0, - ); - const weaponDiscountCountToGenerate = Math.max( - this.desiredAssortCounts.discount.weaponPreset - currentDiscountWeaponPresetCount, - 0, - ); - const equipmentDiscountCountToGenerate = Math.max( - this.desiredAssortCounts.discount.equipmentPreset - currentDiscountEquipmentPresetCount, - 0, - ); - - const discountValues: IGenerationAssortValues = { - item: itemDiscountCountToGenerate, - weaponPreset: weaponDiscountCountToGenerate, - equipmentPreset: equipmentDiscountCountToGenerate, - }; - - return { normal: normalValues, discount: discountValues }; } /** @@ -381,23 +511,47 @@ export class FenceService /** * Choose an item at random and remove it + mods from assorts - * @param assort Items to remove from - * @param rootItems Assort root items to pick from to remove + * @param assort Trader assort to remove item from + * @param rootItems Pool of root items to pick from to remove */ protected removeRandomItemFromAssorts(assort: ITraderAssort, rootItems: Item[]): void { - const rootItemToRemove = this.randomUtil.getArrayValue(rootItems); + const rootItemToAdjust = this.randomUtil.getArrayValue(rootItems); - // Clean up any mods if item had them - const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(assort.items, rootItemToRemove._id); + // Items added by mods may not have a upd object, assume item stack size is 1 + const stackSize = rootItemToAdjust.upd?.StackObjectsCount ?? 1; + + // Get a random count of the chosen item to remove + const itemCountToRemove = this.randomUtil.getInt(1, stackSize); + + const isEntireStackToBeRemoved = itemCountToRemove === stackSize; + + // Partial stack reduction + if (!isEntireStackToBeRemoved) + { + if (!rootItemToAdjust.upd) + { + this.logger.warning(`Fence Item: ${rootItemToAdjust._tpl} lacks a upd object, adding`); + rootItemToAdjust.upd = {}; + } + + // Reduce stack to at smallest, 1 + rootItemToAdjust.upd.StackObjectsCount -= Math.max(1, itemCountToRemove); + + return; + } + + // Remove item + child mods (if any) + const itemWithChildren = this.itemHelper.findAndReturnChildrenAsItems(assort.items, rootItemToAdjust._id); for (const itemToDelete of itemWithChildren) { // Delete item from assort items array assort.items.splice(assort.items.indexOf(itemToDelete), 1); } - delete assort.barter_scheme[rootItemToRemove._id]; - delete assort.loyal_level_items[rootItemToRemove._id]; + // Need to remove item from all areas of trader assort + delete assort.barter_scheme[rootItemToAdjust._id]; + delete assort.loyal_level_items[rootItemToAdjust._id]; } /** @@ -437,16 +591,35 @@ export class FenceService this.createInitialFenceAssortGenerationValues(); // Create basic fence assort - const assorts = this.createFenceAssortSkeleton(); - this.createAssorts(this.desiredAssortCounts.normal, assorts, 1); + const assorts = this.createAssorts(this.desiredAssortCounts.normal, 1); + // Store in this.fenceAssort - this.setFenceAssort(assorts); + this.setFenceAssort(this.convertIntoFenceAssort(assorts)); // Create level 2 assorts accessible at rep level 6 - const discountAssorts = this.createFenceAssortSkeleton(); - this.createAssorts(this.desiredAssortCounts.discount, discountAssorts, 2); + const discountAssorts = this.createAssorts(this.desiredAssortCounts.discount, 2); + // Store in this.fenceDiscountAssort - this.setFenceDiscountAssort(discountAssorts); + this.setFenceDiscountAssort(this.convertIntoFenceAssort(discountAssorts)); + } + + /** + * Convert the intermediary assort data generated into format client can process + * @param intermediaryAssorts Generated assorts that will be converted + * @returns ITraderAssort + */ + protected convertIntoFenceAssort(intermediaryAssorts: ICreateFenceAssortsResult): ITraderAssort + { + const result = this.createFenceAssortSkeleton(); + for (const itemWithChilden of intermediaryAssorts.sptItems) + { + result.items.push(...itemWithChilden); + } + + result.barter_scheme = intermediaryAssorts.barter_scheme; + result.loyal_level_items = intermediaryAssorts.loyal_level_items; + + return result; } /** @@ -506,14 +679,22 @@ export class FenceService * @param assortCount Number of assorts to generate * @param assorts object to add created assorts to */ - protected createAssorts(itemCounts: IGenerationAssortValues, assorts: ITraderAssort, loyaltyLevel: number): void + protected createAssorts(itemCounts: IGenerationAssortValues, loyaltyLevel: number): ICreateFenceAssortsResult { + const result: ICreateFenceAssortsResult = { sptItems: [], barter_scheme: {}, loyal_level_items: {} }; + const baseFenceAssortClone = this.jsonUtil.clone(this.databaseServer.getTables().traders[Traders.FENCE].assort); const itemTypeLimitCounts = this.initItemLimitCounter(this.traderConfig.fence.itemTypeLimits); if (itemCounts.item > 0) { - this.addItemAssorts(itemCounts.item, assorts, baseFenceAssortClone, itemTypeLimitCounts, loyaltyLevel); + const itemResult = this.addItemAssorts( + itemCounts.item, + result, + baseFenceAssortClone, + itemTypeLimitCounts, + loyaltyLevel, + ); } if (itemCounts.weaponPreset > 0 || itemCounts.equipmentPreset > 0) @@ -522,11 +703,13 @@ export class FenceService this.addPresetsToAssort( itemCounts.weaponPreset, itemCounts.equipmentPreset, - assorts, + result, baseFenceAssortClone, loyaltyLevel, ); } + + return result; } /** @@ -539,15 +722,15 @@ export class FenceService */ protected addItemAssorts( assortCount: number, - assorts: ITraderAssort, + assorts: ICreateFenceAssortsResult, baseFenceAssortClone: ITraderAssort, itemTypeLimits: Record, loyaltyLevel: number, ): void { const priceLimits = this.traderConfig.fence.itemCategoryRoublePriceLimit; - const assortRootItems = baseFenceAssortClone.items.filter((x) => - x.parentId === "hideout" && !x.upd?.sptPresetId + const assortRootItems = baseFenceAssortClone.items.filter((item) => + item.parentId === "hideout" && !item.upd?.sptPresetId ); for (let i = 0; i < assortCount; i++) @@ -614,7 +797,7 @@ export class FenceService } // Skip items already in the assort if it exists in the prevent duplicate list - const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.items); + const existingItemThatMatches = this.getMatchingItem(rootItemBeingAdded, itemDbDetails, assorts.sptItems); const shouldBeStacked = this.itemShouldBeForceStacked(existingItemThatMatches, itemDbDetails); if (shouldBeStacked && existingItemThatMatches) { // Decrement loop counter so another items gets added @@ -630,7 +813,7 @@ export class FenceService this.randomiseArmorModDurability(desiredAssortItemAndChildrenClone, itemDbDetails); } - assorts.items.push(...desiredAssortItemAndChildrenClone); + assorts.sptItems.push(desiredAssortItemAndChildrenClone); assorts.barter_scheme[rootItemBeingAdded._id] = this.jsonUtil.clone( baseFenceAssortClone.barter_scheme[chosenBaseAssortRoot._id], @@ -651,15 +834,15 @@ export class FenceService * e.g. salewa hp resource units left * @param rootItemBeingAdded item to look for a match against * @param itemDbDetails Db details of matching item - * @param fenceItemAssorts Items to search through + * @param itemsWithChildren Items to search through * @returns Matching assort item */ - protected getMatchingItem(rootItemBeingAdded: Item, itemDbDetails: ITemplateItem, fenceItemAssorts: Item[]): Item + protected getMatchingItem(rootItemBeingAdded: Item, itemDbDetails: ITemplateItem, itemsWithChildren: Item[][]): Item { // Get matching root items - const matchingItems = fenceItemAssorts.filter((item) => - item._tpl === rootItemBeingAdded._tpl && item.parentId === "hideout" - ); + const matchingItems = itemsWithChildren.filter((itemWithChildren) => + itemWithChildren.find((item) => item._tpl === rootItemBeingAdded._tpl && item.parentId === "hideout") + ).flatMap((x) => x); if (matchingItems.length === 0) { // Nothing matches by tpl and is root item, exit early @@ -726,11 +909,13 @@ export class FenceService return false; } + return this.itemInPreventDupeCategoryList(itemDbDetails._id); + } + + protected itemInPreventDupeCategoryList(tpl: string): boolean + { // Item type in config list - return this.itemHelper.isOfBaseclasses( - itemDbDetails._id, - this.traderConfig.fence.preventDuplicateOffersOfCategory, - ); + return this.itemHelper.isOfBaseclasses(tpl, this.traderConfig.fence.preventDuplicateOffersOfCategory); } /** @@ -799,7 +984,7 @@ export class FenceService protected addPresetsToAssort( desiredWeaponPresetsCount: number, desiredEquipmentPresetsCount: number, - assorts: ITraderAssort, + assorts: ICreateFenceAssortsResult, baseFenceAssort: ITraderAssort, loyaltyLevel: number, ): void @@ -848,7 +1033,7 @@ export class FenceService // Remapping IDs causes parentid to be altered presetWithChildrenClone[0].parentId = "hideout"; - assorts.items.push(...presetWithChildrenClone); + assorts.sptItems.push(presetWithChildrenClone); // Set assort price // Must be careful to use correct id as the item has had its IDs regenerated @@ -908,7 +1093,7 @@ export class FenceService // Remapping IDs causes parentid to be altered presetWithChildrenClone[0].parentId = "hideout"; - assorts.items.push(...presetWithChildrenClone); + assorts.sptItems.push(presetWithChildrenClone); // Set assort price // Must be careful to use correct id as the item has had its IDs regenerated diff --git a/project/src/services/ItemBaseClassService.ts b/project/src/services/ItemBaseClassService.ts index e9ed0493..94259cea 100644 --- a/project/src/services/ItemBaseClassService.ts +++ b/project/src/services/ItemBaseClassService.ts @@ -13,6 +13,7 @@ import { LocalisationService } from "@spt-aki/services/LocalisationService"; export class ItemBaseClassService { protected itemBaseClassesCache: Record = {}; + protected items: Record; protected cacheGenerated = false; constructor( @@ -31,15 +32,15 @@ export class ItemBaseClassService // Clear existing cache this.itemBaseClassesCache = {}; - const allDbItems = this.databaseServer.getTables().templates.items; - if (!allDbItems) + this.items = this.databaseServer.getTables().templates.items; + if (!this.items) { this.logger.warning(this.localisationService.getText("baseclass-missing_db_no_cache")); return; } - const filteredDbItems = Object.values(allDbItems).filter((x) => x._type === "Item"); + const filteredDbItems = Object.values(this.items).filter((x) => x._type === "Item"); for (const item of filteredDbItems) { const itemIdToUpdate = item._id; @@ -48,7 +49,7 @@ export class ItemBaseClassService this.itemBaseClassesCache[item._id] = []; } - this.addBaseItems(itemIdToUpdate, item, allDbItems); + this.addBaseItems(itemIdToUpdate, item); } this.cacheGenerated = true; @@ -58,16 +59,15 @@ export class ItemBaseClassService * Helper method, recursivly iterate through items parent items, finding and adding ids to dictionary * @param itemIdToUpdate item tpl to store base ids against in dictionary * @param item item being checked - * @param allDbItems all items in db */ - protected addBaseItems(itemIdToUpdate: string, item: ITemplateItem, allDbItems: Record): void + protected addBaseItems(itemIdToUpdate: string, item: ITemplateItem): void { this.itemBaseClassesCache[itemIdToUpdate].push(item._parent); - const parent = allDbItems[item._parent]; + const parent = this.items[item._parent]; if (parent._parent !== "") { - this.addBaseItems(itemIdToUpdate, parent, allDbItems); + this.addBaseItems(itemIdToUpdate, parent); } } @@ -91,8 +91,9 @@ export class ItemBaseClassService return false; } - // Edge case - this is the 'root' item that all other items inherit from - if (itemTpl === BaseClasses.ITEM) + // The cache is only generated for item templates with `_type === "Item"`, so return false for any other type, + // including item templates that simply don't exist. + if (!this.cachedItemIsOfItemType(itemTpl)) { return false; } @@ -114,6 +115,16 @@ export class ItemBaseClassService return this.itemBaseClassesCache[itemTpl].some((x) => baseClasses.includes(x)); } + /** + * Check if cached item template is of type Item + * @param itemTemplateId item to check + * @returns true if item is of type Item + */ + private cachedItemIsOfItemType(itemTemplateId: string): boolean + { + return this.items[itemTemplateId]?._type === "Item"; + } + /** * Get base classes item inherits from * @param itemTpl item to get base classes for diff --git a/project/src/services/MailSendService.ts b/project/src/services/MailSendService.ts index df87a958..4fbc536a 100644 --- a/project/src/services/MailSendService.ts +++ b/project/src/services/MailSendService.ts @@ -10,7 +10,7 @@ import { Dialogue, IUserDialogInfo, Message, MessageItems } from "@spt-aki/model import { BaseClasses } from "@spt-aki/models/enums/BaseClasses"; import { MessageType } from "@spt-aki/models/enums/MessageType"; import { Traders } from "@spt-aki/models/enums/Traders"; -import { ISendMessageDetails } from "@spt-aki/models/spt/dialog/ISendMessageDetails"; +import { IProfileChangeEvent, ISendMessageDetails } from "@spt-aki/models/spt/dialog/ISendMessageDetails"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; import { SaveServer } from "@spt-aki/servers/SaveServer"; @@ -169,7 +169,8 @@ export class MailSendService sessionId: string, message: string, items: Item[] = [], - maxStorageTimeSeconds = null, + maxStorageTimeSeconds?: number, + profileChangeEvents?: IProfileChangeEvent[], ): void { const details: ISendMessageDetails = { @@ -185,6 +186,11 @@ export class MailSendService details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } + if ((profileChangeEvents?.length ?? 0) > 0) + { + details.profileChangeEvents = profileChangeEvents; + } + this.sendMessageToPlayer(details); } @@ -199,8 +205,8 @@ export class MailSendService sessionId: string, messageLocaleId: string, items: Item[] = [], - profileChangeEvents = [], - maxStorageTimeSeconds = null, + profileChangeEvents?: IProfileChangeEvent[], + maxStorageTimeSeconds?: number, ): void { const details: ISendMessageDetails = { @@ -216,7 +222,7 @@ export class MailSendService details.itemsMaxStorageLifetimeSeconds = maxStorageTimeSeconds ?? 172800; // 48 hours if no value supplied } - if (profileChangeEvents.length > 0) + if ((profileChangeEvents?.length ?? 0) > 0) { details.profileChangeEvents = profileChangeEvents; } @@ -455,7 +461,7 @@ export class MailSendService } // Ensure every 'base/root' item has the same parentId + has a slotid of 'main' - if (!("slotId" in reward) || reward.slotId === "hideout") + if (!("slotId" in reward) || reward.slotId === "hideout" || reward.parentId === parentItem.parentId) { // Reward items NEED a parent id + slotid reward.parentId = parentItem.parentId; diff --git a/project/src/services/ModCompilerService.ts b/project/src/services/ModCompilerService.ts index 159588b9..7968dea0 100644 --- a/project/src/services/ModCompilerService.ts +++ b/project/src/services/ModCompilerService.ts @@ -114,8 +114,8 @@ export class ModCompilerService if (output.sourceMapText) { output.outputText = output.outputText.replace( - "//# sourceMappingURL=module.js.map", - `//# sourceMappingURL=${parsedDestPath.base}.map`, + "//# sourceMappingURL\=module.js.map", + `//# sourceMappingURL\=${parsedDestPath.base}.map`, ); const sourceMap = JSON.parse(output.sourceMapText); diff --git a/project/src/services/PaymentService.ts b/project/src/services/PaymentService.ts index 4ef6bfac..300197a4 100644 --- a/project/src/services/PaymentService.ts +++ b/project/src/services/PaymentService.ts @@ -65,7 +65,13 @@ export class PaymentService if (!this.paymentHelper.isMoneyTpl(item._tpl)) { // If the item is not money, remove it from the inventory. - this.inventoryHelper.removeItem(pmcData, item._id, sessionID, output); + this.inventoryHelper.removeItemByCount( + pmcData, + item._id, + request.scheme_items[index].count, + sessionID, + output, + ); request.scheme_items[index].count = 0; } else @@ -315,7 +321,7 @@ export class PaymentService } /** - * Get all money stacks in inventory and prioritse items in stash + * Get all money stacks in inventory and prioritise items in stash * @param pmcData * @param currencyTpl * @param playerStashId Players stash id diff --git a/project/src/services/ProfileActivityService.ts b/project/src/services/ProfileActivityService.ts new file mode 100644 index 00000000..b9f7619e --- /dev/null +++ b/project/src/services/ProfileActivityService.ts @@ -0,0 +1,64 @@ +import { injectable } from "tsyringe"; + +@injectable() +export class ProfileActivityService +{ + protected profileActivityTimestamps: Record = {}; + + /** + * Was the requested profile active in the last requested minutes + * @param sessionId Profile to check + * @param minutes Minutes to check for activity in + * @returns True when profile was active within past x minutes + */ + public activeWithinLastMinutes(sessionId: string, minutes: number): boolean + { + const currentTimestamp = new Date().getTime() / 1000; + const storedActivityTimestamp = this.profileActivityTimestamps[sessionId]; + if (!storedActivityTimestamp) + { + // No value, no assumed activity (server offline?) + return false; + } + + // True if difference since last timestamp to now is below desired amount + return (currentTimestamp - storedActivityTimestamp) < (minutes * 60); // convert minutes to seconds to compare + } + + /** + * Get an array of profile ids that were active in the last x minutes + * @param minutes How many minutes from now to search for profiles + * @returns String array of profile ids + */ + public getActiveProfileIdsWithinMinutes(minutes: number): string[] + { + const currentTimestamp = new Date().getTime() / 1000; + const result: string[] = []; + + for (const id of Object.keys(this.profileActivityTimestamps ?? {})) + { + const lastActiveTimestamp = this.profileActivityTimestamps[id]; + if (!lastActiveTimestamp) + { + continue; + } + + // Profile was active in last x minutes, add to return list + if ((currentTimestamp - lastActiveTimestamp) < (minutes * 60)) + { + result.push(id); + } + } + + return result; + } + + /** + * Update the timestamp a profile was last observed active + * @param sessionId Profile to update + */ + public setActivityTimestamp(sessionId: string): void + { + this.profileActivityTimestamps[sessionId] = new Date().getTime() / 1000; + } +} diff --git a/project/src/services/ProfileFixerService.ts b/project/src/services/ProfileFixerService.ts index 23a09b25..28205ee0 100644 --- a/project/src/services/ProfileFixerService.ts +++ b/project/src/services/ProfileFixerService.ts @@ -9,9 +9,9 @@ import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; import { Bonus, HideoutSlot, IQuestStatus } from "@spt-aki/models/eft/common/tables/IBotBase"; import { IHideoutImprovement } from "@spt-aki/models/eft/common/tables/IBotBase"; import { IPmcDataRepeatableQuest, IRepeatableQuest } from "@spt-aki/models/eft/common/tables/IRepeatableQuests"; +import { ITemplateItem } from "@spt-aki/models/eft/common/tables/ITemplateItem"; import { StageBonus } from "@spt-aki/models/eft/hideout/IHideoutArea"; -import { IAkiProfile } from "@spt-aki/models/eft/profile/IAkiProfile"; -import { AccountTypes } from "@spt-aki/models/enums/AccountTypes"; +import { IAkiProfile, IEquipmentBuild, IMagazineBuild, IWeaponBuild } from "@spt-aki/models/eft/profile/IAkiProfile"; import { BonusType } from "@spt-aki/models/enums/BonusType"; import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { HideoutAreas } from "@spt-aki/models/enums/HideoutAreas"; @@ -157,6 +157,7 @@ export class ProfileFixerService } this.fixNullTraderSalesSums(pmcProfile); + this.fixNullTraderNextResupply(pmcProfile); this.updateProfileQuestDataValues(pmcProfile); } @@ -282,7 +283,11 @@ export class ProfileFixerService } const db = this.databaseServer.getTables(); - const placeOfFameAreaDb = db.hideout.areas.find((x) => x.type === HideoutAreas.PLACE_OF_FAME); + const placeOfFameAreaDb = db.hideout.areas.find((area) => area.type === HideoutAreas.PLACE_OF_FAME); + if (!placeOfFameAreaDb) + { + return; + } const stageCurrentlyAt = placeOfFameAreaDb.stages[placeOfFameArea.level]; const placeOfFameStashId = pmcProfile.Inventory.hideoutAreaStashes[HideoutAreas.PLACE_OF_FAME]; @@ -870,53 +875,47 @@ export class ProfileFixerService const inventoryItemsToCheck = pmcProfile.Inventory.items.filter((item) => ["hideout", "main"].includes(item.slotId) ); - if (!inventoryItemsToCheck) + if (inventoryItemsToCheck) { - return; - } - - // Check each item in inventory to ensure item exists in itemdb - for (const item of inventoryItemsToCheck) - { - if (!itemsDb[item._tpl]) + // Check each item in inventory to ensure item exists in itemdb + for (const item of inventoryItemsToCheck) { - this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); - - if (this.coreConfig.fixes.removeModItemsFromProfile) - { - this.logger.success( - `Deleting item from inventory and insurance with id: ${item._id} tpl: ${item._tpl}`, - ); - - // Also deletes from insured array - this.inventoryHelper.removeItem(pmcProfile, item._id, sessionId); - } - } - } - - // Iterate over player-made weapon builds, look for missing items and remove weapon preset if found - for (const buildId in fullProfile.userbuilds?.weaponBuilds) - { - for (const item of fullProfile.userbuilds.weaponBuilds[buildId].Items) - { - // Check item exists in itemsDb if (!itemsDb[item._tpl]) { this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); if (this.coreConfig.fixes.removeModItemsFromProfile) { - delete fullProfile.userbuilds.weaponBuilds[buildId]; - this.logger.warning( - `Item: ${item._tpl} has resulted in the deletion of weapon build: ${buildId}`, + this.logger.success( + `Deleting item from inventory and insurance with id: ${item._id} tpl: ${item._tpl}`, ); - } - break; + // Also deletes from insured array + this.inventoryHelper.removeItem(pmcProfile, item._id, sessionId); + } } } } + // Remove invalid builds from weapon, equipment and magazine build lists + const weaponBuilds = fullProfile.userbuilds?.weaponBuilds || []; + fullProfile.userbuilds.weaponBuilds = weaponBuilds.filter((weaponBuild) => + { + return !this.shouldRemoveWeaponEquipmentBuild("weapon", weaponBuild, itemsDb); + }); + + const equipmentBuilds = fullProfile.userbuilds?.equipmentBuilds || []; + fullProfile.userbuilds.equipmentBuilds = equipmentBuilds.filter((equipmentBuild) => + { + return !this.shouldRemoveWeaponEquipmentBuild("equipment", equipmentBuild, itemsDb); + }); + + const magazineBuilds = fullProfile.userbuilds?.magazineBuilds || []; + fullProfile.userbuilds.magazineBuilds = magazineBuilds.filter((magazineBuild) => + { + return !this.shouldRemoveMagazineBuild(magazineBuild, itemsDb); + }); + // Iterate over dialogs, looking for messages with items not found in item db, remove message if item found for (const dialogId in fullProfile.dialogues) { @@ -927,7 +926,7 @@ export class ProfileFixerService } // Iterate over all messages in dialog - for (const message of dialog.messages) + for (const [_, message] of Object.entries(dialog.messages)) { if (!message.items?.data) { @@ -965,7 +964,7 @@ export class ProfileFixerService } const clothing = this.databaseServer.getTables().templates.customization; - for (const suitId of fullProfile.suits) + for (const [_, suitId] of Object.entries(fullProfile.suits)) { if (!clothing[suitId]) { @@ -980,7 +979,7 @@ export class ProfileFixerService for (const repeatable of fullProfile.characters.pmc.RepeatableQuests ?? []) { - for (const activeQuest of repeatable.activeQuests ?? []) + for (const [_, activeQuest] of Object.entries(repeatable.activeQuests ?? [])) { if (!this.traderHelper.traderEnumHasValue(activeQuest.traderId)) { @@ -1041,6 +1040,77 @@ export class ProfileFixerService } } + /** + * @param buildType The type of build, used for logging only + * @param build The build to check for invalid items + * @param itemsDb The items database to use for item lookup + * @returns True if the build should be removed from the build list, false otherwise + */ + protected shouldRemoveWeaponEquipmentBuild( + buildType: string, + build: IWeaponBuild | IEquipmentBuild, + itemsDb: Record, + ): boolean + { + for (const item of build.Items) + { + // Check item exists in itemsDb + if (!itemsDb[item._tpl]) + { + this.logger.error(this.localisationService.getText("fixer-mod_item_found", item._tpl)); + + if (this.coreConfig.fixes.removeModItemsFromProfile) + { + this.logger.warning( + `Item: ${item._tpl} has resulted in the deletion of ${buildType} build: ${build.Name}`, + ); + + return true; + } + + break; + } + } + + return false; + } + + /** + * @param magazineBuild The magazine build to check for validity + * @param itemsDb The items database to use for item lookup + * @returns True if the build should be removed from the build list, false otherwise + */ + protected shouldRemoveMagazineBuild(magazineBuild: IMagazineBuild, itemsDb: Record): boolean + { + for (const item of magazineBuild.Items) + { + // Magazine builds can have null items in them, skip those + if (!item) + { + continue; + } + + // Check item exists in itemsDb + if (!itemsDb[item.TemplateId]) + { + this.logger.error(this.localisationService.getText("fixer-mod_item_found", item.TemplateId)); + + if (this.coreConfig.fixes.removeModItemsFromProfile) + { + this.logger.warning( + `Item: ${item.TemplateId} has resulted in the deletion of magazine build: ${magazineBuild.Name}`, + ); + + return true; + } + + break; + } + } + + return false; + } + /** * Attempt to fix common item issues that corrupt profiles * @param pmcProfile Profile to check items of @@ -1307,6 +1377,21 @@ export class ProfileFixerService } } + /** + * 3.8.0 utilized the wrong ProductionTime for bitcoin, fix it if it's found + */ + public fixBitcoinProductionTime(pmcProfile: IPmcData): void + { + const btcProd = pmcProfile.Hideout?.Production[HideoutHelper.bitcoinFarm]; + if (btcProd) + { + btcProd.ProductionTime = this.hideoutHelper.getAdjustedCraftTimeWithSkills( + pmcProfile, + HideoutHelper.bitcoinProductionId, + ); + } + } + /** * At some point the property name was changed,migrate data across to new name * @param pmcProfile Profile to migrate improvements in @@ -1337,7 +1422,7 @@ export class ProfileFixerService repeatableQuests.push(...repeatableQuestType.activeQuests); } - for (let i = 0; i < profileQuests.length; i++) + for (let i = profileQuests.length - 1; i >= 0; i--) { if (!(quests[profileQuests[i].qid] || repeatableQuests.find((x) => x._id === profileQuests[i].qid))) { @@ -1346,4 +1431,20 @@ export class ProfileFixerService } } } + + /** + * If someone has run a mod from pre-3.8.0, it results in an invalid `nextResupply` value + * Resolve this by setting the nextResupply to 0 if it's null + */ + protected fixNullTraderNextResupply(pmcProfile: IPmcData): void + { + for (const [traderId, trader] of Object.entries(pmcProfile.TradersInfo)) + { + if (trader && trader.nextResupply === null) + { + this.logger.warning(`trader ${traderId} has a null nextResupply value, resetting to 0`); + trader.nextResupply = 0; + } + } + } } diff --git a/project/src/services/RagfairOfferService.ts b/project/src/services/RagfairOfferService.ts index 7b12174c..6ac95cfb 100644 --- a/project/src/services/RagfairOfferService.ts +++ b/project/src/services/RagfairOfferService.ts @@ -25,7 +25,7 @@ export class RagfairOfferService protected expiredOffers: Record = {}; protected ragfairConfig: IRagfairConfig; - protected ragfairOfferHandler: RagfairOfferHolder = new RagfairOfferHolder(); + protected ragfairOfferHandler: RagfairOfferHolder; constructor( @inject("WinstonLogger") protected logger: ILogger, @@ -41,6 +41,10 @@ export class RagfairOfferService ) { this.ragfairConfig = this.configServer.getConfig(ConfigTypes.RAGFAIR); + this.ragfairOfferHandler = new RagfairOfferHolder( + this.ragfairConfig.dynamic.offerItemCount.max, + ragfairServerHelper, + ); } /** diff --git a/project/src/services/RagfairPriceService.ts b/project/src/services/RagfairPriceService.ts index 6762bcec..6c3e578b 100644 --- a/project/src/services/RagfairPriceService.ts +++ b/project/src/services/RagfairPriceService.ts @@ -56,13 +56,11 @@ export class RagfairPriceService implements OnLoad if (!this.generatedStaticPrices) { this.generateStaticPrices(); - this.generatedStaticPrices = true; } if (!this.generatedDynamicPrices) { this.generateDynamicPrices(); - this.generatedDynamicPrices = true; } } @@ -84,14 +82,18 @@ export class RagfairPriceService implements OnLoad { this.prices.static[item._id] = Math.round(this.handbookHelper.getTemplatePrice(item._id)); } + + this.generatedStaticPrices = true; } /** * Create a dictionary and store prices from prices.json in it */ - protected generateDynamicPrices(): void + public generateDynamicPrices(): void { Object.assign(this.prices.dynamic, this.databaseServer.getTables().templates.prices); + + this.generatedDynamicPrices = true; } /** @@ -223,109 +225,129 @@ export class RagfairPriceService implements OnLoad */ public getDynamicOfferPriceForOffer(offerItems: Item[], desiredCurrency: string, isPackOffer: boolean): number { - const rootItem = offerItems[0]; - - // Price to return + // Price to return. let price = 0; - let endLoop = false; - let isPreset = false; - let manuallyAdjusted = false; + // Iterate over each item in the offer. for (const item of offerItems) { - // Armor insert, skip - we dont factor these into an items price + // Skip over armour inserts as those are not factored into item prices. if (this.itemHelper.isOfBaseclass(item._tpl, BaseClasses.BUILT_IN_INSERTS)) { continue; } - // Get dynamic price, fallback to handbook price if value of 1 found - let itemPrice = this.getFleaPriceForItem(item._tpl); + price += this.getDynamicItemPrice(item._tpl, desiredCurrency, item, offerItems, isPackOffer); - if (this.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice) - { - itemPrice = this.adjustPriceIfBelowHandbook(itemPrice, item._tpl); - } - - if (this.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher) - { - // Get highest trader price for item, if greater than value found so far, use it - const traderPrice = this.traderHelper.getHighestSellToTraderPrice(item._tpl); - if (traderPrice > itemPrice) - { - itemPrice = traderPrice; - } - } - - // Check if item type is weapon preset, handle differently - const itemDetails = this.itemHelper.getItem(item._tpl); - if (this.presetHelper.isPreset(item.upd?.sptPresetId) && itemDetails[1]._props.weapFireType) - { - itemPrice = this.getWeaponPresetPrice(item, offerItems, itemPrice); - endLoop = true; - isPreset = true; - } - - // Check for existance of manual price adjustment multiplier - const manualPriceMultipler = this.ragfairConfig.dynamic.itemPriceMultiplier[item._tpl]; - if (manualPriceMultipler) - { - manuallyAdjusted = true; - itemPrice *= manualPriceMultipler; - } - - // Multiply dynamic price by quality modifier - const itemQualityModifier = this.itemHelper.getItemQualityModifier(item); - price += itemPrice * itemQualityModifier; - - // Stop loop if weapon preset price function has been run - if (endLoop) + // Check if the item is a weapon preset. + if (item?.upd?.sptPresetId && this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON)) { + // This is a weapon preset, which has it's own price calculation that takes into account the mods in the + // preset. Since we've already calculated the price for the preset entire preset in + // `getDynamicItemPrice`, we can skip the rest of the items in the offer. break; } } - // Check for unreasonable price on singular items - if (offerItems.length === 1 && !manuallyAdjusted) - { - const rootItemDb = this.itemHelper.getItem(rootItem._tpl)[1]; - let unreasonableItemPriceChange: IUnreasonableModPrices; - for (const key of Object.keys(this.ragfairConfig.dynamic.unreasonableModPrices)) - { - if (this.itemHelper.isOfBaseclass(rootItemDb._id, key)) - { - unreasonableItemPriceChange = this.ragfairConfig.dynamic.unreasonableModPrices[key]; + return Math.round(price); + } - break; - } - } - if (unreasonableItemPriceChange?.enabled) + /** + * @param itemTemplateId + * @param desiredCurrency + * @param item + * @param offerItems + * @param isPackOffer + * @returns + */ + public getDynamicItemPrice( + itemTemplateId: string, + desiredCurrency: string, + item?: Item, + offerItems?: Item[], + isPackOffer?: boolean, + ): number + { + let isPreset = false; + let price = this.getFleaPriceForItem(itemTemplateId); + + // Adjust price if below handbook price, based on config. + if (this.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice) + { + price = this.adjustPriceIfBelowHandbook(price, itemTemplateId); + } + + // Use trader price if higher, based on config. + if (this.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher) + { + const traderPrice = this.traderHelper.getHighestSellToTraderPrice(itemTemplateId); + if (traderPrice > price) { - price = this.adjustUnreasonablePrice( - this.databaseServer.getTables().templates.handbook.Items, - unreasonableItemPriceChange, - rootItem._tpl, - price, - ); + price = traderPrice; } } - // Get price multiplier min/max to vary price - const rangeValues = this.getOfferTypeRangeValues(isPreset, isPackOffer); - price = this.randomiseOfferPrice(price, rangeValues); + // Prices for weapon presets are handled differently. + if ( + item?.upd?.sptPresetId + && offerItems + && this.presetHelper.isPresetBaseClass(item.upd.sptPresetId, BaseClasses.WEAPON) + ) + { + price = this.getWeaponPresetPrice(item, offerItems, price); + isPreset = true; + } - // Convert to different currency if desiredCurrency param is not roubles - if (desiredCurrency !== Money.ROUBLES) + // Check for existence of manual price adjustment multiplier + const multiplier = this.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId]; + if (multiplier) + { + price *= multiplier; + } + + // The quality of the item affects the price. + if (item) + { + const qualityModifier = this.itemHelper.getItemQualityModifier(item); + price *= qualityModifier; + } + + // Make adjustments for unreasonably priced items. + for (const baseClassTemplateId of Object.keys(this.ragfairConfig.dynamic.unreasonableModPrices)) + { + if (this.itemHelper.isOfBaseclass(itemTemplateId, baseClassTemplateId)) + { + // Found an unreasonable price type. + const unreasonableModifier: IUnreasonableModPrices = + this.ragfairConfig.dynamic.unreasonableModPrices[baseClassTemplateId]; + + if (unreasonableModifier.enabled) + { + price = this.adjustUnreasonablePrice( + this.databaseServer.getTables().templates.handbook.Items, + unreasonableModifier, + itemTemplateId, + price, + ); + } + } + } + + // Vary the price based on the type of offer. + const range = this.getOfferTypeRangeValues(isPreset, isPackOffer); + price = this.randomiseOfferPrice(price, range); + + // Convert to different currency if required. + const roublesId = Money.ROUBLES; + if (desiredCurrency !== roublesId) { price = this.handbookHelper.fromRUB(price, desiredCurrency); } - // Guard against weird prices if (price < 1) { - price = 1; + return 1; } - return price; } @@ -400,7 +422,7 @@ export class RagfairPriceService implements OnLoad const itemHandbookPrice = this.getStaticPriceForItem(itemTpl); const priceDifferencePercent = this.getPriceDifference(itemHandbookPrice, itemPrice); - // Only adjust price if difference is > a percent AND item price passes threshhold set in config + // Only adjust price if difference is > a percent AND item price passes threshold set in config if ( priceDifferencePercent > this.ragfairConfig.dynamic.offerAdjustment.maxPriceDifferenceBelowHandbookPercent && itemPrice >= this.ragfairConfig.dynamic.offerAdjustment.priceThreshholdRub @@ -408,9 +430,7 @@ export class RagfairPriceService implements OnLoad { // const itemDetails = this.itemHelper.getItem(itemTpl); // this.logger.debug(`item below handbook price ${itemDetails[1]._name} handbook: ${itemHandbookPrice} flea: ${itemPrice} ${priceDifferencePercent}%`); - itemPrice = Math.round( - itemHandbookPrice * this.ragfairConfig.dynamic.offerAdjustment.handbookPriceMultipier, - ); + return Math.round(itemHandbookPrice * this.ragfairConfig.dynamic.offerAdjustment.handbookPriceMultipier); } return itemPrice; diff --git a/project/src/services/mod/CustomItemService.ts b/project/src/services/mod/CustomItemService.ts index 2f5954d5..5018a0d9 100644 --- a/project/src/services/mod/CustomItemService.ts +++ b/project/src/services/mod/CustomItemService.ts @@ -72,7 +72,7 @@ export class CustomItemService this.addToItemsDb(newItemId, itemClone); - this.addToHandbookDb(newItemId, newItemDetails.handbookParentId, newItemDetails.fleaPriceRoubles); + this.addToHandbookDb(newItemId, newItemDetails.handbookParentId, newItemDetails.handbookPriceRoubles); this.addToLocaleDbs(newItemDetails.locales, newItemId); @@ -116,7 +116,7 @@ export class CustomItemService this.addToItemsDb(newItem._id, newItem); - this.addToHandbookDb(newItem._id, newItemDetails.handbookParentId, newItemDetails.fleaPriceRoubles); + this.addToHandbookDb(newItem._id, newItemDetails.handbookParentId, newItemDetails.handbookPriceRoubles); this.addToLocaleDbs(newItemDetails.locales, newItem._id); diff --git a/project/src/utils/App.ts b/project/src/utils/App.ts index 9b51b1aa..e3152ebb 100644 --- a/project/src/utils/App.ts +++ b/project/src/utils/App.ts @@ -7,6 +7,7 @@ import { ConfigTypes } from "@spt-aki/models/enums/ConfigTypes"; import { ICoreConfig } from "@spt-aki/models/spt/config/ICoreConfig"; import { ILogger } from "@spt-aki/models/spt/utils/ILogger"; import { ConfigServer } from "@spt-aki/servers/ConfigServer"; +import { HttpServer } from "@spt-aki/servers/HttpServer"; import { LocalisationService } from "@spt-aki/services/LocalisationService"; import { EncodingUtil } from "@spt-aki/utils/EncodingUtil"; import { TimeUtil } from "@spt-aki/utils/TimeUtil"; @@ -23,6 +24,7 @@ export class App @inject("LocalisationService") protected localisationService: LocalisationService, @inject("ConfigServer") protected configServer: ConfigServer, @inject("EncodingUtil") protected encodingUtil: EncodingUtil, + @inject("HttpServer") protected httpServer: HttpServer, @injectAll("OnLoad") protected onLoadComponents: OnLoad[], @injectAll("OnUpdate") protected onUpdateComponents: OnUpdate[], ) @@ -40,15 +42,15 @@ export class App this.logger.debug(`RAM: ${(os.totalmem() / 1024 / 1024 / 1024).toFixed(2)}GB`); this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.argv[0])}`); this.logger.debug(`PATH: ${this.encodingUtil.toBase64(process.execPath)}`); - this.logger.debug(`Server: ${this.coreConfig.akiVersion}`); - if (this.coreConfig.buildTime) + this.logger.debug(`Server: ${globalThis.G_AKIVERSION || this.coreConfig.akiVersion}`); + if (globalThis.G_BUILDTIME) { - this.logger.debug(`Date: ${this.coreConfig.buildTime}`); + this.logger.debug(`Date: ${globalThis.G_BUILDTIME}`); } - if (this.coreConfig.commit) + if (globalThis.G_COMMIT) { - this.logger.debug(`Commit: ${this.coreConfig.commit}`); + this.logger.debug(`Commit: ${globalThis.G_COMMIT}`); } for (const onLoad of this.onLoadComponents) @@ -64,6 +66,12 @@ export class App protected async update(onUpdateComponents: OnUpdate[]): Promise { + // If the server has failed to start, skip any update calls + if (!this.httpServer.isStarted()) + { + return; + } + for (const updateable of onUpdateComponents) { let success = false; diff --git a/project/src/utils/CompareUtil.ts b/project/src/utils/CompareUtil.ts new file mode 100644 index 00000000..80b32053 --- /dev/null +++ b/project/src/utils/CompareUtil.ts @@ -0,0 +1,62 @@ +import { injectable } from "tsyringe"; + +@injectable() +export class CompareUtil +{ + private static typesToCheckAgainst = new Set([ + "string", + "number", + "boolean", + "bigint", + "symbol", + "undefined", + "null", + ]); + + /** + * This function does an object comparison, equivalent to applying reflections + * and scanning for all possible properties including arrays. + * @param v1 value 1 to compare + * @param v2 value 2 to compare + * @returns true if equal, false if not + */ + public recursiveCompare(v1: any, v2: any): boolean + { + const typeOfv1 = typeof v1; + const typeOfv2 = typeof v2; + if (CompareUtil.typesToCheckAgainst.has(typeOfv1)) + { + return v1 === v2; + } + if (typeOfv1 === "object" && typeOfv2 === "object") + { + if (Array.isArray(v1)) + { + if (!Array.isArray(v2)) + { + return false; + } + const arr1 = v1 as Array; + const arr2 = v2 as Array; + if (arr1.length !== arr2.length) + { + return false; + } + return arr1.every((vOf1) => arr2.find((vOf2) => this.recursiveCompare(vOf1, vOf2))); + } + for (const propOf1 in v1) + { + if (v2[propOf1] === undefined) + { + return false; + } + return this.recursiveCompare(v1[propOf1], v2[propOf1]); + } + } + if (typeOfv1 === typeOfv2) + { + return v1 === v2; + } + throw new Error(`could not detect type match for ${typeOfv1} and ${typeOfv2}`); + } +} diff --git a/project/src/utils/DatabaseImporter.ts b/project/src/utils/DatabaseImporter.ts index 78a65150..699f04b9 100644 --- a/project/src/utils/DatabaseImporter.ts +++ b/project/src/utils/DatabaseImporter.ts @@ -134,7 +134,7 @@ export class DatabaseImporter implements OnLoad try { const finalPath = filePathAndName.replace(this.filepath, "").replace(".json", ""); - let tempObject; + let tempObject: any; for (const prop of finalPath.split("/")) { if (!tempObject) diff --git a/project/src/utils/RagfairOfferHolder.ts b/project/src/utils/RagfairOfferHolder.ts index 84dd6b09..aa806efa 100644 --- a/project/src/utils/RagfairOfferHolder.ts +++ b/project/src/utils/RagfairOfferHolder.ts @@ -1,3 +1,4 @@ +import { RagfairServerHelper } from "@spt-aki/helpers/RagfairServerHelper"; import { IRagfairOffer } from "@spt-aki/models/eft/ragfair/IRagfairOffer"; export class RagfairOfferHolder @@ -6,7 +7,7 @@ export class RagfairOfferHolder protected offersByTemplate: Map>; protected offersByTrader: Map>; - constructor() + constructor(protected maxOffersPerTemplate: number, protected ragfairServerHelper: RagfairServerHelper) { this.offersById = new Map(); this.offersByTemplate = new Map(); @@ -62,6 +63,15 @@ export class RagfairOfferHolder const trader = offer.user.id; const offerId = offer._id; const itemTpl = offer.items[0]._tpl; + // If its an NPC PMC offer AND we have already reached the maximum amount of possible offers + // for this template, just dont add in more + if ( + !(this.ragfairServerHelper.isTrader(trader) || this.ragfairServerHelper.isPlayer(trader)) + && this.getOffersByTemplate(itemTpl)?.length >= this.maxOffersPerTemplate + ) + { + return; + } this.offersById.set(offerId, offer); this.addOfferByTrader(trader, offer); this.addOfferByTemplates(itemTpl, offer); @@ -76,7 +86,16 @@ export class RagfairOfferHolder if (this.offersById.has(offer._id)) { this.offersById.delete(offer._id); - this.offersByTrader.get(offer.user.id).delete(offer._id); + const traderOffers = this.offersByTrader.get(offer.user.id); + traderOffers.delete(offer._id); + // This was causing a memory leak, we need to make sure that we remove + // the user ID from the cached offers after they dont have anything else + // on the flea placed. We regenerate the ID for the NPC users, making it + // continously grow otherwise + if (traderOffers.size === 0) + { + this.offersByTrader.delete(offer.user.id); + } this.offersByTemplate.get(offer.items[0]._tpl).delete(offer._id); } } diff --git a/project/src/utils/Watermark.ts b/project/src/utils/Watermark.ts index 91edd475..b3a9f77e 100644 --- a/project/src/utils/Watermark.ts +++ b/project/src/utils/Watermark.ts @@ -108,9 +108,10 @@ export class Watermark */ public getVersionTag(withEftVersion = false): string { + const akiVersion = globalThis.G_AKIVERSION || this.akiConfig.akiVersion; const versionTag = (globalThis.G_DEBUG_CONFIGURATION) - ? `${this.akiConfig.akiVersion} - ${this.localisationService.getText("bleeding_edge_build")}` - : this.akiConfig.akiVersion; + ? `${akiVersion} - ${this.localisationService.getText("bleeding_edge_build")}` + : akiVersion; if (withEftVersion) { @@ -128,9 +129,10 @@ export class Watermark */ public getInGameVersionLabel(): string { + const akiVersion = globalThis.G_AKIVERSION || this.akiConfig.akiVersion; const versionTag = (globalThis.G_DEBUG_CONFIGURATION) - ? `${this.akiConfig.akiVersion} - BLEEDINGEDGE ${this.akiConfig.commit?.slice(0, 6) ?? ""}` - : `${this.akiConfig.akiVersion} - ${this.akiConfig.commit?.slice(0, 6) ?? ""}`; + ? `${akiVersion} - BLEEDINGEDGE ${globalThis.G_COMMIT?.slice(0, 6) ?? ""}` + : `${akiVersion} - ${globalThis.G_COMMIT?.slice(0, 6) ?? ""}`; return `${this.akiConfig.projectName} ${versionTag}`; } diff --git a/project/src/utils/logging/AbstractWinstonLogger.ts b/project/src/utils/logging/AbstractWinstonLogger.ts index 19071d6e..86a6975b 100644 --- a/project/src/utils/logging/AbstractWinstonLogger.ts +++ b/project/src/utils/logging/AbstractWinstonLogger.ts @@ -70,6 +70,7 @@ export abstract class AbstractWinstonLogger implements ILogger filename: this.filePath, datePattern: "YYYY-MM-DD", zippedArchive: true, + frequency: this.getLogFrequency(), maxSize: this.getLogMaxSize(), maxFiles: this.getLogMaxFiles(), format: format.combine( @@ -108,6 +109,11 @@ export abstract class AbstractWinstonLogger implements ILogger protected abstract getFileName(): string; + protected getLogFrequency(): string + { + return "3h"; + } + protected getLogMaxSize(): string { return "5m"; diff --git a/project/tests/__factories__/ProfileInsurance.factory.ts b/project/tests/__factories__/ProfileInsurance.factory.ts index 83ea5629..66679c11 100644 --- a/project/tests/__factories__/ProfileInsurance.factory.ts +++ b/project/tests/__factories__/ProfileInsurance.factory.ts @@ -24,7 +24,7 @@ export class ProfileInsuranceFactory } /** - * Adjusts the scheduledTime and messageContent.systemData.date and messageContent.systemData.time, otherwise the + * Adjusts the scheduledTime, messageContent.systemData.date, and messageContent.systemData.time, otherwise the * dates in the original fixture will likely be expired. */ public adjustPackageDates(dateInput?: DateInput): this @@ -45,8 +45,8 @@ export class ProfileInsuranceFactory } insurance.scheduledTime = date; - insurance.messageContent.systemData.date = format(date, "MM.dd.yyyy"); - insurance.messageContent.systemData.time = format(date, "HH:mm"); + insurance.systemData.date = format(date, "MM.dd.yyyy"); + insurance.systemData.time = format(date, "HH:mm"); return insurance; }); diff --git a/project/tests/__fixture__/profileInsurance.fixture.ts b/project/tests/__fixture__/profileInsurance.fixture.ts index dd26a560..348194e0 100644 --- a/project/tests/__fixture__/profileInsurance.fixture.ts +++ b/project/tests/__fixture__/profileInsurance.fixture.ts @@ -1,747 +1,1388 @@ import { Insurance } from "@spt-aki/models/eft/profile/IAkiProfile"; export const profileInsuranceFixture: Insurance[] = [{ - scheduledTime: 1698945140, - traderId: "54cb50c76803fa8b248b4571", // Prapor - messageContent: { - templateId: "58fe0e4586f774728248ca13 4", - type: 8, - maxStorageTime: 345600, - text: "", - profileChangeEvents: [], - systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, - }, + scheduledTime: 1712950044.4, + traderId: "54cb50c76803fa8b248b4571", + maxStorageTime: 345600, + systemData: { date: "11.04.2024", time: "18:59", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e4586f774728248ca13 0", items: [{ - _id: "3679078e05f5b14466d6a730", - _tpl: "5d6d3716a4b9361bc8618872", - parentId: "5fe49444ae6628187a2e77b8", + _id: "35111c9b72a87b6b7d95ad35", + _tpl: "58948c8e86f77409493f7266", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 55, MaxDurability: 55 } }, + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "911a0f04d5d9c7e239807ae0", - _tpl: "5644bd2b4bdc2d3b4c8b4572", - parentId: "5fe49444ae6628187a2e77b8", + _id: "d45436a159654f43ca3aa52f", + _tpl: "5580223e4bdc2d1c128b457f", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 97.7862549, MaxDurability: 100 } }, + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, }, { - _id: "695b13896108f765e8985698", - _tpl: "5648a69d4bdc2ded0b8b457b", - parentId: "5fe49444ae6628187a2e77b8", + _id: "2c60ad9b6051f059ab796aa6", + _tpl: "5a7ae0c351dfba0017554310", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, { + _id: "a5c86cef7d25f57bf0fb593c", + _tpl: "5b432f3d5acfc4704b4a1dfb", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "bb49d6ceb3e87d8563a06455", - _tpl: "5df8a4d786f77412672a1e3b", - parentId: "5fe49444ae6628187a2e77b8", + _id: "8ac63abcbaf95d09a4d50c02", + _tpl: "5ea17ca01412a1425304d1c0", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "631f8492de748dec852f7ddf", - _tpl: "64abd93857958b4249003418", - parentId: "5fe49444ae6628187a2e77b8", + _id: "33c99e86f72af509da01dc9a", + _tpl: "657f9a55c6679fefb3051e19", + parentId: "8ac63abcbaf95d09a4d50c02", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, { + _id: "426902ae3d7efa5f8c78acf7", + _tpl: "657f9a94ada5fadd1f07a589", + parentId: "8ac63abcbaf95d09a4d50c02", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, { + _id: "5d2be23efb34d0d1da9d3701", + _tpl: "603648ff5a45383c122086ac", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 49.2865, MaxDurability: 60 } }, - }, { - _id: "a2b0c716162c5e31ec28c55a", - _tpl: "5a16b8a9fcdbcb00165aa6ca", - parentId: "3679078e05f5b14466d6a730", - slotId: "mod_nvg", upd: { StackObjectsCount: 1 }, }, { - _id: "dc565f750342cb2d19eeda06", - _tpl: "5d6d3be5a4b9361bc73bc763", - parentId: "3679078e05f5b14466d6a730", - slotId: "mod_equipment_001", - upd: { StackObjectsCount: 1, Repairable: { Durability: 29.33, MaxDurability: 29.33 } }, - }, { - _id: "e9ff62601669d9e2ea9c2fbb", - _tpl: "5d6d3943a4b9360dbc46d0cc", - parentId: "3679078e05f5b14466d6a730", - slotId: "mod_equipment_002", + _id: "9f601faab37dcc58190898ac", + _tpl: "618bb76513f5097c8d5aa2d5", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "ac134d7cf6c9d8e25edd0015", - _tpl: "5c11046cd174af02a012e42b", - parentId: "a2b0c716162c5e31ec28c55a", - slotId: "mod_nvg", + _id: "f74d377063e65d350e0099be", + _tpl: "5c0e5bab86f77461f55ed1f3", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "22274b895ecc80d51c3cba1c", - _tpl: "5c110624d174af029e69734c", - parentId: "ac134d7cf6c9d8e25edd0015", - slotId: "mod_nvg", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 }, Togglable: { On: true } }, + _id: "0ab2a81fc507ac846f43b15f", + _tpl: "6571b27a6d84a2b8b6007f92", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 50.88512, MaxDurability: 52 } }, }, { - _id: "c9278dd8251e99578bf7a274", - _tpl: "59c6633186f7740cf0493bb9", - parentId: "911a0f04d5d9c7e239807ae0", - slotId: "mod_gas_block", + _id: "2ca1b6606d918483ed6b70a5", + _tpl: "6571baa74cb80d995d0a1490", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 49, MaxDurability: 52 } }, + }, { + _id: "5658a9d10f9d44112a991561", + _tpl: "6571baac6d84a2b8b6007fa3", + parentId: "f74d377063e65d350e0099be", + slotId: "Soft_armor_left", + upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, + }, { + _id: "8d0ba4d12fa601312b71d3d7", + _tpl: "6571bab0f41985531a038091", + parentId: "f74d377063e65d350e0099be", + slotId: "soft_armor_right", + upd: { Repairable: { Durability: 8, MaxDurability: 8 } }, + }, { + _id: "45d19bbff6d42c8f781abb38", + _tpl: "6571babb4076795e5e07383f", + parentId: "f74d377063e65d350e0099be", + slotId: "Collar", + upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, + }, { + _id: "cf2ba30bab4d8e80393a8ffe", + _tpl: "6571bac34076795e5e073843", + parentId: "f74d377063e65d350e0099be", + slotId: "Groin", + upd: { Repairable: { Durability: 10, MaxDurability: 10 } }, + }, { + _id: "a3f866e60ccd9c29e77eb5ef", + _tpl: "6571babf4cb80d995d0a1494", + parentId: "f74d377063e65d350e0099be", + slotId: "Groin_back", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, { + _id: "a3287a706e1b77b44db82fa1", + _tpl: "5aa2ba71e5b5b000137b758f", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "677c209ebb45445ebb42c405", - _tpl: "5649ab884bdc2ded0b8b457f", - parentId: "911a0f04d5d9c7e239807ae0", - slotId: "mod_muzzle", + _id: "c6ad1be7e8401755de69d6a0", + _tpl: "5d6d2ef3a4b93618084f58bd", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "8ada5c9cc26585281577c6eb", - _tpl: "5649ae4a4bdc2d1b2b8b4588", - parentId: "911a0f04d5d9c7e239807ae0", + _id: "7c42d3dce0ddbc4806bce48b", + _tpl: "5894a51286f77426d13baf02", + parentId: "35111c9b72a87b6b7d95ad35", slotId: "mod_pistol_grip", - upd: { StackObjectsCount: 1 }, + upd: {}, }, { - _id: "4bd10f89836fd9f86aedcac1", - _tpl: "5649af094bdc2df8348b4586", - parentId: "911a0f04d5d9c7e239807ae0", + _id: "10b97872c5f4e0e1949a0369", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_magazine", + }, { + _id: "a6cd9986dde4cabddcd2dce2", + _tpl: "5894a5b586f77426d2590767", + parentId: "35111c9b72a87b6b7d95ad35", slotId: "mod_reciever", - upd: { StackObjectsCount: 1 }, + upd: {}, }, { - _id: "8b1327270791b142ac341b03", - _tpl: "5649d9a14bdc2d79388b4580", - parentId: "911a0f04d5d9c7e239807ae0", + _id: "b65635b515712f990fdcc201", + _tpl: "58ac1bf086f77420ed183f9f", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_stock", + }, { + _id: "0e11045873efe3625695c1ae", + _tpl: "5c5db6b32e221600102611a0", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "35111c9b72a87b6b7d95ad35", + slotId: "mod_charge", + }, { + _id: "94c4161abe8bf654fb986063", + _tpl: "57adff4f24597737f373b6e6", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_scope", + }, { + _id: "9b284ccfd0d535acec1ff58b", + _tpl: "5c5db5c62e22160012542255", + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_barrel", + upd: {}, + }, { + _id: "d730caa83a11fd01250a7261", + _tpl: "5c5db63a2e2216000f1b284a", + parentId: "a6cd9986dde4cabddcd2dce2", + slotId: "mod_handguard", + upd: {}, + }, { + _id: "24291c7bcf91e362adb6d68b", + _tpl: "5fb6564947ce63734e3fa1da", + parentId: "a6cd9986dde4cabddcd2dce2", slotId: "mod_sight_rear", upd: { StackObjectsCount: 1 }, }, { - _id: "566335b3df586f34b47f5e35", - _tpl: "5649b2314bdc2d79388b4576", - parentId: "911a0f04d5d9c7e239807ae0", - slotId: "mod_stock", - upd: { StackObjectsCount: 1 }, - }, { - _id: "da8cde1b3024c336f6e06152", - _tpl: "55d482194bdc2d1d4e8b456b", - parentId: "911a0f04d5d9c7e239807ae0", - slotId: "mod_magazine", + _id: "0d98fd0769cce8e473bbe540", + _tpl: "58d2664f86f7747fec5834f6", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "94c4161abe8bf654fb986063", + slotId: "mod_scope", }, { - _id: "1e0b177df108c0c117028812", - _tpl: "57cffddc24597763133760c6", - parentId: "c9278dd8251e99578bf7a274", - slotId: "mod_handguard", + _id: "11b174510f039e8217fbd202", + _tpl: "58d268fc86f774111273f8c2", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "0d98fd0769cce8e473bbe540", + slotId: "mod_scope", + }, { + _id: "c435230e530574b1d7c32300", + _tpl: "5c7e8fab2e22165df16b889b", + parentId: "9b284ccfd0d535acec1ff58b", + slotId: "mod_muzzle", + upd: {}, + }, { + _id: "15666fe6fd2d95206612e418", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_000", upd: { StackObjectsCount: 1 }, }, { - _id: "bc041c0011d76f714b898400", - _tpl: "57cffcd624597763133760c5", - parentId: "1e0b177df108c0c117028812", + _id: "a54de8b9014eee71fdf1d01d", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_001", + upd: { StackObjectsCount: 1 }, + }, { + _id: "c34555bc95a9a7a23150a36f", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_002", + upd: { StackObjectsCount: 1 }, + }, { + _id: "91cae4ae30d1366b87158238", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", slotId: "mod_mount_003", upd: { StackObjectsCount: 1 }, }, { - _id: "9f8d7880a6e0a47a211ec5d3", - _tpl: "58491f3324597764bc48fa02", - parentId: "8b1327270791b142ac341b03", - slotId: "mod_scope", + _id: "48f23df4509164cf397b9ab5", + _tpl: "6269220d70b6c02e665f2635", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_004", upd: { StackObjectsCount: 1 }, }, { - _id: "402b4086535a50ef7d9cef88", - _tpl: "5649be884bdc2d79388b4577", - parentId: "566335b3df586f34b47f5e35", - slotId: "mod_stock", + _id: "a55f05f689978ac65c7da654", + _tpl: "5b7be4895acfc400170e2dd5", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_foregrip", + upd: {}, + }, { + _id: "8ae4ea81a2d6074162d87a9c", + _tpl: "5b7be47f5acfc400170e2dd2", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_005", + upd: {}, + }, { + _id: "312cc0f6687963305457235e", + _tpl: "5b7be47f5acfc400170e2dd2", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_mount_006", + upd: {}, + }, { + _id: "e1e5aaf474b7282a52ac9a14", + _tpl: "5fb6567747ce63734e3fa1dc", + parentId: "d730caa83a11fd01250a7261", + slotId: "mod_sight_front", upd: { StackObjectsCount: 1 }, }, { - _id: "db2ef9442178910eba985b51", - _tpl: "58d2946386f774496974c37e", - parentId: "402b4086535a50ef7d9cef88", - slotId: "mod_stock_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "3c32b7d47ad80e83749fa906", - _tpl: "58d2912286f7744e27117493", - parentId: "db2ef9442178910eba985b51", - slotId: "mod_stock", - upd: { StackObjectsCount: 1 }, - }, { - _id: "574a9b5535585255cde19570", - _tpl: "55d482194bdc2d1d4e8b456b", - parentId: "695b13896108f765e8985698", - slotId: "1", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + _id: "bb9a34648e08f005db5d7484", + _tpl: "5cc9c20cd7f00c001336c65d", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "15666fe6fd2d95206612e418", + slotId: "mod_tactical", }, { - _id: "696835b2badfb96623ea887c", - _tpl: "55d482194bdc2d1d4e8b456b", - parentId: "695b13896108f765e8985698", + _id: "dd9ac99d3ea4c9656221bcc9", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a54de8b9014eee71fdf1d01d", + slotId: "mod_tactical", + }, { + _id: "b22748de8da5f3c1362dd8e0", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "c34555bc95a9a7a23150a36f", + slotId: "mod_tactical", + }, { + _id: "e3cc1be8954c4889f94b435a", + _tpl: "5cc9c20cd7f00c001336c65d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "91cae4ae30d1366b87158238", + slotId: "mod_tactical", + }, { + _id: "e73f05be5a306168e847da82", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "48f23df4509164cf397b9ab5", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, { + _id: "847cf35ec92d8af8e4814ea8", + _tpl: "5c1cd46f2e22164bef5cfedb", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "a55f05f689978ac65c7da654", + slotId: "mod_foregrip", + }, { + _id: "bb4b7a4475fea0f0135305f6", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "8ae4ea81a2d6074162d87a9c", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, { + _id: "d0ac8e688a0bb17668589909", + _tpl: "5cc9c20cd7f00c001336c65d", + parentId: "312cc0f6687963305457235e", + slotId: "mod_tactical", + upd: { StackObjectsCount: 1 }, + }, { + _id: "5dbcf8cbbb3f8ef669836320", + _tpl: "5c793fc42e221600114ca25d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b65635b515712f990fdcc201", + slotId: "mod_stock", + }, { + _id: "f996645c809968f8033593a6", + _tpl: "5fc2369685fd526b824a5713", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5dbcf8cbbb3f8ef669836320", + slotId: "mod_stock_000", + }, { + _id: "7d959c20811fdc440387f0a4", + _tpl: "55d447bb4bdc2d892f8b456f", + parentId: "d45436a159654f43ca3aa52f", + slotId: "mod_barrel", + upd: {}, + }, { + _id: "16969c588bd20e223d93e65a", + _tpl: "611a31ce5b7ffe001b4649d1", + parentId: "d45436a159654f43ca3aa52f", + slotId: "mod_stock", + upd: {}, + }, { + _id: "d3a31aa632d852bfe57d7aca", + _tpl: "5a6b5f868dc32e000a311389", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_barrel", + upd: {}, + }, { + _id: "fdba343644672594e7c73f47", + _tpl: "5a7b4960e899ef197b331a2d", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_pistol_grip", + upd: {}, + }, { + _id: "5f47943e00d184b3c8f9c2b5", + _tpl: "5a6f5e048dc32e00094b97da", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_reciever", + upd: {}, + }, { + _id: "f616853cb3b860d670252e66", + _tpl: "5a718b548dc32e000d46d262", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_magazine", + upd: {}, + }, { + _id: "5153ee12f6d4abc4856dd4ae", + _tpl: "5a7ad74e51dfba0015068f45", + parentId: "2c60ad9b6051f059ab796aa6", + slotId: "mod_tactical", + upd: {}, + }, { + _id: "aa5dc438d849a311e335667b", + _tpl: "5a7d9122159bd4001438dbf4", + parentId: "5f47943e00d184b3c8f9c2b5", + slotId: "mod_sight_rear", + upd: {}, + }, { + _id: "79a1dfa8bff1b7ca118d6b0f", + _tpl: "5a7d90eb159bd400165484f1", + parentId: "5f47943e00d184b3c8f9c2b5", + slotId: "mod_sight_front", + upd: {}, + }, { + _id: "e784a6d774f9a885bf5ed847", + _tpl: "5a7b483fe899ef0016170d15", + parentId: "5153ee12f6d4abc4856dd4ae", + slotId: "mod_tactical", + upd: {}, + }, { + _id: "fd79789b0e394e2cc1299ab1", + _tpl: "5c5db6742e2216000f1b2852", + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "1", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "a19f5e338bfd32f1c1f3fb73", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", slotId: "2", location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "c2d5e23c7886e8ff02010731", - _tpl: "55d482194bdc2d1d4e8b456b", - parentId: "695b13896108f765e8985698", + _id: "9e709808929c226f7bdbf57a", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", slotId: "3", location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "306de2f475a559610a4f6f1d", - _tpl: "55d482194bdc2d1d4e8b456b", - parentId: "695b13896108f765e8985698", + _id: "9fe70bf25a2db7f8c1b23502", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", slotId: "4", location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "eb0445b49a97e84e27d47f3c", - _tpl: "5aa2ba71e5b5b000137b758f", - parentId: "695b13896108f765e8985698", + _id: "4519dc962deebb2dbfc9e70c", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "5", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "a94275912f1cbcd483563916", + _tpl: "5c5db6742e2216000f1b2852", + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "6", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "7f2ae8c0685bf3a2195185dd", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "7", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "53a9f3dc5c08cbd02ff31b12", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "8", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "e0ab45585b1a874dbaa68fb3", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "9", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "3f66f7abde039a848f8b4cf0", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5d2be23efb34d0d1da9d3701", + slotId: "10", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "04a202a45f8a39b61a58a05a", + _tpl: "544a5caa4bdc2d1a388b4568", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "d5f6e03c07ede944e89fb407", + _tpl: "6570e83223c1f638ef0b0ede", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, { + _id: "5433cbf0f07a68651e888c74", + _tpl: "6570e87c23c1f638ef0b0ee2", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, { + _id: "da91bed43f688a80b627ad4d", + _tpl: "6570e90b3a5689d85f08db97", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Groin", + upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, + }, { + _id: "ad7f524f3de9ad544df8c0b8", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + location: { x: 3, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "0844cf6b7a89c13454b6e3db", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + location: { x: 4, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "c3f58f44366d0a06d29d66ba", + _tpl: "5a38e6bac4a2826c6e06d79b", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + location: { x: 0, y: 4, r: "Horizontal", isSearched: true }, + }, { + _id: "d46e16faba780c68e0600532", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 45, MaxDurability: 45 } }, + location: { x: 3, y: 2, r: "Horizontal", isSearched: true }, + }, { + _id: "26598f88d49198c4a0a9391c", + _tpl: "571a12c42459771f627b58a0", + parentId: "9f601faab37dcc58190898ac", + slotId: "main", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + location: { x: 3, y: 4, r: "Horizontal", isSearched: true }, + }, { + _id: "5ee8e16837809adc34caae00", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, { + _id: "de042f9ebf0fd9ad451033d4", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "04a202a45f8a39b61a58a05a", + slotId: "Back_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, { + _id: "03de471c2a3faa359aca7486", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "1", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "091c85804613176da9478edd", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "2", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "5482888e242a98ff154c0ee8", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "3", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "3c8e206a2c2e9b0fee45b56b", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "b2405216e5730f3511884a10", + _tpl: "5ea17ca01412a1425304d1c0", + parentId: "04a202a45f8a39b61a58a05a", slotId: "5", upd: { StackObjectsCount: 1 }, location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, }, { - _id: "fad89a5bdfd23e3248123346", - _tpl: "5fc5396e900b1d5091531e72", - parentId: "695b13896108f765e8985698", + _id: "7a0675280dbbad69ce592d74", + _tpl: "657f9a55c6679fefb3051e19", + parentId: "b2405216e5730f3511884a10", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, { + _id: "c0c182942f54d3c183f0e179", + _tpl: "657f9a94ada5fadd1f07a589", + parentId: "b2405216e5730f3511884a10", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 24, MaxDurability: 24 } }, + }, { + _id: "8ec4534a4fe96f89ea88c107", + _tpl: "5c165d832e2216398b5a7e36", + parentId: "04a202a45f8a39b61a58a05a", slotId: "6", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, upd: { StackObjectsCount: 1 }, - }, { - _id: "b16c2a938954cd69c687c51a", - _tpl: "5b4736b986f77405cb415c10", - parentId: "695b13896108f765e8985698", - slotId: "7", location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "a2b3019ac8d340eeb068d429", + _id: "0d91ed3d44881d33b1fd94ec", + _tpl: "5c5db6742e2216000f1b2852", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "04a202a45f8a39b61a58a05a", + slotId: "11", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "f7066fdfeefb29eca1d2dbeb", _tpl: "5ea18c84ecf1982c7712d9a2", - parentId: "695b13896108f765e8985698", - slotId: "10", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 29, MaxDurability: 33 } }, + upd: { StackObjectsCount: 1, Repairable: { Durability: 22, MaxDurability: 25 } }, + parentId: "b2405216e5730f3511884a10", + slotId: "mod_nvg", }, { - _id: "0b3c5d183e8b506d655f85c4", - _tpl: "644a3df63b0b6f03e101e065", - parentId: "fad89a5bdfd23e3248123346", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "757211a0b648fe27b0475ded", - _tpl: "59f8a37386f7747af3328f06", - parentId: "b16c2a938954cd69c687c51a", - slotId: "mod_foregrip", + _id: "ee0ec86e9608abe773175e3a", + _tpl: "5c0558060db834001b735271", + parentId: "f7066fdfeefb29eca1d2dbeb", + slotId: "mod_nvg", upd: { StackObjectsCount: 1 }, }, { - _id: "870a887c63ca30fb15736b3d", - _tpl: "62a1b7fbc30cfa1d366af586", - parentId: "bb49d6ceb3e87d8563a06455", - slotId: "main", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "f3de631a1bb2b74bd0160d9a", - _tpl: "5d6d3be5a4b9361bc73bc763", - parentId: "bb49d6ceb3e87d8563a06455", - slotId: "main", - location: { x: 5, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 22.41, MaxDurability: 22.41 } }, - }, { - _id: "351180f3248d45c71cb2ebdc", - _tpl: "57c44b372459772d2b39b8ce", - parentId: "870a887c63ca30fb15736b3d", - slotId: "main", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "7237f722106866f2df8dc8d1", - _tpl: "56e33680d2720be2748b4576", - parentId: "870a887c63ca30fb15736b3d", - slotId: "main", - location: { x: 0, y: 3, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "d0cf00aff56ea520cdd94330", - _tpl: "57c44dd02459772d2e0ae249", - parentId: "351180f3248d45c71cb2ebdc", - slotId: "mod_muzzle", - upd: { StackObjectsCount: 1 }, - }, { - _id: "5119653b2c66d57ee219e26f", - _tpl: "57c44f4f2459772d2c627113", - parentId: "351180f3248d45c71cb2ebdc", - slotId: "mod_reciever", - upd: { StackObjectsCount: 1 }, - }, { - _id: "ed1ac0183a8af587110aa74e", - _tpl: "5a9e81fba2750c00164f6b11", - parentId: "351180f3248d45c71cb2ebdc", + _id: "0515d1e589fd626b504e59cd", + _tpl: "5a38ee51c4a282000c5a955c", + parentId: "c3f58f44366d0a06d29d66ba", slotId: "mod_magazine", - upd: { StackObjectsCount: 1 }, + upd: {}, }, { - _id: "310a7d1bb07ae0e522f3f8e3", - _tpl: "5a69a2ed8dc32e000d46d1f1", - parentId: "351180f3248d45c71cb2ebdc", - slotId: "mod_pistol_grip", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "8a7e3489197b3b98126447fd", - _tpl: "6130ca3fd92c473c77020dbd", - parentId: "351180f3248d45c71cb2ebdc", - slotId: "mod_charge", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "e818616e11ae07aa05388759", - _tpl: "5dff8db859400025ea5150d4", - parentId: "351180f3248d45c71cb2ebdc", - slotId: "mod_mount_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "768812984debf2756bece089", - _tpl: "57c44e7b2459772d28133248", - parentId: "d0cf00aff56ea520cdd94330", - slotId: "mod_sight_rear", - upd: { StackObjectsCount: 1 }, - }, { - _id: "67c610585ed668baf4604931", - _tpl: "59eb7ebe86f7740b373438ce", - parentId: "d0cf00aff56ea520cdd94330", - slotId: "mod_mount_000", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "80e9dffa49bfe263ab0128c7", - _tpl: "6267c6396b642f77f56f5c1c", - parentId: "67c610585ed668baf4604931", - slotId: "mod_tactical_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "dee323443ce23ba8c54b9f1c", - _tpl: "5cc9c20cd7f00c001336c65d", - parentId: "67c610585ed668baf4604931", - slotId: "mod_tactical_001", - upd: { StackObjectsCount: 1 }, - }, { - _id: "3008088022dd55f1c99e5a32", - _tpl: "5c1cd46f2e22164bef5cfedb", - parentId: "67c610585ed668baf4604931", - slotId: "mod_foregrip", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "71e9f8d005c72940d857fe64", - _tpl: "59d790f486f77403cb06aec6", - parentId: "80e9dffa49bfe263ab0128c7", - slotId: "mod_flashlight", - upd: { StackObjectsCount: 1 }, - }, { - _id: "8c610c6cc67115a5fc1662ff", - _tpl: "56eabf3bd2720b75698b4569", - parentId: "310a7d1bb07ae0e522f3f8e3", - slotId: "mod_stock_000", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "9bf01177f0c1e346b2d65373", - _tpl: "58d2912286f7744e27117493", - parentId: "8c610c6cc67115a5fc1662ff", + _id: "cb30ae6f997a2e6d119f2186", + _tpl: "5a38ef1fc4a282000b1521f6", + parentId: "c3f58f44366d0a06d29d66ba", slotId: "mod_stock", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + upd: { Foldable: { Folded: true } }, }, { - _id: "7dd43ffa6e03c2da6cddc56e", - _tpl: "6171407e50224f204c1da3c5", - parentId: "e818616e11ae07aa05388759", - slotId: "mod_scope", - upd: { StackObjectsCount: 1 }, + _id: "be57a04835a8c1ae85811949", + _tpl: "5a38eecdc4a282329a73b512", + parentId: "cb30ae6f997a2e6d119f2186", + slotId: "mod_pistol_grip", + upd: {}, }, { - _id: "fa9da4ccf3630cb173c293f9", - _tpl: "5b3b99475acfc432ff4dcbee", - parentId: "7dd43ffa6e03c2da6cddc56e", - slotId: "mod_scope_000", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "fd6ef6e377e6280ca9386dbc", + _tpl: "571a26d524597720680fbe8a", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_barrel", + upd: {}, }, { - _id: "6e2727806fb12e12123e9a57", - _tpl: "616554fe50224f204c1da2aa", - parentId: "7dd43ffa6e03c2da6cddc56e", - slotId: "mod_scope_001", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "5c40aff0d1c5d4f206123b83", + _tpl: "571a282c2459771fb2755a69", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_pistol_grip", + upd: {}, }, { - _id: "2c868d4676adc934f897e9a7", - _tpl: "61605d88ffa6e502ac5e7eeb", - parentId: "7dd43ffa6e03c2da6cddc56e", - slotId: "mod_scope_002", - upd: { StackObjectsCount: 1 }, + _id: "34b2c7cf0f6b8f484411cebf", + _tpl: "571a29dc2459771fb2755a6a", + parentId: "26598f88d49198c4a0a9391c", + slotId: "mod_magazine", + upd: {}, }, { - _id: "1b159fdc14c350f8a4a7e19e", - _tpl: "58d39b0386f77443380bf13c", - parentId: "6e2727806fb12e12123e9a57", - slotId: "mod_scope", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "9932dd0e1339053e27d54a41", + _tpl: "654a4dea7c17dec2f50cc86a", + parentId: "f74d377063e65d350e0099be", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, }, { - _id: "7691790ffc5290da292cab99", - _tpl: "61657230d92c473c770213d7", - parentId: "1b159fdc14c350f8a4a7e19e", - slotId: "mod_scope", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "012a11e7dcb1280a1ab9d2f6", - _tpl: "618168b350224f204c1da4d8", - parentId: "7237f722106866f2df8dc8d1", - slotId: "main", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "38ca7415a458c4d22ba2f3c3", - _tpl: "6130c43c67085e45ef1405a1", - parentId: "012a11e7dcb1280a1ab9d2f6", - slotId: "mod_muzzle", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "c5a0621ebf856ce1b0945efc", - _tpl: "61816fcad92c473c770215cc", - parentId: "012a11e7dcb1280a1ab9d2f6", - slotId: "mod_sight_front", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "a74677b17c1c49edc002df9b", - _tpl: "5dfa3d2b0dee1b22f862eade", - parentId: "38ca7415a458c4d22ba2f3c3", - slotId: "mod_muzzle", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "0f69c261881206320d8f583d", + _tpl: "657b22485f444d6dff0c6c2f", + parentId: "f74d377063e65d350e0099be", + slotId: "Back_plate", + upd: { StackObjectsCount: 1, Repairable: { Durability: 4.681114, MaxDurability: 40 } }, }], }, { - scheduledTime: 1698945140, - traderId: "54cb57776803fa99248b456e", // Therapist - messageContent: { - templateId: "58fe0e3486f77471f772c3f2 2", - type: 8, - maxStorageTime: 518400, - text: "", - profileChangeEvents: [], - systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, - }, + scheduledTime: 1712896726, + traderId: "54cb57776803fa99248b456e", + maxStorageTime: 518400, + systemData: { date: "11.04.2024", time: "19:19", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e3486f77471f772c3f2 3", items: [{ - _id: "5ae1c2b99a0a339adc620148", - _tpl: "5cebec38d7f00c00110a652a", - parentId: "ad018df9da0cbf2726394ef1", - slotId: "mod_mount_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "30f4bcb87bcc4604e27c02c1", - _tpl: "5cc70146e4a949000d73bf6b", - parentId: "ad018df9da0cbf2726394ef1", - slotId: "mod_mount_001", - upd: { StackObjectsCount: 1 }, - }, { - _id: "ad018df9da0cbf2726394ef1", - _tpl: "5cc70102e4a949035e43ba74", - parentId: "3bc4ff5bd99f165dc75cbd25", - slotId: "main", - upd: { StackObjectsCount: 1 }, - location: { x: 3, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "12c243bd6b3e486e61325f81", - _tpl: "5cc82d76e24e8d00134b4b83", - parentId: "5fe49444ae6628187a2e77b8", + _id: "5cfe91bfe022641c19bc8c60", + _tpl: "5aafa857e5b5b00018480968", + upd: { + StackObjectsCount: 1, + sptPresetId: "5ac4ad3686f774181345c3da", + Repairable: { Durability: 98.33, MaxDurability: 98.33 }, + }, + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 99.93771, MaxDurability: 100 } }, }, { - _id: "760652d86ee78eed513e0ad7", - _tpl: "5ab8f39486f7745cd93a1cca", - parentId: "5fe49444ae6628187a2e77b8", + _id: "a5063619e7f4db123ca07fcc", + _tpl: "60db29ce99594040e04c4a27", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, { + _id: "3702c30b6333e28d6a15d62c", + _tpl: "56e0598dd2720bb5668b45a6", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + }, { + _id: "387c9f2b44d2da266f856b31", + _tpl: "6571bde39837cc51b800c212", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "61ab4afefac354dfc64c7874", - _tpl: "5b432d215acfc4771e1c6624", - parentId: "5fe49444ae6628187a2e77b8", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 30, MaxDurability: 30 } }, - }, { - _id: "285e9d9ae196ae4e336cd04f", - _tpl: "5d5d87f786f77427997cfaef", - parentId: "5fe49444ae6628187a2e77b8", - slotId: "hideout", - upd: { StackObjectsCount: 1, Repairable: { Durability: 75, MaxDurability: 80 } }, - }, { - _id: "3bc4ff5bd99f165dc75cbd25", - _tpl: "5f5e467b0bc58666c37e7821", - parentId: "5fe49444ae6628187a2e77b8", + _id: "275f046ea1a7b40046cd54fa", + _tpl: "5b40e4035acfc47a87740943", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "6bf5d8ee81a3c9aec21bbbad", - _tpl: "5d5fca1ea4b93635fd598c07", - parentId: "5fe49444ae6628187a2e77b8", + _id: "f30858ff9924b1fe211dd1f7", + _tpl: "657f95bff92cd718b701550c", + parentId: "275f046ea1a7b40046cd54fa", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 10.3212032, MaxDurability: 18 } }, + }, { + _id: "eec1072ac0cc44984e1ed43b", + _tpl: "657f9605f4c82973640b2358", + parentId: "275f046ea1a7b40046cd54fa", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 13.3160009, MaxDurability: 18 } }, + }, { + _id: "b82495b01ad0bfe5dd7e864d", + _tpl: "5c0e746986f7741453628fe5", + parentId: "d2b3b859f667d4fd8b35bc96", slotId: "hideout", upd: { StackObjectsCount: 1 }, }, { - _id: "2371438cf809b5e483bf5d85", - _tpl: "5cc70093e4a949033c734312", - parentId: "12c243bd6b3e486e61325f81", + _id: "31531773990cd1aefa751db7", + _tpl: "6570df294cc0d2ab1e05ed74", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 31.0571022, MaxDurability: 35 } }, + }, { + _id: "eb8c6c7c671d2a2490454e7c", + _tpl: "6570df9c615f54368b04fca9", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 30.8, MaxDurability: 35 } }, + }, { + _id: "f9cc99048aa37c5a4a837ef9", + _tpl: "5ca20d5986f774331e7c9602", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, { + _id: "bd8a4a3783d80b81cc8655ee", + _tpl: "5aa2ba71e5b5b000137b758f", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, { + _id: "025748ec34dcd1bfb2529537", + _tpl: "5c0d32fcd174af02a1659c75", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, { + _id: "9c552e79f1ae38350afb3723", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5cfe91bfe022641c19bc8c60", slotId: "mod_magazine", - upd: { StackObjectsCount: 1 }, }, { - _id: "7f890346ea5b2cbc68c3170f", - _tpl: "5cc700b9e4a949000f0f0f25", - parentId: "12c243bd6b3e486e61325f81", + _id: "14cb5b7c9789876325670163", + _tpl: "5aaf8e43e5b5b00015693246", + parentId: "5cfe91bfe022641c19bc8c60", slotId: "mod_stock", - upd: { StackObjectsCount: 1 }, + upd: {}, }, { - _id: "12fb79a9c4929009ff8d89e1", - _tpl: "5cc700ede4a949033c734315", - parentId: "12c243bd6b3e486e61325f81", - slotId: "mod_reciever", - upd: { StackObjectsCount: 1 }, - }, { - _id: "d4c5274082ed716e19447f46", - _tpl: "5cc701d7e4a94900100ac4e7", - parentId: "12c243bd6b3e486e61325f81", + _id: "0e4c9e11000589751523a62c", + _tpl: "5addbac75acfc400194dbc56", + parentId: "5cfe91bfe022641c19bc8c60", slotId: "mod_barrel", upd: { StackObjectsCount: 1 }, }, { - _id: "d819dd4d2b13de10e9d6d805", - _tpl: "5cc6ea85e4a949000e1ea3c3", - parentId: "12c243bd6b3e486e61325f81", - slotId: "mod_charge", - upd: { StackObjectsCount: 1 }, - }, { - _id: "fc9a664cacc477c4e725a81a", - _tpl: "5cc700d4e4a949000f0f0f28", - parentId: "7f890346ea5b2cbc68c3170f", - slotId: "mod_stock_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "372891c593cf14e176b93ce2", - _tpl: "5cc7012ae4a949001252b43e", - parentId: "12fb79a9c4929009ff8d89e1", - slotId: "mod_mount_000", - upd: { StackObjectsCount: 1 }, - }, { - _id: "bd196435a57bdc433df1e49d", - _tpl: "5cc7012ae4a949001252b43e", - parentId: "12fb79a9c4929009ff8d89e1", - slotId: "mod_mount_001", - upd: { StackObjectsCount: 1 }, - }, { - _id: "ea3349d29797354d835c2192", - _tpl: "58491f3324597764bc48fa02", - parentId: "12fb79a9c4929009ff8d89e1", - slotId: "mod_scope", + _id: "a63cf65e9646a04944d18106", + _tpl: "5abcbb20d8ce87001773e258", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5cfe91bfe022641c19bc8c60", + slotId: "mod_sight_rear", }, { - _id: "4ccf7c74ca7d2167deb0ae5c", - _tpl: "626becf9582c3e319310b837", - parentId: "372891c593cf14e176b93ce2", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, - }, { - _id: "adfd3640fc93daf21c721ca6", - _tpl: "5cc9c20cd7f00c001336c65d", - parentId: "bd196435a57bdc433df1e49d", - slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, - }, { - _id: "deeb36b1812790b0145d2532", - _tpl: "5a16badafcdbcb001865f72d", - parentId: "61ab4afefac354dfc64c7874", - slotId: "mod_equipment_000", - upd: { StackObjectsCount: 1, Repairable: { Durability: 12, MaxDurability: 25 } }, - }, { - _id: "4c0e0548df904c384569190c", - _tpl: "5ea058e01dbce517f324b3e2", - parentId: "61ab4afefac354dfc64c7874", - slotId: "mod_nvg", - upd: { StackObjectsCount: 1, Repairable: { Durability: 3, MaxDurability: 39 } }, - }, { - _id: "da82c293cabc705b30fef93a", - _tpl: "5a398ab9c4a282000c5a9842", - parentId: "61ab4afefac354dfc64c7874", + _id: "f67388e02546cd97c976d479", + _tpl: "5addbfe15acfc4001a5fc58b", + parentId: "5cfe91bfe022641c19bc8c60", slotId: "mod_mount", + upd: { StackObjectsCount: 1 }, + }, { + _id: "bed3b1a2f866e18743db2a63", + _tpl: "5addbfbb5acfc400194dbcf7", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "14cb5b7c9789876325670163", + slotId: "mod_mount", }, { - _id: "b8fc94611def6e9ba534a8b3", - _tpl: "5a16b8a9fcdbcb00165aa6ca", - parentId: "4c0e0548df904c384569190c", - slotId: "mod_nvg", + _id: "821a4953b87f562b3f435fd7", + _tpl: "5649a2464bdc2d91118b45a8", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "bed3b1a2f866e18743db2a63", + slotId: "mod_scope", }, { - _id: "20d6193c1f399e6326ebbc10", - _tpl: "5a16b93dfcdbcbcae6687261", - parentId: "b8fc94611def6e9ba534a8b3", - slotId: "mod_nvg", + _id: "24813deb9b9a6ec3ca8376ef", + _tpl: "5d10b49bd7ad1a1a560708b0", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "065c4f13b2bd8be266e1e809", - _tpl: "57235b6f24597759bf5a30f1", - parentId: "20d6193c1f399e6326ebbc10", - slotId: "mod_nvg", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 }, Togglable: { On: true } }, - }, { - _id: "1883b955ab202fa099809278", - _tpl: "57d17c5e2459775a5c57d17d", - parentId: "da82c293cabc705b30fef93a", - slotId: "mod_flashlight", - upd: { StackObjectsCount: 1 }, - }, { - _id: "e3c9e50ce31900c950b4ff6f", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "1", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "193259b5eb848af4d036bee5", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "2", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "f97ce69443f63bbe8f8097a7", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "3", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "5d1c154a8abcfa934e477ac4", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "4", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "289f7af841690c5388095477", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "5", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "3e6d578165b61aef9865f677", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "6", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "338682523f8504f97f84f3ab", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "7", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "6d18ac01aa04b16e4f0d5d2f", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "8", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "ac4ed54d61daa0c5219f8522", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "9", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "2460460ef3d3df5c1ce07edb", - _tpl: "5cc70093e4a949033c734312", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "10", - location: { x: 0, y: 0, r: "Vertical", isSearched: true }, - upd: { StackObjectsCount: 1 }, - }, { - _id: "3aeb18aac0b532f34255f162", - _tpl: "5cc70146e4a949000d73bf6b", - parentId: "285e9d9ae196ae4e336cd04f", - slotId: "11", - upd: { StackObjectsCount: 1 }, - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - }, { - _id: "bdb46107abbf1d92edaaf14e", - _tpl: "6272379924e29f06af4d5ecb", - parentId: "3aeb18aac0b532f34255f162", + parentId: "bed3b1a2f866e18743db2a63", slotId: "mod_tactical", - upd: { StackObjectsCount: 1 }, }, { - _id: "0caadd8507a36d9ea871e88e", - _tpl: "5ab8f04f86f774585f4237d8", - parentId: "3bc4ff5bd99f165dc75cbd25", - slotId: "main", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { StackObjectsCount: 1 }, + _id: "4194116ceb7e9e623cba4e89", + _tpl: "609bab8b455afd752b2e6138", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "821a4953b87f562b3f435fd7", + slotId: "mod_scope", }, { - _id: "240046eebc9040c1d7e58611", - _tpl: "5ac66d015acfc400180ae6e4", - parentId: "0caadd8507a36d9ea871e88e", - slotId: "main", - location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, - upd: { - StackObjectsCount: 1, - sptPresetId: "5acf7dfc86f774401e19c390", - Repairable: { Durability: 32, MaxDurability: 59 }, - Foldable: { Folded: true }, - }, - }, { - _id: "70b23c628fa17699d9a71e94", - _tpl: "59c6633186f7740cf0493bb9", - parentId: "240046eebc9040c1d7e58611", - slotId: "mod_gas_block", - upd: { - StackObjectsCount: 1, - sptPresetId: "5acf7dfc86f774401e19c390", - Repairable: { Durability: 32, MaxDurability: 59 }, - }, - }, { - _id: "7cc2e24dc6bc0716bdddc472", - _tpl: "5943ee5a86f77413872d25ec", - parentId: "240046eebc9040c1d7e58611", + _id: "3bd8b76ba1ff8f1cf954af91", + _tpl: "59bffc1f86f77435b128b872", + parentId: "0e4c9e11000589751523a62c", slotId: "mod_muzzle", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, - }, { - _id: "7a51ebbad703082660d59d27", - _tpl: "5649ade84bdc2d1b2b8b4587", - parentId: "240046eebc9040c1d7e58611", - slotId: "mod_pistol_grip", - upd: { - StackObjectsCount: 1, - sptPresetId: "5acf7dfc86f774401e19c390", - Repairable: { Durability: 32, MaxDurability: 59 }, - }, - }, { - _id: "b481bc57436ed9a0c3abe7f3", - _tpl: "5d2c76ed48f03532f2136169", - parentId: "240046eebc9040c1d7e58611", - slotId: "mod_reciever", upd: { StackObjectsCount: 1 }, }, { - _id: "5774ef80597c7f91bff40dbb", - _tpl: "5ac50c185acfc400163398d4", - parentId: "240046eebc9040c1d7e58611", - slotId: "mod_stock", - upd: { - StackObjectsCount: 1, - sptPresetId: "5acf7dfc86f774401e19c390", - Repairable: { Durability: 32, MaxDurability: 59 }, - }, + _id: "3d953b4a4283363d0494d614", + _tpl: "59bffbb386f77435b379b9c2", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "3bd8b76ba1ff8f1cf954af91", + slotId: "mod_muzzle", }, { - _id: "8b7c8e6ba172ac390c99a2ae", - _tpl: "5ac66c5d5acfc4001718d314", - parentId: "240046eebc9040c1d7e58611", + _id: "4b2c9fb752a7c3458e07a35d", + _tpl: "626bb8532c923541184624b4", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f67388e02546cd97c976d479", + slotId: "mod_scope", + }, { + _id: "ce39864f056a3ad649d77243", + _tpl: "60dc519adf4c47305f6d410d", + parentId: "a5063619e7f4db123ca07fcc", slotId: "mod_magazine", - upd: { StackObjectsCount: 1 }, + upd: {}, }, { - _id: "1ed3a416b1fc7adbed1160df", - _tpl: "6130ca3fd92c473c77020dbd", - parentId: "240046eebc9040c1d7e58611", - slotId: "mod_charge", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "4ffc8f4e80708f6b9336c224", + _tpl: "612368f58b401f4f51239b33", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_barrel", + upd: {}, }, { - _id: "bbe087661947c0d9c1cde146", - _tpl: "5648b1504bdc2d9d488b4584", - parentId: "70b23c628fa17699d9a71e94", + _id: "b401a4ce551dfcb0602e4073", + _tpl: "612781056f3d944a17348d60", + parentId: "a5063619e7f4db123ca07fcc", + slotId: "mod_stock", + upd: {}, + }, { + _id: "b206761507a97037d05f0268", + _tpl: "6123649463849f3d843da7c4", + parentId: "a5063619e7f4db123ca07fcc", slotId: "mod_handguard", + upd: {}, + }, { + _id: "25af8615f5c902fd5920965f", + _tpl: "619d36da53b4d42ee724fae4", + parentId: "4ffc8f4e80708f6b9336c224", + slotId: "mod_muzzle", + upd: {}, + }, { + _id: "38c5e9751e1d69d4d0804a49", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_magazine", + upd: {}, + }, { + _id: "54da5dc9656bb9477eb16c88", + _tpl: "56e05b06d2720bb2668b4586", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_muzzle", + upd: {}, + }, { + _id: "ad690f7145984b942288457f", + _tpl: "56e05a6ed2720bd0748b4567", + parentId: "3702c30b6333e28d6a15d62c", + slotId: "mod_pistolgrip", + upd: {}, + }, { + _id: "c4ffff33f0a5f48c9500699a", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Front_plate", + upd: { Repairable: { Durability: 31.1713047, MaxDurability: 45 } }, + }, { + _id: "8453961a28b572039197e140", + _tpl: "656fa0fb498d1b7e3e071d9c", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "Back_plate", + upd: { Repairable: { Durability: 32.4, MaxDurability: 45 } }, + }, { + _id: "43e7482d78b276a5db4f4fef", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "1", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, { + _id: "7372a194a2de632f5941b701", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "2", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, { + _id: "624555830937dfa5190a11bf", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "3", + location: { x: 0, y: 1, r: "Horizontal", isSearched: true }, + }, { + _id: "05aedd00b683ce0d00ac5c74", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "8c3eccca9f25989d68d90e59", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "5", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "b8b2e1651d7dbb891053b514", + _tpl: "5aa7e454e5b5b0214e506fa2", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "8", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "f9b891b8a5cf948b858a7b1b", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "8b66bc46287219eb0e7c190d", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "24cd31ecc0fdac526c8bd21d", + _tpl: "657f92e7f4c82973640b2354", + parentId: "b8b2e1651d7dbb891053b514", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "c6125558f051cd10cfaf77e0", + _tpl: "5d6d3716a4b9361bc8618872", + parentId: "b82495b01ad0bfe5dd7e864d", + slotId: "9", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "ee92a87a762b35b45f9d7fa7", + _tpl: "657fa009d4caf976440afe3a", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, { + _id: "be9a15c5ab850ae0437315bb", + _tpl: "657fa04ac6679fefb3051e24", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, { + _id: "65c9ceccbebe5f2813a8c70e", + _tpl: "657fa07387e11c61f70bface", + parentId: "c6125558f051cd10cfaf77e0", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 33, MaxDurability: 33 } }, + }, { + _id: "769eab07773ecfaa6e12e4c4", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 }, Togglable: { On: true } }, + parentId: "b8b2e1651d7dbb891053b514", + slotId: "mod_equipment", + }, { + _id: "82aa530739c59be8dd5a0911", + _tpl: "5d6d3829a4b9361bc8618943", + upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 }, Togglable: { On: true } }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_000", + }, { + _id: "996a6f0f8e90cb31f758c801", + _tpl: "5d6d3be5a4b9361bc73bc763", + upd: { StackObjectsCount: 1, Repairable: { Durability: 10, MaxDurability: 24 } }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_001", + }, { + _id: "8c43cca672e16a931590945f", + _tpl: "5d6d3943a4b9360dbc46d0cc", + upd: { StackObjectsCount: 1, Repairable: { Durability: 1, MaxDurability: 1 } }, + parentId: "c6125558f051cd10cfaf77e0", + slotId: "mod_equipment_002", + }, { + _id: "5858b72da0ca732b2fb5ed95", + _tpl: "544a5caa4bdc2d1a388b4568", + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Vertical", isSearched: true }, + }, { + _id: "43ef5a5e1c93ba3ab032811f", + _tpl: "6570e83223c1f638ef0b0ede", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, { + _id: "e1f16c6d9e853f2735948665", + _tpl: "6570e87c23c1f638ef0b0ee2", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 42, MaxDurability: 42 } }, + }, { + _id: "d9bdf684a8264ac1fb3208bf", + _tpl: "6570e90b3a5689d85f08db97", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Groin", + upd: { Repairable: { Durability: 28, MaxDurability: 28 } }, + }, { + _id: "e4b484ba7209d770482732c8", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 0, y: 3, r: "Horizontal", isSearched: true }, + }, { + _id: "ddc3945694d52dcdae9cba4d", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 1, y: 3, r: "Horizontal", isSearched: true }, + }, { + _id: "59923cfba8be35031e5d95e6", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 2, y: 3, r: "Horizontal", isSearched: true }, + }, { + _id: "95cf47373df5c4f07f458a93", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "f9cc99048aa37c5a4a837ef9", + slotId: "main", + location: { x: 3, y: 3, r: "Horizontal", isSearched: true }, + }, { + _id: "98661f27ea826095d0cdd609", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Front_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, { + _id: "525179b06d14baaddb2b04fb", + _tpl: "656f9fa0498d1b7e3e071d98", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "Back_plate", + upd: { Repairable: { Durability: 50, MaxDurability: 50 } }, + }, { + _id: "353638d16450339e40f5b5eb", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "1", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "fa4a5c3e4e3c2f017e35eb1a", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "2", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "7554a8ddb30e0306de7b7d80", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "3", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "4c73b93f4d9f17a05a5782fa", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "4", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "8ce190fcd2ffe5f1f9ad345a", + _tpl: "5aa7e4a4e5b5b000137b76f2", + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "5", + upd: { StackObjectsCount: 1 }, + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "6607b1b9d73f83e559304208", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "41912d06dac91585499c05a2", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "db24f69de28bddd7f09b9c3e", + _tpl: "657f92e7f4c82973640b2354", + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "6c578731bc0c3f91c8089116", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "6", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "aa7b1ce4897aa7e64309ce86", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "6", + location: { x: 1, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "7e5e5dbe18de6aea779d904d", + _tpl: "5addccf45acfc400185c2989", + upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + parentId: "5858b72da0ca732b2fb5ed95", + slotId: "11", + location: { x: 0, y: 0, r: "Horizontal", isSearched: true }, + }, { + _id: "b50b5052892729841e26934f", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 47, MaxDurability: 47 }, Togglable: { On: true } }, + parentId: "8ce190fcd2ffe5f1f9ad345a", + slotId: "mod_equipment", + }], +}, { + scheduledTime: 1712960777.6, + traderId: "54cb50c76803fa8b248b4571", + maxStorageTime: 345600, + systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e4586f774728248ca13 4", + items: [{ + _id: "b29c463afe52421ba72b1816", + _tpl: "5aa7e3abe5b5b000171d064d", + upd: { StackObjectsCount: 1, Repairable: { Durability: 50, MaxDurability: 50 } }, + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + }, { + _id: "1813e676a1bceefd5424b4bb", + _tpl: "5ac7655e5acfc40016339a19", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "a58746a7e98ac16ba9105fc9", + _tpl: "5cf50850d7f00c056e24104c", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "70acf65d9944b19d17d92b19", + _tpl: "55d480c04bdc2d1d4e8b456a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "e3a54ae66a2970372eee1888", + _tpl: "602e63fb6335467b0c5ac94d", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "a4b1cb12dc5ece274d348e2b", + _tpl: "6033749e88382f4fab3fd2c5", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "e3c2162f4001a0d6ed2a199d", + _tpl: "602f85fd9b513876d4338d9c", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "548a111c4e48fb058e7a5c09", + _tpl: "603372b4da11d6478d5a07ff", + parentId: "e3a54ae66a2970372eee1888", + slotId: "mod_barrel", + upd: {}, + }, { + _id: "d58db125fdd3f3b15a9798ca", + _tpl: "602e620f9b513876d4338d9a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "f85ba56791757174e3447c55", + _tpl: "630764fea987397c0816d219", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "e3c409642a067f980ca168b7", + _tpl: "63075cc5962d0247b029dc2a", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "5ff60d8b2b61c9f20ee8e91b", + _tpl: "63076701a987397c0816d21b", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "b212acf3c8f09f48b4beaa0d", + _tpl: "5648a69d4bdc2ded0b8b457b", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }], +}, { + scheduledTime: 1712920104.8, + traderId: "54cb57776803fa99248b456e", + maxStorageTime: 518400, + systemData: { date: "11.04.2024", time: "19:30", location: "factory4_day" }, + messageType: 8, + messageTemplateId: "58fe0e3486f77471f772c3f2 0", + items: [{ + _id: "203161dde59c5a2fdd362da9", + _tpl: "5aa7e4a4e5b5b000137b76f2", + upd: { StackObjectsCount: 1, sptPresetId: "657fa87fc6679fefb3051e32" }, + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + }, { + _id: "37c9968cfc4372c968f57c42", + _tpl: "657f925dada5fadd1f07a57a", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_top", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "5517446f3cd41cf75d3a9cd2", + _tpl: "657f92acada5fadd1f07a57e", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_back", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "0fdc8f25f7dfc61678cdef01", + _tpl: "657f92e7f4c82973640b2354", + parentId: "203161dde59c5a2fdd362da9", + slotId: "Helmet_ears", + upd: { Repairable: { Durability: 21, MaxDurability: 21 } }, + }, { + _id: "e2cba41b10edfc595e2bb574", + _tpl: "628b916469015a4e1711ed8d", + parentId: "6c5ef8a5fb3b88641420e9a0", + slotId: "mod_handguard", + upd: {}, + }, { + _id: "dd3aa187f853187198860933", + _tpl: "628b9be6cff66b70c002b14c", + parentId: "e2cba41b10edfc595e2bb574", + slotId: "mod_reciever", + upd: {}, + }, { + _id: "13d29ea647b01f0ecb774a54", + _tpl: "628b9471078f94059a4b9bfb", + parentId: "dd3aa187f853187198860933", + slotId: "mod_sight_rear", + upd: {}, + }, { + _id: "6c5ef8a5fb3b88641420e9a0", + _tpl: "628b8d83717774443b15e248", + parentId: "afcef56bf4fa36d0ec1f4166", + slotId: "mod_gas_block", + upd: {}, + }, { + _id: "7980e04a92db0858cb7f4bfa", + _tpl: "55d4ae6c4bdc2d8b2f8b456e", + parentId: "929c1577ba7390558c59d8a5", + slotId: "mod_stock", + upd: {}, + }, { + _id: "929c1577ba7390558c59d8a5", + _tpl: "628b9a40717774443b15e9f2", + parentId: "afcef56bf4fa36d0ec1f4166", + slotId: "mod_stock_000", + upd: {}, + }, { + _id: "afcef56bf4fa36d0ec1f4166", + _tpl: "628b5638ad252a16da6dd245", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { + FireMode: { FireMode: "single" }, StackObjectsCount: 1, - sptPresetId: "5acf7dfc86f774401e19c390", - Repairable: { Durability: 32, MaxDurability: 59 }, + Repairable: { Durability: 100, MaxDurability: 100 }, }, }, { - _id: "724388f8110434efccd79b3a", - _tpl: "544a3a774bdc2d3a388b4567", - parentId: "b481bc57436ed9a0c3abe7f3", - slotId: "mod_scope", + _id: "a94905f708670fca5de11e7e", + _tpl: "60339954d62c9b14ed777c06", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { + FireMode: { FireMode: "single" }, + StackObjectsCount: 1, + Repairable: { Durability: 100, MaxDurability: 100 }, + }, + }, { + _id: "8f5ce6d3c7730240c3ae78ad", + _tpl: "602e71bd53a60014f9705bfa", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_pistol_grip", + upd: {}, + }, { + _id: "c320122de049da2880d0a235", + _tpl: "5a7ad2e851dfba0016153692", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_magazine", + upd: {}, + }, { + _id: "d2923c8984f26f68f01d20d7", + _tpl: "602e3f1254072b51b239f713", + parentId: "a94905f708670fca5de11e7e", + slotId: "mod_stock_001", + upd: {}, + }, { + _id: "ecd363cddbb5361670d531b0", + _tpl: "60337f5dce399e10262255d1", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "704c139d092f1bd3e3d18df2", + _tpl: "6034e3cb0ddce744014cb870", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "72bd97cb21996a2282ff7bcd", + _tpl: "630765cb962d0247b029dc45", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "44e3df51e01d5b23445fb95f", + _tpl: "630765777d50ff5e8a1ea718", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: {}, + }, { + _id: "1cb0900a4bd068b04ca05db1", + _tpl: "63088377b5cd696784087147", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, }, { - _id: "8581038b0f795618a3d26c94", - _tpl: "58d268fc86f774111273f8c2", - parentId: "724388f8110434efccd79b3a", - slotId: "mod_scope", - upd: { StackObjectsCount: 1, Repairable: { Durability: 100, MaxDurability: 100 } }, + _id: "379ca7cd56ebb1434bd89d62", + _tpl: "656f9d5900d62bcd2e02407c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Front_plate", + upd: { Repairable: { Durability: 32.4841042, MaxDurability: 45 } }, + }, { + _id: "d700aaa1d7a15644f6b91dc7", + _tpl: "656f9d5900d62bcd2e02407c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Back_plate", + upd: { Repairable: { Durability: 45, MaxDurability: 45 } }, + }, { + _id: "eb3bbc6cb084a53ff48b672d", + _tpl: "5b44d22286f774172b0c9de8", + parentId: "d2b3b859f667d4fd8b35bc96", + slotId: "hideout", + upd: { StackObjectsCount: 1 }, + }, { + _id: "6a3d83c5230d1779060e17a9", + _tpl: "65704de13e7bba58ea0285c8", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_front", + upd: { Repairable: { Durability: 37.4214172, MaxDurability: 56 } }, + }, { + _id: "9fba54de64b37902dd14b6e5", + _tpl: "65705c3c14f2ed6d7d0b7738", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_back", + upd: { Repairable: { Durability: 49.93156, MaxDurability: 56 } }, + }, { + _id: "2b534b3af5f240c625a77424", + _tpl: "65705c777260e1139e091408", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Soft_armor_left", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, { + _id: "e046688c9167ceaced5af3a7", + _tpl: "65705cb314f2ed6d7d0b773c", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "soft_armor_right", + upd: { Repairable: { Durability: 12, MaxDurability: 12 } }, + }, { + _id: "6c612d370959e61b6c10b7bf", + _tpl: "65705cea4916448ae1050897", + parentId: "eb3bbc6cb084a53ff48b672d", + slotId: "Collar", + upd: { Repairable: { Durability: 14, MaxDurability: 14 } }, }], }]; diff --git a/project/tests/controllers/InsuranceController.test.ts b/project/tests/controllers/InsuranceController.test.ts index ba0cbed5..7b1fc23b 100644 --- a/project/tests/controllers/InsuranceController.test.ts +++ b/project/tests/controllers/InsuranceController.test.ts @@ -122,9 +122,7 @@ describe("InsuranceController", () => // Verify that the correct methods were called. expect(mockGetProfile).toBeCalledTimes(1); - expect(mockLoggerDebug).toBeCalledWith( - `Found ${insuranceFixture.length} insurance packages in profile ${sessionID}`, - ); + expect(mockLoggerDebug).toBeCalledTimes(1); expect(insuredFiltered.length).toBe(insuranceFixture.length); }); @@ -147,9 +145,7 @@ describe("InsuranceController", () => // Verify that the correct methods were called. expect(mockGetProfile).toBeCalledTimes(1); - expect(mockLoggerDebug).toBeCalledWith( - `Found ${insuranceFixture.length} insurance packages in profile ${sessionID}`, - ); + expect(mockLoggerDebug).toBeCalledTimes(1); expect(insuredFiltered.length).toBe(insuranceFixture.length - 1); // Should be 1 less than the original fixture. }); @@ -173,9 +169,7 @@ describe("InsuranceController", () => // Verify that the correct methods were called. expect(mockGetProfile).toBeCalledTimes(1); - expect(mockLoggerDebug).toBeCalledWith( - `Found ${insuranceFixture.length} insurance packages in profile ${sessionID}`, - ); + expect(mockLoggerDebug).toBeCalledTimes(1); // Verify that the returned array is empty. expect(insuredFiltered.length).toBe(0); @@ -187,12 +181,14 @@ describe("InsuranceController", () => it("should log information about the insurance package", () => { const sessionId = "session-id"; + const numberOfItems = 666; // Spy on the logger.debug method. const mockLoggerDebug = vi.spyOn(insuranceController.logger, "debug"); + vi.spyOn(insuranceController, "countAllInsuranceItems").mockReturnValue(numberOfItems); vi.spyOn(insuranceController, "findItemsToDelete").mockImplementation(vi.fn()); vi.spyOn(insuranceController, "removeItemsFromInsurance").mockImplementation(vi.fn()); - vi.spyOn(insuranceController, "adoptOrphanedItems").mockImplementation(vi.fn()); + vi.spyOn(insuranceController.itemHelper, "adoptOrphanedItems").mockImplementation(vi.fn()); vi.spyOn(insuranceController, "sendMail").mockImplementation(vi.fn()); vi.spyOn(insuranceController, "removeInsurancePackageFromProfile").mockImplementation(vi.fn()); @@ -201,9 +197,7 @@ describe("InsuranceController", () => // Verify that the log was written. expect(mockLoggerDebug).toBeCalledWith( - `Processing ${insuranceFixture.length} insurance packages, which includes a total of ${ - insuranceController.countAllInsuranceItems(insuranceFixture) - } items, in profile ${sessionId}`, + `Processing ${insuranceFixture.length} insurance packages, which includes a total of ${numberOfItems} items, in profile ${sessionId}`, ); }); @@ -218,9 +212,8 @@ describe("InsuranceController", () => ); const mockRemoveItemsFromInsurance = vi.spyOn(insuranceController, "removeItemsFromInsurance") .mockImplementation(vi.fn()); - const mockAdoptOrphanedItems = vi.spyOn(insuranceController, "adoptOrphanedItems").mockImplementation( - vi.fn(), - ); + const mockAdoptOrphanedItems = vi.spyOn(insuranceController.itemHelper, "adoptOrphanedItems") + .mockImplementation(vi.fn()); const mockSendMail = vi.spyOn(insuranceController, "sendMail").mockImplementation(vi.fn()); const mockRemoveInsurancePackageFromProfile = vi.spyOn( insuranceController, @@ -295,12 +288,17 @@ describe("InsuranceController", () => it("should remove the specified insurance package from the profile", () => { const sessionID = "session-id"; - const packageToRemove = { date: "01.11.2023", time: "10:51", location: "factory4_day" }; + const packageToRemove = { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }; const profile = { insurance: [{ - messageContent: { systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" } }, - }, { // This one should be removed - messageContent: { systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" } }, + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }, { + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, }], }; @@ -312,20 +310,23 @@ describe("InsuranceController", () => // Verify that the specified insurance package was removed. expect(profile.insurance.length).toBe(1); - expect(profile.insurance[0].messageContent.systemData).toStrictEqual({ - date: "01.11.2023", - time: "11:18", - location: "factory4_day", - }); + expect(profile.insurance).toStrictEqual([{ + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, + }]); }); it("should log a message indicating that the package was removed", () => { const sessionID = "session-id"; - const packageToRemove = { date: "01.11.2023", time: "10:51", location: "factory4_day" }; + const packageToRemove = { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }; const profile = { insurance: [{ - messageContent: { systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" } }, + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, }], }; @@ -340,17 +341,24 @@ describe("InsuranceController", () => // Verify that the log was written. expect(mockLoggerDebug).toBeCalledWith( - `Removed insurance package with date: ${packageToRemove.date}, time: ${packageToRemove.time}, and location: ${packageToRemove.location} from profile ${sessionID}. Remaining packages: ${profile.insurance.length}`, + `Removed processed insurance package. Remaining packages: ${profile.insurance.length}`, ); }); it("should not remove any packages if the specified package is not found", () => { const sessionID = "session-id"; - const packageToRemove = { date: "01.11.2023", time: "10:51", location: "factory4_day" }; + const packageToRemove = { + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:25", location: "factory4_day" }, + }; const profile = { insurance: [{ - messageContent: { systemData: { date: "02.11.2023", time: "10:50", location: "factory4_night" } }, + traderId: "54cb50c76803fa8b248b4571", + systemData: { date: "01.11.2023", time: "11:18", location: "factory4_day" }, + }, { + traderId: "54cb57776803fa99248b456e", + systemData: { date: "01.11.2023", time: "10:51", location: "factory4_day" }, }], }; @@ -360,8 +368,8 @@ describe("InsuranceController", () => // Execute the method. insuranceController.removeInsurancePackageFromProfile(sessionID, packageToRemove); - // Verify that no packages were removed. - expect(profile.insurance.length).toBe(1); + // Verify that the specified insurance package was removed. + expect(profile.insurance.length).toBe(2); }); }); @@ -373,7 +381,10 @@ describe("InsuranceController", () => insurancePackage.items = []; // Execute the method. - const result = insuranceController.findItemsToDelete(insurancePackage); + const result = insuranceController.findItemsToDelete( + insuranceController.hashUtil.generate(), + insurancePackage, + ); // Verify that the result is correct. expect(result.size).toBe(0); @@ -387,7 +398,6 @@ describe("InsuranceController", () => const numberOfItems = insured.items.length; // Mock helper methods. - const mockPopulateItemsMap = vi.spyOn(insuranceController, "populateItemsMap"); const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); const mockIsAttachmentAttached = vi.spyOn(insuranceController.itemHelper, "isAttachmentAttached"); const mockProcessAttachments = vi.spyOn(insuranceController, "processAttachments").mockImplementation( @@ -405,12 +415,11 @@ describe("InsuranceController", () => vi.spyOn(insuranceController, "processRegularItems").mockImplementation(mockProcessRegularItems); // Execute the method. - const result = insuranceController.findItemsToDelete(insured); + const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); // Verify that the correct methods were called. - expect(mockPopulateItemsMap).toHaveBeenCalledTimes(1); expect(mockPopulateParentAttachmentsMap).toHaveBeenCalledTimes(1); - expect(mockIsAttachmentAttached).toHaveBeenCalledTimes(numberOfItems + 1); // Once for each item, plus once more + expect(mockIsAttachmentAttached).toHaveBeenCalled(); expect(mockProcessRegularItems).toHaveBeenCalledTimes(1); expect(mockProcessAttachments).not.toHaveBeenCalled(); @@ -426,7 +435,6 @@ describe("InsuranceController", () => const insured = insuranceFixture[0]; // Mock helper methods. - const mockPopulateItemsMap = vi.spyOn(insuranceController, "populateItemsMap"); const mockProcessRegularItems = vi.spyOn(insuranceController, "processRegularItems"); const mockProcessAttachments = vi.spyOn(insuranceController, "processAttachments"); @@ -440,10 +448,9 @@ describe("InsuranceController", () => ); // Execute the method. - const result = insuranceController.findItemsToDelete(insured); + const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); // Verify that the correct methods were called. - expect(mockPopulateItemsMap).toHaveBeenCalled(); expect(mockPopulateParentAttachmentsMap).toHaveBeenCalled(); expect(mockProcessRegularItems).not.toHaveBeenCalled(); expect(mockProcessAttachments).not.toHaveBeenCalled(); @@ -459,7 +466,6 @@ describe("InsuranceController", () => const numberOfItems = insured.items.length; // Mock helper methods. - const mockPopulateItemsMap = vi.spyOn(insuranceController, "populateItemsMap"); const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); // Add all items to the toDelete set. Not realistic, but it's fine for this test. @@ -481,10 +487,9 @@ describe("InsuranceController", () => vi.spyOn(insuranceController, "processAttachments").mockImplementation(mockProcessAttachments); // Execute the method. - const result = insuranceController.findItemsToDelete(insured); + const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); // Verify that the correct methods were called. - expect(mockPopulateItemsMap).toHaveBeenCalled(); expect(mockPopulateParentAttachmentsMap).toHaveBeenCalled(); expect(mockProcessRegularItems).toHaveBeenCalled(); expect(mockProcessAttachments).toHaveBeenCalled(); @@ -499,7 +504,6 @@ describe("InsuranceController", () => const insured = insuranceFixture[0]; // Mock helper methods. - const mockPopulateItemsMap = vi.spyOn(insuranceController, "populateItemsMap"); const mockPopulateParentAttachmentsMap = vi.spyOn(insuranceController, "populateParentAttachmentsMap"); // Don't add any items to the toDelete set. @@ -511,10 +515,9 @@ describe("InsuranceController", () => ); // Execute the method. - const result = insuranceController.findItemsToDelete(insured); + const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); // Verify that the correct methods were called. - expect(mockPopulateItemsMap).toHaveBeenCalled(); expect(mockPopulateParentAttachmentsMap).toHaveBeenCalled(); expect(mockProcessRegularItems).toHaveBeenCalled(); expect(mockProcessAttachments).toHaveBeenCalled(); @@ -551,7 +554,7 @@ describe("InsuranceController", () => vi.spyOn(insuranceController, "processAttachments").mockImplementation(mockProcessAttachments); // Execute the method. - const result = insuranceController.findItemsToDelete(insured); + const result = insuranceController.findItemsToDelete(insuranceController.hashUtil.generate(), insured); // Verify that the result is the correct size, and the size is logged. expect(result.size).toBe(numberOfItems); @@ -566,26 +569,54 @@ describe("InsuranceController", () => const insured = insuranceFixture[0]; // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); // Execute the method. - const result = insuranceController.populateParentAttachmentsMap(insured, itemsMap); + const result = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Verify that the map is populated correctly. - expect(result.size).toBe(6); // There are 6 base-level items in this insurance package. + expect(result.size).toBe(9); // There are 9 base-level items in this insurance package. - const gun = result.get("911a0f04d5d9c7e239807ae0"); - expect(gun.length).toBe(7); // This AK has 7 attachments. + const gun = result.get("35111c9b72a87b6b7d95ad35"); + expect(gun.length).toBe(31); // This gun has 31 attachments. - // The attachments should be mapped to the AK properly... + // The attachments should be mapped to the gun properly... const validAttachmentTemplates = [ - "677c209ebb45445ebb42c405", - "4bd10f89836fd9f86aedcac1", - "8b1327270791b142ac341b03", - "da8cde1b3024c336f6e06152", - "bc041c0011d76f714b898400", - "9f8d7880a6e0a47a211ec5d3", - "db2ef9442178910eba985b51", + "7c42d3dce0ddbc4806bce48b", + "10b97872c5f4e0e1949a0369", + "a6cd9986dde4cabddcd2dce2", + "b65635b515712f990fdcc201", + "0e11045873efe3625695c1ae", + "94c4161abe8bf654fb986063", + "9b284ccfd0d535acec1ff58b", + "d730caa83a11fd01250a7261", + "24291c7bcf91e362adb6d68b", + "0d98fd0769cce8e473bbe540", + "11b174510f039e8217fbd202", + "c435230e530574b1d7c32300", + "15666fe6fd2d95206612e418", + "a54de8b9014eee71fdf1d01d", + "c34555bc95a9a7a23150a36f", + "91cae4ae30d1366b87158238", + "48f23df4509164cf397b9ab5", + "a55f05f689978ac65c7da654", + "8ae4ea81a2d6074162d87a9c", + "312cc0f6687963305457235e", + "e1e5aaf474b7282a52ac9a14", + "bb9a34648e08f005db5d7484", + "dd9ac99d3ea4c9656221bcc9", + "b22748de8da5f3c1362dd8e0", + "e3cc1be8954c4889f94b435a", + "e73f05be5a306168e847da82", + "847cf35ec92d8af8e4814ea8", + "bb4b7a4475fea0f0135305f6", + "d0ac8e688a0bb17668589909", + "5dbcf8cbbb3f8ef669836320", + "f996645c809968f8033593a6", ]; for (const value of validAttachmentTemplates) { @@ -594,64 +625,37 @@ describe("InsuranceController", () => } }); - it("should ignore gun accessories that cannot be modified in-raid", () => - { - const insured = insuranceFixture[0]; - - // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); - - // Execute the method. - const result = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - - // Verify that the map is populated correctly. - expect(result.size).toBe(6); // There are 6 base-level items in this insurance package. - - const gun = result.get("911a0f04d5d9c7e239807ae0"); - expect(gun.length).toBe(7); // This AK has 7 valid attachments. - - // These are attachments for the AK, but they are not raid moddable, so they should not be mapped. - const invalidAttachmentTemplates = [ - "1e0b177df108c0c117028812", - "c9278dd8251e99578bf7a274", - "402b4086535a50ef7d9cef88", - "566335b3df586f34b47f5e35", - ]; - for (const value of invalidAttachmentTemplates) - { - // Verify that each template is not present in the array of attachments. - expect(gun.every((item) => item._id !== value)).toBe(true); - } - }); - it("should correctly map helmet to all of its attachments", () => { const insured = insuranceFixture[0]; // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); // Execute the method. - const result = insuranceController.populateParentAttachmentsMap(insured, itemsMap); + const result = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Verify that the map is populated correctly. - expect(result.size).toBe(6); // There are 6 base-level items in this insurance package. + expect(result.size).toBe(9); // There are 9 base-level items in this insurance package. - const gun = result.get("3679078e05f5b14466d6a730"); - expect(gun.length).toBe(5); // This LShZ-2DTM has 5 valid attachments. + const helmet = result.get("b2405216e5730f3511884a10"); + expect(helmet.length).toBe(4); // This helmet has 2 valid attachments. - // The attachments should be mapped to the AK properly... + // The attachments should be mapped to the helmet properly... const validAttachmentTemplates = [ - "a2b0c716162c5e31ec28c55a", - "dc565f750342cb2d19eeda06", - "e9ff62601669d9e2ea9c2fbb", - "ac134d7cf6c9d8e25edd0015", - "22274b895ecc80d51c3cba1c", + "7a0675280dbbad69ce592d74", + "c0c182942f54d3c183f0e179", + "f7066fdfeefb29eca1d2dbeb", + "ee0ec86e9608abe773175e3a", ]; for (const value of validAttachmentTemplates) { // Verify that each template is present in the array of attachments. - expect(gun.some((item) => item._id === value)).toBe(true); + expect(helmet.some((item) => item._id === value)).toBe(true); } }); @@ -660,29 +664,41 @@ describe("InsuranceController", () => const insured = insuranceFixture[0]; // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); // Execute the method. - const result = insuranceController.populateParentAttachmentsMap(insured, itemsMap); + const result = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Verify that the map is populated correctly. - expect(result.size).toBe(6); // There are 6 base-level items in this insurance package. + expect(result.size).toBe(9); // There are 9 base-level items in this insurance package. - const gun = result.get("351180f3248d45c71cb2ebdc"); - expect(insured.items.find((item) => item._id === "351180f3248d45c71cb2ebdc").slotId).toBe("main"); - expect(gun.length).toBe(14); // This AS VAL has 14 valid attachments. + const gun = result.get("26598f88d49198c4a0a9391c"); + expect(insured.items.find((item) => item._id === "26598f88d49198c4a0a9391c").slotId).toBe("main"); + expect(gun.length).toBe(3); }); it("should not map items that do not have a main-parent", () => { + // Remove regular items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); const insured = insuranceFixture[0]; // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + + // Suppress warnings. + const mockLoggerWarning = vi.spyOn(insuranceController.logger, "warning").mockImplementation(vi.fn()); // Execute the method. - const result = insuranceController.populateParentAttachmentsMap(insured, itemsMap); + const result = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Verify that the map is populated correctly. expect(result.size).toBe(0); @@ -690,31 +706,92 @@ describe("InsuranceController", () => it("should log a warning when an item does not have a main-parent", () => { + // Remove regular items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); const insured = insuranceFixture[0]; // Generate the items map. - const itemsMap = insuranceController.populateItemsMap(insured); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); // Suppress warnings. const mockLoggerWarning = vi.spyOn(insuranceController.logger, "warning").mockImplementation(vi.fn()); // Execute the method. - insuranceController.populateParentAttachmentsMap(insured, itemsMap); + insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Verify that the warning was logged. expect(mockLoggerWarning).toHaveBeenCalled(); }); }); + describe("removeNonModdableAttachments", () => + { + it("should return a Map where each parent item ID is mapped to only moddable attachments", () => + { + const insured = insuranceFixture[0]; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + + // Execute the method. + const result = insuranceController.removeNonModdableAttachments(parentAttachmentsMap, itemsMap); + + // Verify that the map is populated correctly. + for (const [parentId, attachments] of result) + { + for (const attachment of attachments) + { + // Verify that each attachment is moddable. + const attachmentParentItem = itemsMap.get(parentId); + expect(insuranceController.itemHelper.isRaidModdable(attachment, attachmentParentItem)).toBe(true); + } + } + }); + + it("should remove parents that do not have any moddable attachments", () => + { + const insured = insuranceFixture[0]; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + + // Mock isRaidModdable to return false for all attachments. + vi.spyOn(insuranceController.itemHelper, "isRaidModdable").mockReturnValue(false); + + // Execute the method. + const result = insuranceController.removeNonModdableAttachments(parentAttachmentsMap, itemsMap); + + // Verify that the map is now empty. + expect(result.size).toBe(0); + }); + }); + describe("processRegularItems", () => { it("should process regular items and their non-attachment children", () => { + // Remove attachment items from the fixture. insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeAttachmentItems().get(); + const insured = insuranceFixture[0]; const numberOfItems = insured.items.length; const toDelete = new Set(); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Mock helper methods. const mockIsAttachmentAttached = vi.spyOn(insuranceController.itemHelper, "isAttachmentAttached"); @@ -727,11 +804,11 @@ describe("InsuranceController", () => const mockRollForDelete = vi.spyOn(insuranceController, "rollForDelete").mockReturnValue(true); // Execute the method. - insuranceController.processRegularItems(insured, toDelete); + insuranceController.processRegularItems(insured, toDelete, parentAttachmentsMap); // Verify that the correct methods were called. - expect(mockIsAttachmentAttached).toHaveBeenCalled(); - expect(mockFindAndReturnChildrenAsItems).toHaveBeenCalled(); + expect(mockIsAttachmentAttached).toHaveBeenCalledTimes(numberOfItems); + expect(mockFindAndReturnChildrenAsItems).not.toHaveBeenCalled(); expect(mockRollForDelete).toHaveBeenCalledTimes(numberOfItems); // Verify that all items were added to the toDelete set. @@ -742,6 +819,12 @@ describe("InsuranceController", () => { const insured = insuranceFixture[0]; const toDelete = new Set(); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Mock isAttachmentAttached to return true for all items. vi.spyOn(insuranceController.itemHelper, "isAttachmentAttached").mockReturnValue(true); @@ -750,7 +833,7 @@ describe("InsuranceController", () => const mockRollForDelete = vi.spyOn(insuranceController, "rollForDelete").mockReturnValue(true); // Execute the method. - insuranceController.processRegularItems(insured, toDelete); + insuranceController.processRegularItems(insured, toDelete, parentAttachmentsMap); // Verify that a roll was not made for any items. expect(mockRollForDelete).not.toHaveBeenCalled(); @@ -761,20 +844,24 @@ describe("InsuranceController", () => it("should mark attachments for deletion when parent is marked for deletion", () => { - const itemHelper = container.resolve("ItemHelper"); - const insured = insuranceFixture[0]; const toDelete = new Set(); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Mock rollForDelete to return true for all base-parent items. const mockRollForDelete = vi.fn((traderId, insuredItem) => { - return !itemHelper.isAttachmentAttached(insuredItem); + return !insuranceController.itemHelper.isAttachmentAttached(insuredItem); }); vi.spyOn(insuranceController, "rollForDelete").mockImplementation(mockRollForDelete); // Execute the method. - insuranceController.processRegularItems(insured, toDelete); + insuranceController.processRegularItems(insured, toDelete, parentAttachmentsMap); // Verify that all items were added to the toDelete set. expect(toDelete).toEqual(new Set(insured.items.map((item) => item._id))); @@ -786,44 +873,53 @@ describe("InsuranceController", () => it("should iterate over each parent item", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); const toDelete = new Set(); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Mock helper methods. const mockProcessAttachmentByParent = vi.spyOn(insuranceController, "processAttachmentByParent"); // Execute the method. - insuranceController.processAttachments(parentToAttachmentMap, itemsMap, insured.traderId, toDelete); + insuranceController.processAttachments(parentAttachmentsMap, itemsMap, insured.traderId, toDelete); // Verify - expect(mockProcessAttachmentByParent).toHaveBeenCalledTimes(parentToAttachmentMap.size); + expect(mockProcessAttachmentByParent).toHaveBeenCalledTimes(parentAttachmentsMap.size); }); it("should log the name of each parent item", () => { - const itemHelper = container.resolve("ItemHelper"); - const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); const toDelete = new Set(); + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); // Mock helper methods. - const mockLoggerDebug = vi.spyOn(insuranceController.logger, "debug"); + const mockLoggerDebug = vi.spyOn(insuranceController.logger, "debug").mockImplementation(vi.fn()); + + // Mock processAttachmentByParent to prevent it from being called. + vi.spyOn(insuranceController, "processAttachmentByParent").mockImplementation(vi.fn()); // Execute the method. - insuranceController.processAttachments(parentToAttachmentMap, itemsMap, insured.traderId, toDelete); + insuranceController.processAttachments(parentAttachmentsMap, itemsMap, insured.traderId, toDelete); // Verify that the name of each parent item is logged. - for (const [parentId] of parentToAttachmentMap) + for (const [parentId] of parentAttachmentsMap) { const parentItem = itemsMap.get(parentId); if (parentItem) { - const expectedMessage = `Processing attachments for parent item: ${ - itemHelper.getItemName(parentItem._tpl) - }`; + const expectedMessage = `Processing attachments of parent "${ + insuranceController.itemHelper.getItemName(parentItem._tpl) + }":`; expect(mockLoggerDebug).toHaveBeenCalledWith(expectedMessage); } } @@ -835,9 +931,13 @@ describe("InsuranceController", () => it("should handle sorting, rolling, and deleting attachments by calling helper methods", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.entries().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.entries().next().value; const toDelete = new Set(); // Mock helper methods. @@ -854,12 +954,16 @@ describe("InsuranceController", () => expect(mockAttachmentDeletionByValue).toHaveBeenCalled(); }); - it("should log attachment details and number of successful rolls", () => + it("should log attachment details and number of attachments to be deleted", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.entries().next().value; const toDelete = new Set(); const successfulRolls = 4; @@ -873,58 +977,66 @@ describe("InsuranceController", () => // Verify that the logs were called/written. expect(mockLogAttachmentsDetails).toBeCalled(); - expect(mockLoggerDebug).toHaveBeenCalledWith(`Number of successful rolls: ${successfulRolls}`); + expect(mockLoggerDebug).toHaveBeenCalledWith(`Number of attachments to be deleted: ${successfulRolls}`); }); }); describe("sortAttachmentsByPrice", () => { - it("should sort the attachments array by maxPrice in descending order", () => + it("should sort the attachments array by dynamicPrice in descending order", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.entries().next().value; + const attachmentCount = attachments.length; // Execute the method. const sortedAttachments = insuranceController.sortAttachmentsByPrice(attachments); - // Verify the length of the sorted attachments array - expect(sortedAttachments.length).toBe(5); + // Verify the length of the sorted attachments array is unchanged + expect(sortedAttachments.length).toBe(attachmentCount); - // Verify that the attachments are sorted by maxPrice in descending order + // Verify that the attachments are sorted by dynamicPrice in descending order for (let i = 1; i < sortedAttachments.length; i++) { - expect(sortedAttachments[i - 1].maxPrice).toBeGreaterThanOrEqual(sortedAttachments[i].maxPrice); + expect(sortedAttachments[i - 1].dynamicPrice).toBeGreaterThanOrEqual(sortedAttachments[i].dynamicPrice); } }); - it("should place attachments with null maxPrice at the bottom of the sorted list", () => + it("should place attachments with null dynamicPrice at the bottom of the sorted list", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; - - // Set the maxPrice of the first two attachments to null. - vi.spyOn(insuranceController.itemHelper, "getItemMaxPrice").mockReturnValueOnce(null).mockReturnValueOnce( - null, + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, ); + const attachments = parentAttachmentsMap.entries().next().value; + + // Set the dynamicPrice of the first attachment to null. + vi.spyOn(insuranceController.ragfairPriceService, "getDynamicItemPrice").mockReturnValue(666) + .mockReturnValueOnce(null); // Execute the method. const sortedAttachments = insuranceController.sortAttachmentsByPrice(attachments); - // Verify that the attachments with null maxPrice are at the bottom of the list - const nullPriceAttachments = sortedAttachments.slice(-2); + // Verify that the attachments with null dynamicPrice are at the bottom of the list + const nullPriceAttachments = sortedAttachments.slice(-1); for (const attachment of nullPriceAttachments) { - expect(attachment.maxPrice).toBeNull(); + expect(attachment.dynamicPrice).toBeNull(); } - // Verify that the rest of the attachments are sorted by maxPrice in descending order + // Verify that the rest of the attachments are sorted by dynamicPrice in descending order for (let i = 1; i < sortedAttachments.length - 2; i++) { - expect(sortedAttachments[i - 1].maxPrice).toBeGreaterThanOrEqual(sortedAttachments[i].maxPrice); + expect(sortedAttachments[i - 1].dynamicPrice).toBeGreaterThanOrEqual(sortedAttachments[i].dynamicPrice); } }); }); @@ -933,10 +1045,10 @@ describe("InsuranceController", () => { it("should log details for each attachment", () => { - const attachments = [{ _id: "item1", name: "Item 1", maxPrice: 100 }, { + const attachments = [{ _id: "item1", name: "Item 1", dynamicPrice: 100 }, { _id: "item2", name: "Item 2", - maxPrice: 200, + dynamicPrice: 200, }]; // Mock the logger.debug function. @@ -947,8 +1059,8 @@ describe("InsuranceController", () => // Verify that logger.debug was called correctly. expect(loggerDebugSpy).toHaveBeenCalledTimes(2); - expect(loggerDebugSpy).toHaveBeenNthCalledWith(1, "Child Item - Name: Item 1, Max Price: 100"); - expect(loggerDebugSpy).toHaveBeenNthCalledWith(2, "Child Item - Name: Item 2, Max Price: 200"); + expect(loggerDebugSpy).toHaveBeenNthCalledWith(1, "Attachment 1: \"Item 1\" - Price: 100"); + expect(loggerDebugSpy).toHaveBeenNthCalledWith(2, "Attachment 2: \"Item 2\" - Price: 200"); }); it("should not log anything when there are no attachments", () => @@ -968,12 +1080,16 @@ describe("InsuranceController", () => describe("countSuccessfulRolls", () => { - it("should count the number of successful rolls based on the rollForDelete method", () => + it("should count the number of successful rolls made in the rollForDelete method", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.values().next().value; // Mock rollForDelete to return true for the first two attachments. const mockRollForDelete = vi.spyOn(insuranceController, "rollForDelete").mockReturnValue(false) @@ -987,12 +1103,16 @@ describe("InsuranceController", () => expect(result).toBe(2); }); - it("should count the number of successful rolls based on the rollForDelete method", () => + it("should return zero if no successful rolls were made in the rollForDelete method", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.values().next().value; // Mock rollForDelete to return false. const mockRollForDelete = vi.spyOn(insuranceController, "rollForDelete").mockReturnValue(false); @@ -1027,9 +1147,13 @@ describe("InsuranceController", () => it("should add the correct number of attachments to the toDelete set", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.values().next().value; const successfulRolls = 2; const toDelete = new Set(); @@ -1044,9 +1168,13 @@ describe("InsuranceController", () => it("should not add any attachments to toDelete if successfulRolls is zero", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.values().next().value; const successfulRolls = 0; const toDelete = new Set(); @@ -1061,9 +1189,13 @@ describe("InsuranceController", () => it("should add all attachments to toDelete if successfulRolls is greater than the number of attachments", () => { const insured = insuranceFixture[0]; - const itemsMap = insuranceController.populateItemsMap(insured); - const parentToAttachmentMap = insuranceController.populateParentAttachmentsMap(insured, itemsMap); - const attachments = parentToAttachmentMap.values().next().value; + const itemsMap = insuranceController.itemHelper.generateItemsMap(insured.items); + const parentAttachmentsMap = insuranceController.populateParentAttachmentsMap( + insuranceController.hashUtil.generate(), + insured, + itemsMap, + ); + const attachments = parentAttachmentsMap.values().next().value; const successfulRolls = 999; const toDelete = new Set(); @@ -1134,125 +1266,10 @@ describe("InsuranceController", () => }); }); - describe("adoptOrphanedItems", () => - { - it("should adopt orphaned items by resetting them as base-level items", () => - { - // Get all of the items, so that we can dynamically find the hideout item. - const insured = insuranceFixture[0]; - const hideoutParentId = insuranceController.fetchHideoutItemParent(insured.items); - - // Manually set one of the items to be orphaned. - insured.items[0].parentId = "9999"; // Should not exist in the items array. - insured.items[0].slotId = "main"; // Should not be "hideout". - - // Iterate over the items and find an individual orphaned item. - const orphanedItem = insured.items.find((item) => - !insured.items.some((parent) => parent._id === item.parentId) - ); - - // Setup tests to verify that the orphaned item we added is in fact orphaned. - expect(orphanedItem.parentId).toBe(insured.items[0].parentId); - expect(orphanedItem.slotId).toBe(insured.items[0].slotId); - - // Execute the method. - insuranceController.adoptOrphanedItems(insured); - - // Verify that the orphaned items have been adopted. - expect(orphanedItem.parentId).toBe(hideoutParentId); - expect(orphanedItem.slotId).toBe("hideout"); - }); - - it("should not adopt items that are not orphaned", () => - { - const unmodified = insuranceFixture[0]; - - // Create a deep copy of the insured items array. - const insured = JSON.parse(JSON.stringify(insuranceFixture[0])); - - // Execute the method. - insuranceController.adoptOrphanedItems(insured); - - // Verify that the orphaned items have been adopted. - expect(insured).toStrictEqual(unmodified); - }); - - it("should remove location data from adopted items", () => - { - const insured = insuranceFixture[0]; - - // Manually set one of the items to be orphaned. - insured.items[0].parentId = "9999"; // Should not exist in the items array. - insured.items[0].slotId = "main"; // Should not be "hideout". - insured.items[0].location = { x: 1, y: 2, r: 3, isSearched: true }; // Should be removed. - - // Iterate over the items and find an individual orphaned item. - const orphanedItem = insured.items.find((item) => - !insured.items.some((parent) => parent._id === item.parentId) - ); - - // Setup tests to verify that the orphaned item we added is in fact orphaned. - expect(orphanedItem.parentId).toBe(insured.items[0].parentId); - expect(orphanedItem.slotId).toBe(insured.items[0].slotId); - - // Execute the method. - insuranceController.adoptOrphanedItems(insured); - - // Verify that the orphaned items have been adopted. - expect(orphanedItem).not.toHaveProperty("location"); - }); - }); - - describe("fetchHideoutItemParent", () => - { - it("should return the parentId value of an item that has a slotId of 'hideout'", () => - { - const insured = insuranceFixture[0]; - const hideoutParentId = insuranceController.fetchHideoutItemParent(insured.items); - - // Execute the method. - const result = insuranceController.fetchHideoutItemParent(insured.items); - - // Verify that the hideout item parentId is returned. - expect(result).toBe(hideoutParentId); - }); - - it("should return an empty string if no item with a slotId of 'hideout' could be found", () => - { - // Fetch a bunch of orphaned items that don't have a hideout parent. - const insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); - const insured = insuranceFixture[0]; - - // Execute the method. - const result = insuranceController.fetchHideoutItemParent(insured.items); - - // Verify that the hideout item parentId is returned. - expect(result).toBe(""); - }); - - it("should log a warning if the base-level item does not exist", () => - { - // Fetch a bunch of orphaned items that don't have a hideout parent. - const insuranceFixture = new ProfileInsuranceFactory().adjustPackageDates().removeRegularItems().get(); - const insured = insuranceFixture[0]; - - // Spy on the logger. - const loggerWarningSpy = vi.spyOn(insuranceController.logger, "warning"); - - // Execute the method. - insuranceController.fetchHideoutItemParent(insured.items); - - // Verify that the hideout item parentId is returned. - expect(loggerWarningSpy).toHaveBeenCalled(); - }); - }); - describe("sendMail", () => { it("should send insurance failed message when no items are present", () => { - const traderHelper = container.resolve("TraderHelper"); - const insurance = insuranceFixture[0]; insurance.items = []; // Empty the items array const sessionID = "session-id"; @@ -1276,19 +1293,17 @@ describe("InsuranceController", () => // Verify that the insurance failed message was sent. expect(sendMessageSpy).toHaveBeenCalledWith( sessionID, - traderHelper.getTraderById(insurance.traderId), + insuranceController.traderHelper.getTraderById(insurance.traderId), MessageType.INSURANCE_RETURN, insuranceFailedTpl, insurance.items, - insurance.messageContent.maxStorageTime, - insurance.messageContent.systemData, + insurance.maxStorageTime, + insurance.systemData, ); }); it("should not send insurance failed message when items are present", () => { - const traderHelper = container.resolve("TraderHelper"); - const insurance = insuranceFixture[0]; const sessionID = "session-id"; const insuranceFailedTpl = "failed-message-template"; @@ -1311,12 +1326,12 @@ describe("InsuranceController", () => // Verify that the insurance failed message was not sent. expect(sendMessageSpy).toHaveBeenCalledWith( sessionID, - traderHelper.getTraderById(insurance.traderId), + insuranceController.traderHelper.getTraderById(insurance.traderId), MessageType.INSURANCE_RETURN, - insurance.messageContent.templateId, + insurance.messageTemplateId, insurance.items, - insurance.messageContent.maxStorageTime, - insurance.messageContent.systemData, + insurance.maxStorageTime, + insurance.systemData, ); }); }); @@ -1519,14 +1534,17 @@ describe("InsuranceController", () => expect(pmcData.InsuredItems.length).toBe(body.items.length); }); - it("should return the output with warnings if payment fails", () => + it("should update output with warnings if payment fails", () => { // Override the payMoney mock to simulate a payment failure with a warning. const expectedPayMoneyReturn = { - warnings: [{ index: 0, errmsg: "Not enough money to complete transaction", code: 500 }], + warnings: [{ index: 0, errmsg: "You broke.", code: 500 }], otherProperty: "property-value", }; - mockPayMoney.mockReturnValue(expectedPayMoneyReturn); + mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => + { + output.warnings = expectedPayMoneyReturn.warnings; + }); // Execute the method. const response = insuranceController.insure(pmcData, body, sessionId); @@ -1542,10 +1560,13 @@ describe("InsuranceController", () => { // Override the payMoney mock to simulate a payment failure with a warning. const expectedPayMoneyReturn = { - warnings: [{ index: 0, errmsg: "Not enough money to complete transaction", code: 500 }], + warnings: [{ index: 0, errmsg: "You broke.", code: 500 }], otherProperty: "property-value", }; - mockPayMoney.mockReturnValue(expectedPayMoneyReturn); + mockPayMoney.mockImplementation((pmcData, request, sessionID, output) => + { + output.warnings = expectedPayMoneyReturn.warnings; + }); // Execute the method. insuranceController.insure(pmcData, body, sessionId); diff --git a/project/tests/generators/BotGenerator.test.ts b/project/tests/generators/BotGenerator.test.ts index 05d9f402..6562bcae 100644 --- a/project/tests/generators/BotGenerator.test.ts +++ b/project/tests/generators/BotGenerator.test.ts @@ -55,94 +55,157 @@ describe("BotGenerator", () => describe("generateBotNickname", () => { - it("should return single name `test` for non pscav assault bot name ", () => + it("should choose random firstname for non player scav assault bot", () => { + const botJsonTemplate = { firstName: ["one", "two"], lastName: [] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; - vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - const botJsonTemplate = { firstName: ["test"], lastName: [] }; + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); - const sessionId = "sessionId"; - const isPlayerScav = false; - const botRole = "assault"; - - const result = botGenerator.generateBotNickname(botJsonTemplate, isPlayerScav, botRole, sessionId); - expect(result).toBe("test"); + expect(result).toMatch(/(one|two)/); }); - it("should return `test assault` for non pscav assault bot with `showTypeInNickname` enabled ", () => + it("should choose random lastname for non player scav assault bot", () => { + const botJsonTemplate = { firstName: [], lastName: [["one", "two"]] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; + + const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; + vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); + + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + + expect(result).toMatch(/(one|two)/); + }); + + it("should choose random firstname and lastname for non player scav assault bot", () => + { + const botJsonTemplate = { firstName: ["first-one", "first-two"], lastName: [["last-one", "last-two"]] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; + + const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; + vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); + + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + + expect(result).toMatch(/first-(one|two) last-(one|two)/); + }); + + it("should choose random firstname for player scav assault bot", () => + { + const botJsonTemplate = { firstName: ["one", "two"], lastName: [] }; + const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; + + const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; + vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); + + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + + expect(result).toMatch(/(one|two)/); + }); + + it("should choose random lastname for player scav assault bot", () => + { + const botJsonTemplate = { firstName: [], lastName: [["one", "two"]] }; + const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; + + const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; + vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); + + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + + expect(result).toMatch(/(one|two)/); + }); + + it("should choose random firstname and lastname for player scav assault bot", () => + { + const botJsonTemplate = { firstName: ["first-one", "first-two"], lastName: [["last-one", "last-two"]] }; + const botGenerationDetails = { isPlayerScav: true, isPmc: false, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; + + const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; + vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); + + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + + expect(result).toMatch(/first-(one|two) last-(one|two)/); + }); + + it("should append bot type to end of name when showTypeInNickname option is enabled ", () => + { + const botJsonTemplate = { firstName: ["firstname"], lastName: ["lastname"] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 0; botGenerator.botConfig.showTypeInNickname = true; const mockPlayerProfile = { Info: { Nickname: "Player Nickname", Level: 1 } }; vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - const botJsonTemplate = { firstName: ["test"], lastName: [] }; + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); - const sessionId = "sessionId"; - const isPlayerScav = false; - const botRole = "assault"; - - const result = botGenerator.generateBotNickname(botJsonTemplate, isPlayerScav, botRole, sessionId); - expect(result).toBe("test assault"); + expect(result).toBe("firstname lastname assault"); }); - it("should return name `test Player` for bot with same name as player and `addPrefixToSameNamePMCAsPlayerChance` 100%", () => + it("should return name prefix for PMC bot with same name as player if allPmcsHaveSameNameAsPlayer is enabled", () => { + const botJsonTemplate = { firstName: ["player"], lastName: [] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: true }; + const botRole = "assault"; + botGenerator.botConfig.showTypeInNickname = false; botGenerator.pmcConfig.addPrefixToSameNamePMCAsPlayerChance = 100; - const mockPlayerProfile = { Info: { Nickname: "Player", Level: 1 } }; - vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - vi.spyOn(botGenerator.localisationService, "getRandomTextThatMatchesPartialKey").mockReturnValue("test"); - - const botJsonTemplate = { firstName: ["Player"], lastName: [] }; - - const sessionId = "sessionId"; - const isPlayerScav = false; - const botRole = "assault"; - - const result = botGenerator.generateBotNickname(botJsonTemplate, isPlayerScav, botRole, sessionId); - expect(result).toBe("test Player"); - }); - - it("should return name `test` for player scav bot", () => - { - botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 100; - - const mockPlayerProfile = { Info: { Nickname: "Player", Level: 1 } }; + const mockPlayerProfile = { Info: { Nickname: "player", Level: 1 } }; vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - const botJsonTemplate = { firstName: ["test"], lastName: [] }; + const getRandomTextThatMatchesPartialKeySpy = vi.spyOn( + (botGenerator as any).localisationService, + "getRandomTextThatMatchesPartialKey", + ).mockReturnValue("test"); - const sessionId = "sessionId"; - const isPlayerScav = true; - const botRole = "assault"; + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); - const result = botGenerator.generateBotNickname(botJsonTemplate, isPlayerScav, botRole, sessionId); - expect(result).toBe("test"); + expect(getRandomTextThatMatchesPartialKeySpy).toHaveBeenCalled(); + expect(result).toBe("test player"); }); - it("should return name `test (usec)` for player scav bot", () => + it("should generate PMC name in brackets behind scav name when chanceAssaultScavHasPlayerScavName is enabled", () => { + const botJsonTemplate = { firstName: ["scav"], lastName: [] }; + const botGenerationDetails = { isPlayerScav: false, isPmc: true, allPmcsHaveSameNameAsPlayer: false }; + const botRole = "assault"; + botGenerator.botConfig.chanceAssaultScavHasPlayerScavName = 100; - botGenerator.databaseServer.getTables().bots.types.usec.firstName = ["usec"]; + botGenerator.databaseServer.getTables().bots.types.usec.firstName = ["player"]; botGenerator.databaseServer.getTables().bots.types.bear.firstName = []; const mockPlayerProfile = { Info: { Nickname: "Player", Level: 1 } }; vi.spyOn(botGenerator.profileHelper, "getPmcProfile").mockReturnValue(mockPlayerProfile); - const botJsonTemplate = { firstName: ["test"], lastName: [] }; - - const sessionId = "sessionId"; - const isPlayerScav = false; - const botRole = "assault"; - - const result = botGenerator.generateBotNickname(botJsonTemplate, isPlayerScav, botRole, sessionId); - expect(result).toBe("test (usec)"); + const result = botGenerator.generateBotNickname(botJsonTemplate, botGenerationDetails, botRole); + expect(result).toBe("scav (player)"); }); }); }); diff --git a/project/tests/generators/BotLevelGenerator.test.ts b/project/tests/generators/BotLevelGenerator.test.ts index 8d8815a6..1def6ee4 100644 --- a/project/tests/generators/BotLevelGenerator.test.ts +++ b/project/tests/generators/BotLevelGenerator.test.ts @@ -35,6 +35,7 @@ describe("BotLevelGenerator", () => side: "", playerLevel: 5, botRelativeLevelDeltaMax: 0, + botRelativeLevelDeltaMin: 0, botCountToGenerate: 0, botDifficulty: "", isPlayerScav: false, diff --git a/project/tests/helpers/HandbookHelper.test.ts b/project/tests/helpers/HandbookHelper.test.ts index 0747f1a7..9509a02f 100644 --- a/project/tests/helpers/HandbookHelper.test.ts +++ b/project/tests/helpers/HandbookHelper.test.ts @@ -88,10 +88,26 @@ describe("HandbookHelper", () => expect(result).toBe(0); }); - it("should return roughly 1380 roubles when given 10 euros ", () => + it("should lookup currency value and multiply the input by the value", () => { - const result = handbookHelper.inRUB(10, Money.EUROS); - expect(result).closeTo(1379, 10); + // Mock the getTemplatePrice method to return a value of 100 roubles + const getTemplatePriceSpy = vi.spyOn(handbookHelper, "getTemplatePrice").mockReturnValue(100); + + const result = handbookHelper.inRUB(5, Money.EUROS); + + expect(getTemplatePriceSpy).toHaveBeenCalled(); + expect(result).toBe(500); + }); + + it("should always return a whole number", () => + { + // Mock the getTemplatePrice method to return a value of 100 roubles + const getTemplatePriceSpy = vi.spyOn(handbookHelper, "getTemplatePrice").mockReturnValue(123.321); + + const result = handbookHelper.inRUB(12.21, Money.EUROS); + + expect(getTemplatePriceSpy).toHaveBeenCalled(); + expect(result).toBe(1506); }); }); diff --git a/project/tests/helpers/InRaidHelper.test.ts b/project/tests/helpers/InRaidHelper.test.ts index d13f2e91..b9bf02ad 100644 --- a/project/tests/helpers/InRaidHelper.test.ts +++ b/project/tests/helpers/InRaidHelper.test.ts @@ -3,7 +3,8 @@ import { container } from "tsyringe"; import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { InRaidHelper } from "@spt-aki/helpers/InRaidHelper"; -import { DatabaseServer } from "@spt-aki/servers/DatabaseServer"; + +import { IPmcData } from "@spt-aki/models/eft/common/IPmcData"; describe("InRaidHelper", () => { @@ -19,67 +20,32 @@ describe("InRaidHelper", () => vi.restoreAllMocks(); }); - describe("calculateFenceStandingChangeFromKills", () => + describe("resetSkillPointsEarnedDuringRaid", () => { - it("should return negative value when player kills 2 scavs as scav", () => + it("should reset PointsEarnedDuringSession for each skill in profile", () => { - const fenceStanding = 0; - const postRaidPlayerVictims = [{ Side: "Savage", Role: "assault" }, { Side: "Savage", Role: "assault" }]; // Kills + const mockProfile = { + Skills: { + Common: [ + { Id: "BotReload", Progress: 160.543, PointsEarnedDuringSession: 42, LastAccess: 1712633904 }, + { Id: "BotSound", Progress: 145.6547, PointsEarnedDuringSession: 42, LastAccess: 1712633904 }, + { + Id: "Endurance", + Progress: 223.951157, + PointsEarnedDuringSession: 42, + LastAccess: 1712633904, + }, + { Id: "Strength", Progress: 141.2618, PointsEarnedDuringSession: 42, LastAccess: 1712633904 }, + ], + }, + }; - const databaseServer = container.resolve("DatabaseServer"); - const scavStandingChangeOnKill = databaseServer.getTables().bots.types.assault.experience.standingForKill; + (inraidHelper as any).resetSkillPointsEarnedDuringRaid(mockProfile); - const result = inraidHelper.calculateFenceStandingChangeFromKills(fenceStanding, postRaidPlayerVictims); - expect(result).toBe(scavStandingChangeOnKill * postRaidPlayerVictims.length); // Scav rep loss times number of scav kills - expect(result).lessThan(0); - }); - - it("should return positive value when player kills 2 PMCs of different sides as scav", () => - { - const fenceStanding = 0; - const postRaidPlayerVictims = [{ Side: "Usec", Role: "sptUsec" }, { Side: "Bear", Role: "sptBear" }]; // Kills - - const databaseServer = container.resolve("DatabaseServer"); - const bearStandingChangeOnKill = databaseServer.getTables().bots.types.bear.experience.standingForKill; - const usecStandingChangeOnKill = databaseServer.getTables().bots.types.bear.experience.standingForKill; - - const result = inraidHelper.calculateFenceStandingChangeFromKills(fenceStanding, postRaidPlayerVictims); - expect(result).toBe(bearStandingChangeOnKill + usecStandingChangeOnKill); - expect(result).greaterThan(0); - }); - - it("should return negative value when player kills 1 PMC, 1 boss and 2 scavs as scav", () => - { - const fenceStanding = 0; - const postRaidPlayerVictims = [{ Side: "Usec", Role: "sptUsec" }, { Side: "savage", Role: "assault" }, { - Side: "savage", - Role: "bossBoar", - }, { Side: "savage", Role: "assault" }]; // Kills - - const databaseServer = container.resolve("DatabaseServer"); - const usecStandingChangeOnKill = databaseServer.getTables().bots.types.bear.experience.standingForKill; - const scavStandingChangeOnKill = databaseServer.getTables().bots.types.assault.experience.standingForKill; - const bossBoarStandingChangeOnKill = - databaseServer.getTables().bots.types.bossboar.experience.standingForKill; - - const result = inraidHelper.calculateFenceStandingChangeFromKills(fenceStanding, postRaidPlayerVictims); - expect(result).toBe( - usecStandingChangeOnKill + (scavStandingChangeOnKill * 2) + bossBoarStandingChangeOnKill, - ); - expect(result).lessThan(0); - }); - - it("should return 0 when player kills bot with undefined standing as scav", () => - { - const fenceStanding = 0; - const postRaidPlayerVictims = [{ Side: "savage", Role: "testRole" }]; // Kills - - // Fake getFenceStandingChangeForKillAsScav() returning null - vi.spyOn(inraidHelper, "getFenceStandingChangeForKillAsScav").mockReturnValueOnce(null).mockReturnValueOnce( - null, - ); - const result = inraidHelper.calculateFenceStandingChangeFromKills(fenceStanding, postRaidPlayerVictims); - expect(result).toBe(0); + for (const skill of mockProfile.Skills.Common) + { + expect(skill.PointsEarnedDuringSession).toBe(0); + } }); }); }); diff --git a/project/tests/helpers/ItemHelper.test.ts b/project/tests/helpers/ItemHelper.test.ts index 8e875727..a732ffe1 100644 --- a/project/tests/helpers/ItemHelper.test.ts +++ b/project/tests/helpers/ItemHelper.test.ts @@ -275,44 +275,6 @@ describe("ItemHelper", () => }); }); - describe("generateItemsFromStackSlot", () => - { - it("should generate valid StackSlot item for an AmmoBox", () => - { - const ammoBox = itemHelper.getItem("57372c89245977685d4159b1"); // "5.45x39mm BT gs ammo pack (30 pcs)" - const parentId = container.resolve("HashUtil").generate(); - - const result = itemHelper.generateItemsFromStackSlot(ammoBox[1], parentId); - - expect(result.length).toBe(1); - expect(result[0]._id).toBeDefined(); - expect(result[0]._tpl).toBe(ammoBox[1]._props.StackSlots[0]._props.filters[0].Filter[0]); - expect(result[0].parentId).toBe(parentId); - expect(result[0].slotId).toBe("cartridges"); - expect(result[0].location).toBe(0); - expect(result[0].upd.StackObjectsCount).toBe(ammoBox[1]._props.StackSlots[0]._max_count); - }); - - it("should log a warning if no IDs are found in Filter", () => - { - const ammoBox = itemHelper.getItem("57372c89245977685d4159b1"); // "5.45x39mm BT gs ammo pack (30 pcs)" - ammoBox[1]._props.StackSlots[0]._props.filters[0].Filter = []; // Empty the Filter array. - - const parentId = container.resolve("HashUtil").generate(); - - // Spy on the logger's warning method and mock its implementation to prevent it from being actually called. - const loggerWarningSpy = vi.spyOn((itemHelper as any).logger, "warning").mockImplementation(() => - {}); - - itemHelper.generateItemsFromStackSlot(ammoBox[1], parentId); - - expect(loggerWarningSpy).toHaveBeenCalled(); - - // Restore the original behavior - loggerWarningSpy.mockRestore(); - }); - }); - describe("getItems", () => { it("should call databaseServer.getTables() and jsonUtil.clone() methods", () => @@ -451,12 +413,16 @@ describe("ItemHelper", () => const itemId = container.resolve("HashUtil").generate(); const item: Item = { _id: itemId, - _tpl: "5b40e1525acfc4771e1c6611", // "HighCom Striker ULACH IIIA helmet (Black)" + _tpl: "5b40e1525acfc4771e1c6611", upd: { Repairable: { Durability: 19, MaxDurability: 38 } }, }; + const getRepairableItemQualityValueSpt = vi.spyOn(itemHelper as any, "getRepairableItemQualityValue") + .mockReturnValue(0.5); + const result = itemHelper.getItemQualityModifier(item); + expect(getRepairableItemQualityValueSpt).toHaveBeenCalled(); expect(result).toBe(0.5); }); @@ -556,40 +522,7 @@ describe("ItemHelper", () => describe("getRepairableItemQualityValue", () => { - it("should return the correct quality value for armor items", () => - { - const armor = itemHelper.getItem("5648a7494bdc2d9d488b4583")[1]; // "PACA Soft Armor" - const repairable: Repairable = { Durability: 25, MaxDurability: 50 }; - const item: Item = { // Not used for armor, but required for the method. - _id: "", - _tpl: "", - }; - - // Cast the method to any to allow access to private/protected method. - const result = (itemHelper as any).getRepairableItemQualityValue(armor, repairable, item); - - expect(result).toBe(0.5); - }); - - it("should not use the Repairable MaxDurability property for armor", () => - { - const armor = itemHelper.getItem("5648a7494bdc2d9d488b4583")[1]; // "PACA Soft Armor" - const repairable: Repairable = { - Durability: 25, - MaxDurability: 1000, // This should be ignored. - }; - const item: Item = { // Not used for armor, but required for the method. - _id: "", - _tpl: "", - }; - - // Cast the method to any to allow access to private/protected method. - const result = (itemHelper as any).getRepairableItemQualityValue(armor, repairable, item); - - expect(result).toBe(0.5); - }); - - it("should return the correct quality value for weapon items", () => + it("should return the correct quality value", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" const repairable: Repairable = { Durability: 50, MaxDurability: 100 }; @@ -601,7 +534,7 @@ describe("ItemHelper", () => expect(result).toBe(Math.sqrt(0.5)); }); - it("should fall back to using Repairable MaxDurability for weapon items", () => + it("should fall back to using Repairable MaxDurability", () => { const weapon = itemHelper.getItem("5a38e6bac4a2826c6e06d79b")[1]; // "TOZ-106 20ga bolt-action shotgun" weapon._props.MaxDurability = undefined; // Remove the MaxDurability property. @@ -941,6 +874,74 @@ describe("ItemHelper", () => }); }); + describe("adoptOrphanedItems", () => + { + it("should adopt orphaned items by resetting them as base-level items", () => + { + const rootId = "root-id"; + const items = [ + { _id: "first-id", _tpl: "anything1", parentId: "does-not-exist", slotId: "main" }, + { _id: "second-id", _tpl: "anything2", parentId: "first-id", slotId: "slot-id" }, + { _id: "third-id", _tpl: "anything3", parentId: "second-id", slotId: "slot-id" }, + { _id: "forth-id", _tpl: "anything4", parentId: "third-id", slotId: "slot-id" }, + ]; + + // Iterate over the items and find the individual orphaned item. + const orphanedItem = items.find((item) => !items.some((parent) => parent._id === item.parentId)); + + // Setup tests to verify that the orphaned item is in fact orphaned. + expect(orphanedItem.parentId).toBe(items[0].parentId); + expect(orphanedItem.slotId).toBe(items[0].slotId); + + // Execute the method. + (itemHelper as any).adoptOrphanedItems(rootId, items); + + // Verify that the orphaned items have been adopted. + expect(orphanedItem.parentId).toBe(rootId); + expect(orphanedItem.slotId).toBe("hideout"); + }); + + it("should not adopt items that are not orphaned", () => + { + const rootId = "root-id"; + const items = [ + { _id: "first-id", _tpl: "anything1", parentId: rootId, slotId: "hideout" }, + { _id: "second-id", _tpl: "anything2", parentId: "first-id", slotId: "slot-id" }, + { _id: "third-id", _tpl: "anything3", parentId: "second-id", slotId: "slot-id" }, + { _id: "forth-id", _tpl: "anything4", parentId: "third-id", slotId: "slot-id" }, + ]; + + // Execute the method. + const adopted = (itemHelper as any).adoptOrphanedItems(rootId, items); + + // Verify that the orphaned items have been adopted. + expect(adopted).toStrictEqual(items); + }); + + it("should remove location data from adopted items", () => + { + const rootId = "root-id"; + const items = [ + { + _id: "first-id", + _tpl: "anything1", + parentId: "does-not-exist", + slotId: "main", + location: { x: 1, y: 2, r: 3, isSearched: true }, // Should be removed. + }, + { _id: "second-id", _tpl: "anything2", parentId: "first-id", slotId: "slot-id" }, + { _id: "third-id", _tpl: "anything3", parentId: "second-id", slotId: "slot-id" }, + { _id: "forth-id", _tpl: "anything4", parentId: "third-id", slotId: "slot-id" }, + ]; + + // Execute the method. + (itemHelper as any).adoptOrphanedItems(rootId, items); + + // Verify that the location property has been removed. + expect(items).not.toHaveProperty("location"); + }); + }); + describe("splitStack", () => { it("should return array of two items when provided item over its natural stack size limit", () => diff --git a/project/tests/services/ItemBaseClassService.test.ts b/project/tests/services/ItemBaseClassService.test.ts index eee0d619..1fedba8d 100644 --- a/project/tests/services/ItemBaseClassService.test.ts +++ b/project/tests/services/ItemBaseClassService.test.ts @@ -42,23 +42,23 @@ describe("ItemBaseClassService", () => it("should return false when the base item type is passed in", () => { // Remove item from base cache - const result = itemBaseClassService.itemHasBaseClass("54009119af1c881c07000029", []); // "Base item" + const result = itemBaseClassService.itemHasBaseClass("54009119af1c881c07000029", []); expect(result).toBe(false); }); - it("should return true when an item is passed in", () => + it("should return true when a med item is passed in with the meds base class", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; // Remove item from base cache delete itemBaseClassService.itemBaseClassesCache[salewaTpl]; - const result = itemBaseClassService.itemHasBaseClass(salewaTpl, ["543be5664bdc2dd4348b4569"]); // "Meds" type + const result = itemBaseClassService.itemHasBaseClass(salewaTpl, ["543be5664bdc2dd4348b4569"]); expect(result).toBe(true); }); - it("should return true when an item and 2 matching base classes are passed in", () => + it("should return true when an item and two matching base classes are passed in", () => { const salewaTpl = "544fb45d4bdc2dee738b4568"; @@ -67,7 +67,7 @@ describe("ItemBaseClassService", () => const result = itemBaseClassService.itemHasBaseClass(salewaTpl, [ "543be5664bdc2dd4348b4569", "54009119af1c881c07000029", - ]); // "Meds" and "Item" type + ]); // "Meds" and "Item" base classes expect(result).toBe(true); }); @@ -84,15 +84,28 @@ describe("ItemBaseClassService", () => delete itemBaseClassService.itemBaseClassesCache[salewaTpl]; // Perform check - const result = itemBaseClassService.itemHasBaseClass(salewaTpl, ["543be5664bdc2dd4348b4569"]); // "Meds" type + const result = itemBaseClassService.itemHasBaseClass(salewaTpl, ["543be5664bdc2dd4348b4569"]); expect(result).toBe(true); expect(hydrateItemBaseClassCacheSpy).toHaveBeenCalled(); }); - it("should throw an exception when an invalid item is passed in", () => + it("should return false for any item template ID that does not exist", () => { - expect(() => itemBaseClassService.itemHasBaseClass("fakeTpl", ["543be5664bdc2dd4348b4569"])).toThrowError(); + const result = itemBaseClassService.itemHasBaseClass("not-a-valid-template-id", [ + "543be5664bdc2dd4348b4569", + ]); + + expect(result).toBe(false); + }); + + it("should return false for any item template ID without the Item type ", () => + { + const result = itemBaseClassService.itemHasBaseClass("54009119af1c881c07000029", [ + "543be5664bdc2dd4348b4569", + ]); + + expect(result).toBe(false); }); }); diff --git a/project/tests/services/PaymentService.test.ts b/project/tests/services/PaymentService.test.ts index cea1dae3..9f97f17c 100644 --- a/project/tests/services/PaymentService.test.ts +++ b/project/tests/services/PaymentService.test.ts @@ -71,48 +71,50 @@ describe("PaymentService", () => const itemEventRouterResponse = { warnings: [], - profileChanges: { sessionID: { _id: sessionID, items: { new: [], change: [], del: [] } } }, + profileChanges: { [sessionID]: { _id: sessionID, items: { new: [], change: [], del: [] } } }, } as unknown as IItemEventRouterResponse; // Mock the logger debug method to return void. - vi.spyOn((paymentService as any).logger, "debug").mockImplementation(() => - {}); + vi.spyOn((paymentService as any).logger, "debug").mockResolvedValue(undefined); // Mock the trader helper to return a trader with the currency of Roubles. - const traderHelperGetTraderSpy = vi.spyOn((paymentService as any).traderHelper, "getTrader") - .mockReturnValue({ tid: traderId, currency: "RUB" } as unknown as ITraderBase); + const getTraderSpy = vi.spyOn((paymentService as any).traderHelper, "getTrader").mockReturnValue( + { tid: traderId, currency: "RUB" } as unknown as ITraderBase, + ); // Mock the addPaymentToOutput method to subtract the item cost from the money stack. - const addPaymentToOutputSpy = vi.spyOn(paymentService as any, "addPaymentToOutput").mockImplementation(() => - { - moneyItem.upd.StackObjectsCount -= costAmount; - return { warnings: [], profileChanges: { [sessionID]: { items: { change: [moneyItem] } } } }; - }); + const addPaymentToOutputSpy = vi.spyOn(paymentService as any, "addPaymentToOutput").mockImplementation( + ( + pmcData: IPmcData, + currencyTpl: string, + amountToPay: number, + sessionIdentifier: string, + output: IItemEventRouterResponse, + ) => + { + moneyItem.upd.StackObjectsCount -= costAmount; + output.profileChanges[sessionIdentifier].items.change.push(moneyItem); + }, + ); // Mock the traderHelper lvlUp method to return void. - const traderHelperLvlUpSpy = vi.spyOn((paymentService as any).traderHelper, "lvlUp").mockImplementation( - () => - {}, - ); + const lvlUpSpy = vi.spyOn((paymentService as any).traderHelper, "lvlUp").mockResolvedValue(undefined); - const output = paymentService.payMoney( - pmcData, - processBuyTradeRequestData, - sessionID, - itemEventRouterResponse, - ); + paymentService.payMoney(pmcData, processBuyTradeRequestData, sessionID, itemEventRouterResponse); // Check for absence of output warnings. - expect(output.warnings).toHaveLength(0); + expect(itemEventRouterResponse.warnings).toHaveLength(0); // Check that the currency change was correctly handled. - expect(output.profileChanges[sessionID].items.change).toHaveLength(1); - expect(output.profileChanges[sessionID].items.change[0]._id).toBe(costItemId); - expect(output.profileChanges[sessionID].items.change[0]._tpl).toBe(costItemTpl); - expect(output.profileChanges[sessionID].items.change[0].upd.StackObjectsCount).toBe(costAmount * 3); + expect(itemEventRouterResponse.profileChanges[sessionID].items.change).toHaveLength(1); + expect(itemEventRouterResponse.profileChanges[sessionID].items.change[0]._id).toBe(costItemId); + expect(itemEventRouterResponse.profileChanges[sessionID].items.change[0]._tpl).toBe(costItemTpl); + expect(itemEventRouterResponse.profileChanges[sessionID].items.change[0].upd.StackObjectsCount).toBe( + costAmount * 3, + ); // Check if mocked methods were called as expected. - expect(traderHelperGetTraderSpy).toBeCalledTimes(1); + expect(getTraderSpy).toBeCalledTimes(1); expect(addPaymentToOutputSpy).toBeCalledWith( expect.anything(), costItemTpl, @@ -120,7 +122,7 @@ describe("PaymentService", () => sessionID, expect.anything(), ); - expect(traderHelperLvlUpSpy).toBeCalledTimes(1); + expect(lvlUpSpy).toBeCalledTimes(1); }); }); diff --git a/project/tests/services/PlayerService.test.ts b/project/tests/services/PlayerService.test.ts index 6c731861..fd03934c 100644 --- a/project/tests/services/PlayerService.test.ts +++ b/project/tests/services/PlayerService.test.ts @@ -61,11 +61,11 @@ describe("PlayerService", () => expect(result).toBe(25); }); - it("should return 79 when player xp is 68,206,066", () => + it("should return 79 when player xp is 81,126,895", () => { const playerProfile = { Info: { - Experience: 68206066, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels + Experience: 81126895, // Via wiki: https://escapefromtarkov.fandom.com/wiki/Character_skills#Levels }, }; diff --git a/project/tests/services/ProfileFixerService.test.ts b/project/tests/services/ProfileFixerService.test.ts new file mode 100644 index 00000000..bc9b6c89 --- /dev/null +++ b/project/tests/services/ProfileFixerService.test.ts @@ -0,0 +1,39 @@ +import { ProfileFixerService } from "@spt-aki/services/ProfileFixerService"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +describe("ProfileFixerService", () => +{ + let profileFixerService: any; // Using "any" to access private/protected methods without type errors. + + beforeEach(() => + { + profileFixerService = container.resolve("ProfileFixerService"); + }); + + afterEach(() => + { + vi.restoreAllMocks(); + }); + + describe("FixPmcProfileIssues", () => + { + it("should reset nextResupply to 0 when it is null", () => + { + const pmcProfile = { TradersInfo: { traderId: { nextResupply: null } } }; + + profileFixerService.fixNullTraderNextResupply(pmcProfile); + + expect(pmcProfile.TradersInfo.traderId.nextResupply).toBe(0); + }); + + it("should not reset nextResupply to 0 when it is not null", () => + { + const pmcProfile = { TradersInfo: { traderId: { nextResupply: 1234 } } }; + + profileFixerService.fixNullTraderNextResupply(pmcProfile); + + expect(pmcProfile.TradersInfo.traderId.nextResupply).toBe(1234); + }); + }); +}); diff --git a/project/tests/services/RagfairPriceService.test.ts b/project/tests/services/RagfairPriceService.test.ts new file mode 100644 index 00000000..8ae6fee2 --- /dev/null +++ b/project/tests/services/RagfairPriceService.test.ts @@ -0,0 +1,501 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import "reflect-metadata"; +import { container } from "tsyringe"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; + +import { RagfairPriceService } from "@spt-aki/services/RagfairPriceService"; + +import { MinMax } from "@spt-aki/models/common/MinMax"; +import { Money } from "@spt-aki/models/enums/Money"; + +describe("RagfairPriceService", () => +{ + let ragfairPriceService: any; // Using "any" to access private/protected methods without type errors. + + beforeEach(() => + { + ragfairPriceService = container.resolve("RagfairPriceService"); + }); + + afterEach(() => + { + vi.restoreAllMocks(); + }); + + describe("getDynamicOfferPriceForOffer", () => + { + it("should return zero when empty offerItems array is passed", () => + { + const offerItems = []; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toEqual(0); + }); + + it("should return non-zero number when valid item is passed", () => + { + const offerItems = [{ + _id: "d445ea263cdfc5f278334264", + _tpl: "57e3dba62459770f0c32322b", + parentId: "631abbff398cc0170cbd3089", + slotId: "mod_pistol_grip", + }]; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + const expectedPrice = 42069; + + // Mock the getDynamicItemPrice method to return a static price. + vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue(expectedPrice); + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toBe(expectedPrice); + }); + + it("should always return a whole number", () => + { + const offerItems = [{ + _id: "d445ea263cdfc5f278334264", + _tpl: "57e3dba62459770f0c32322b", + parentId: "631abbff398cc0170cbd3089", + slotId: "mod_pistol_grip", + }]; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + const originalPrice = 42069.999999999; + + // Mock the getDynamicItemPrice method to return a static price. + vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue(originalPrice); + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toBeGreaterThan(originalPrice); + expect(price).toBe(Math.round(originalPrice)); + }); + + it("should skip prices for soft armour inserts", () => + { + const offerItems = [{ + _id: "d445ea263cdfc5f278334264", + _tpl: "657080a212755ae0d907ad04", + parentId: "631abbff398cc0170cbd3089", + slotId: "Soft_armor_front", + }]; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + + // Mock the getDynamicItemPrice method. + const getDynamicItemPriceSpy = vi.spyOn(ragfairPriceService, "getDynamicItemPrice"); + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toBe(0); + expect(getDynamicItemPriceSpy).not.toHaveBeenCalled(); + }); + + it("should not add value of mods to weapon preset", () => + { + const offerItems = [{ + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 90, MaxDurability: 90 }, + }, + }, { + _id: "59c6897a59ed48f1ca02f659", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_magazine", + }, { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, { + _id: "3b09149e8b7833dc5fdd32a4", + _tpl: "63c6adcfb4ba094317063742", + parentId: "7e8062d4bc57b56927c2d117", + slotId: "mod_sight_rear", + }, { + _id: "e833a5c26af29870df9cdd2e", + _tpl: "6374a7e7417239a7bf00f042", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_pistolgrip", + }]; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + const expectedPrice = 10000; + + // Mock the getDynamicItemPrice method to return a static price. + const getDynamicItemPriceSpy = vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue( + expectedPrice, + ); + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toBe(expectedPrice); + expect(getDynamicItemPriceSpy).toHaveBeenCalledTimes(1); + }); + + it("should sum value of all offer items", () => + { + const offerItems = [{ + _id: "59c6897a59ed48f1ca02f659", + _tpl: "5448c12b4bdc2d02308b456f", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_magazine", + }, { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }, { + _id: "3b09149e8b7833dc5fdd32a4", + _tpl: "63c6adcfb4ba094317063742", + parentId: "7e8062d4bc57b56927c2d117", + slotId: "mod_sight_rear", + }, { + _id: "e833a5c26af29870df9cdd2e", + _tpl: "6374a7e7417239a7bf00f042", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_pistolgrip", + }]; + const desiredCurrency = Money.ROUBLES; + const isPackOffer = false; + const expectedPrice = 10000; + + // Mock the getDynamicItemPrice method to return a static price. + const getDynamicItemPriceSpy = vi.spyOn(ragfairPriceService, "getDynamicItemPrice").mockReturnValue( + expectedPrice, + ); + + const price = ragfairPriceService.getDynamicOfferPriceForOffer(offerItems, desiredCurrency, isPackOffer); + + expect(price).toBe(expectedPrice * offerItems.length); + expect(getDynamicItemPriceSpy).toHaveBeenCalledTimes(offerItems.length); + }); + }); + + describe("getDynamicItemPrice", () => + { + it("should not return zero for a valid template ID", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.ROUBLES; + + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(price).not.toBe(0); + }); + + it("should use trader price if it is higher than flea price and configuration allows it", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.ROUBLES; + const mockTraderPrice = 20000; + const mockFleaPrice = 15000; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + + // Mock the configs to allow using trader price if higher. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = true; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock the getFleaPriceForItem method to return a static price. + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); + + // Mock the getHighestSellToTraderPrice method to return a higher static price. + vi.spyOn((ragfairPriceService as any).traderHelper, "getHighestSellToTraderPrice").mockReturnValue( + mockTraderPrice, + ); + + // Mock the getOfferTypeRangeValues method to return a static minMax. + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(price).toBe(mockTraderPrice); + }); + + it("should adjust flea price when below handbook price and configuration allows it", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.ROUBLES; + const mockFleaPrice = 1; + const handbookPrice = 10000; + const adjustedPrice = 9000; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + + // Enable adjustment for prices below handbook price. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = true; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock the getFleaPriceForItem method to return a static price below the handbook price. + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); + + // Mock the adjustPriceIfBelowHandbook method to simulate price adjustment. + vi.spyOn(ragfairPriceService, "adjustPriceIfBelowHandbook").mockImplementation( + (price: number, templateId) => + { + return price < handbookPrice ? adjustedPrice : price; + }, + ); + + // Mock the getOfferTypeRangeValues method to return a static minMax. + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + // Verify the price is adjusted correctly according to the mocked handbook price adjustment logic. + expect(price).toBe(adjustedPrice); + }); + + it("should handle weapon preset prices correctly", () => + { + const itemTemplateId = "579204f224597773d619e051"; + const desiredCurrency = Money.ROUBLES; + const mockPresetPrice = 25000; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + const offerItems = [{ + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 90, MaxDurability: 90 }, + }, + }, { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }]; + const item = offerItems[0]; + + // Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock getFleaPriceForItem to bypass initial flea price fetch + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(0); + + // Mock the isPresetBaseClass method to return true for the item + vi.spyOn((ragfairPriceService as any).presetHelper, "isPresetBaseClass").mockReturnValue(true); + + // Mock the getWeaponPresetPrice method to return a specific preset price + const getWeaponPresetPriceSpy = vi.spyOn(ragfairPriceService, "getWeaponPresetPrice").mockReturnValue( + mockPresetPrice, + ); + + // Mock the getOfferTypeRangeValues method to return a static minMax. + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Mock the getItemQualityModifier method to return 1 (no change) + vi.spyOn((ragfairPriceService as any).itemHelper, "getItemQualityModifier").mockReturnValue(1); + + // Call the method with the mock item and offer items + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency, item, offerItems); + + // Call the method. + expect(price).toBe(mockPresetPrice); + + // Additionally, you can verify that getWeaponPresetPrice was called with the correct parameters + expect(getWeaponPresetPriceSpy).toHaveBeenCalledWith(item, offerItems, expect.any(Number)); + }); + + it("should update price based on the ragfair config item price multiplier values", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.ROUBLES; + const mockFleaPrice = 20000; + const itemPriceMultiplier = 2; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + + // Mock the ragfair config to have a price multiplier of 2. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = itemPriceMultiplier; + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + + // Mock the getFleaPriceForItem method to return a static price. + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); + + // Mock the getOfferTypeRangeValues method to return a static minMax. + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(price).toBe(mockFleaPrice * itemPriceMultiplier); + }); + + it("should adjust price when durability is not perfect", () => + { + const itemTemplateId = "579204f224597773d619e051"; + const desiredCurrency = Money.ROUBLES; + const mockPrice = 25000; + const mockDurabilityMulti = 0.5; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + const offerItems = [{ + _id: "344d02bbf2102ce4e145bf35", + _tpl: "579204f224597773d619e051", + upd: { + StackObjectsCount: 1, + UnlimitedCount: true, + sptPresetId: "5841499024597759f825ff3e", + Repairable: { Durability: 40, MaxDurability: 90 }, + }, + }, { + _id: "7e8062d4bc57b56927c2d117", + _tpl: "6374a822e629013b9c0645c8", + parentId: "344d02bbf2102ce4e145bf35", + slotId: "mod_reciever", + }]; + const item = offerItems[0]; + + // Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock getFleaPriceForItem to bypass initial flea price fetch + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(0); + + // Mock the isPresetBaseClass method to return true for the item + vi.spyOn((ragfairPriceService as any).presetHelper, "isPresetBaseClass").mockReturnValue(true); + + // Mock the getWeaponPresetPrice method to return a specific preset price + vi.spyOn(ragfairPriceService, "getWeaponPresetPrice").mockReturnValue(mockPrice); + + // Mock the getOfferTypeRangeValues method to return a static minMax. + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Mock the getItemQualityModifier method to return 1 (no change) + const getItemQualityModifierSpy = vi.spyOn( + (ragfairPriceService as any).itemHelper, + "getItemQualityModifier", + ).mockReturnValue(mockDurabilityMulti); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency, item, offerItems); + + expect(getItemQualityModifierSpy).toHaveBeenCalled(); + expect(price).toBe(mockPrice * mockDurabilityMulti); + }); + + it("should adjust unreasonable prices based on ragfair config unreasonable price values", () => + { + const itemTemplateId = "5c052f6886f7746b1e3db148"; + const desiredCurrency = Money.ROUBLES; + const mockFleaPrice = 9999999; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + const mockBaseClassTemplateId = "57864a66245977548f04a81f"; + const mockUnreasonableModPrices = { + itemType: "Electronics", + enabled: true, + handbookPriceOverMultiplier: 11, + newPriceHandbookMultiplier: 11, + }; + + // Mock the Disable unreasonableModPrices config. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.unreasonableModPrices[mockBaseClassTemplateId] = + mockUnreasonableModPrices; + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock getFleaPriceForItem to bypass initial flea price fetch + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); + + // Mock isOfBaseclass to ensure that the item is always of the base class + const isOfBaseclassSpy = vi.spyOn((ragfairPriceService as any).itemHelper, "isOfBaseclass").mockReturnValue( + true, + ); + + // Mock the adjustUnreasonablePrice method to ensure it was called + const adjustUnreasonablePriceSpy = vi.spyOn(ragfairPriceService, "adjustUnreasonablePrice"); + + // Mock the getOfferTypeRangeValues method to return a static minMax + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(isOfBaseclassSpy).toHaveBeenCalled(); + expect(adjustUnreasonablePriceSpy).toHaveBeenCalled(); + expect(price).toBeLessThan(mockFleaPrice); + }); + + it("should vary the price within a random range", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.ROUBLES; + const mockFleaPrice = 10000; + const mockRandomiseOfferPrice = 9500; + + // Mock the configs to allow using trader price if higher. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock the getFleaPriceForItem method to return a static price + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockFleaPrice); + + // Mock the isPresetBaseClass method to return false + vi.spyOn((ragfairPriceService as any).presetHelper, "isPresetBaseClass").mockReturnValue(false); + + // Mock the randomiseOfferPrice method to have a simplified implementation + const randomiseOfferPriceSpy = vi.spyOn(ragfairPriceService, "randomiseOfferPrice").mockReturnValue( + mockRandomiseOfferPrice, + ); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(randomiseOfferPriceSpy).toHaveBeenCalled(); + expect(price).toBe(mockRandomiseOfferPrice); + }); + + it("should convert currency", () => + { + const itemTemplateId = "5e54f6af86f7742199090bf3"; + const desiredCurrency = Money.DOLLARS; + const mockRoublePrice = 10000; + const mockDollarPrice = 500; + const getOfferTypeRangeValues = { max: 1, min: 1 }; + + // Mock the configs to allow using trader price if higher. Disable other adjustments for isolation. + ragfairPriceService.ragfairConfig.dynamic.offerAdjustment.adjustPriceWhenBelowHandbookPrice = false; + ragfairPriceService.ragfairConfig.dynamic.useTraderPriceForOffersIfHigher = false; + ragfairPriceService.ragfairConfig.dynamic.itemPriceMultiplier[itemTemplateId] = null; + + // Mock the getFleaPriceForItem method to return a static price. + vi.spyOn(ragfairPriceService, "getFleaPriceForItem").mockReturnValue(mockRoublePrice); + + // Mock the getOfferTypeRangeValues method to return a static minMax + vi.spyOn(ragfairPriceService, "getOfferTypeRangeValues").mockReturnValue(getOfferTypeRangeValues); + + // Mock the fromRUB method to convert the price to a different currency + const fromRUBSpy = vi.spyOn((ragfairPriceService as any).handbookHelper, "fromRUB").mockReturnValue( + mockDollarPrice, + ); + + // Call the method. + const price = ragfairPriceService.getDynamicItemPrice(itemTemplateId, desiredCurrency); + + expect(fromRUBSpy).toHaveBeenCalledWith(mockRoublePrice, desiredCurrency); + expect(price).not.toBe(mockRoublePrice); + expect(price).toBe(mockDollarPrice); + }); + }); +});